almost there for function
This commit is contained in:
@@ -3,9 +3,11 @@ import { useBars } from "~/context/bars";
|
||||
import { onMount, createEffect } from "solid-js";
|
||||
|
||||
export function LeftBar() {
|
||||
const { setLeftBarSize, leftBarVisible } = useBars();
|
||||
const { setLeftBarSize, leftBarVisible, setLeftBarVisible } = useBars();
|
||||
let ref: HTMLDivElement | undefined;
|
||||
let actualWidth = 0;
|
||||
let touchStartX = 0;
|
||||
let touchStartY = 0;
|
||||
|
||||
onMount(() => {
|
||||
if (ref) {
|
||||
@@ -25,7 +27,72 @@ export function LeftBar() {
|
||||
});
|
||||
resizeObserver.observe(ref);
|
||||
|
||||
return () => resizeObserver.disconnect();
|
||||
// Swipe-to-dismiss gesture on sidebar itself (mobile only)
|
||||
const handleTouchStart = (e: TouchEvent) => {
|
||||
touchStartX = e.touches[0].clientX;
|
||||
touchStartY = e.touches[0].clientY;
|
||||
};
|
||||
|
||||
const handleTouchEnd = (e: TouchEvent) => {
|
||||
const isMobile = window.innerWidth < 768;
|
||||
if (!isMobile) return; // Only allow dismiss on mobile
|
||||
|
||||
const touchEndX = e.changedTouches[0].clientX;
|
||||
const touchEndY = e.changedTouches[0].clientY;
|
||||
const deltaX = touchEndX - touchStartX;
|
||||
const deltaY = touchEndY - touchStartY;
|
||||
|
||||
// Only trigger if horizontal swipe is dominant
|
||||
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
||||
// Swipe left to dismiss (at least 50px)
|
||||
if (deltaX < -50 && leftBarVisible()) {
|
||||
setLeftBarVisible(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Focus trap for accessibility on mobile
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const isMobile = window.innerWidth < 768;
|
||||
|
||||
if (!isMobile || !leftBarVisible()) return;
|
||||
|
||||
if (e.key === 'Tab') {
|
||||
const focusableElements = ref?.querySelectorAll(
|
||||
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
||||
);
|
||||
|
||||
if (!focusableElements || focusableElements.length === 0) return;
|
||||
|
||||
const firstElement = focusableElements[0] as HTMLElement;
|
||||
const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
|
||||
|
||||
if (e.shiftKey) {
|
||||
// Shift+Tab - going backwards
|
||||
if (document.activeElement === firstElement) {
|
||||
e.preventDefault();
|
||||
lastElement.focus();
|
||||
}
|
||||
} else {
|
||||
// Tab - going forwards
|
||||
if (document.activeElement === lastElement) {
|
||||
e.preventDefault();
|
||||
firstElement.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ref.addEventListener('touchstart', handleTouchStart, { passive: true });
|
||||
ref.addEventListener('touchend', handleTouchEnd, { passive: true });
|
||||
ref.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
ref?.removeEventListener('touchstart', handleTouchStart);
|
||||
ref?.removeEventListener('touchend', handleTouchEnd);
|
||||
ref?.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -34,6 +101,22 @@ export function LeftBar() {
|
||||
setLeftBarSize(leftBarVisible() ? actualWidth : 0);
|
||||
});
|
||||
|
||||
// Auto-focus first element when sidebar opens on mobile
|
||||
createEffect(() => {
|
||||
const isMobile = window.innerWidth < 768;
|
||||
|
||||
if (leftBarVisible() && isMobile && ref) {
|
||||
const firstFocusable = ref.querySelector(
|
||||
'a[href], button:not([disabled]), input:not([disabled])'
|
||||
) as HTMLElement;
|
||||
|
||||
if (firstFocusable) {
|
||||
// Small delay to ensure animation has started
|
||||
setTimeout(() => firstFocusable.focus(), 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<nav
|
||||
ref={ref}
|
||||
@@ -113,7 +196,9 @@ export function RightBar() {
|
||||
});
|
||||
resizeObserver.observe(ref);
|
||||
|
||||
return () => resizeObserver.disconnect();
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user