Improve drag/swipe handling and Features page UX

- SwipeTabs: Delay pointer capture until drag starts for better tap detection
- Features: Only allow drag via handle dots, not entire card
- Features: Smart hasOrderChanges - hide buttons when order returns to initial
- Features: Don't apply dragging style until movement exceeds threshold
- ThemeSettings: Add role="button" for accessibility on all option cards
- Sidebar: Light theme active menu item styling improvements
- Layout: Tab bar translucency and blur effects

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-23 03:19:40 +01:00
parent 75cb687500
commit 9e3556322f
6 changed files with 130 additions and 50 deletions

View File

@@ -95,8 +95,9 @@ export function SwipeTabs<T extends string | number>({
const shouldIgnoreSwipe = useCallback((target: EventTarget | null) => {
const element = resolveSwipeTarget(target);
if (!element) return false;
// Don't ignore role="button" - we handle tap vs swipe via delayed pointer capture
if (element.closest(
'[data-swipe-ignore="true"], button, a, input, select, textarea, [role="button"], [role="link"], [role="switch"], [contenteditable="true"]'
'[data-swipe-ignore="true"], button, a, input, select, textarea, [role="link"], [role="switch"], [contenteditable="true"]'
)) {
return true;
}
@@ -287,6 +288,14 @@ export function SwipeTabs<T extends string | number>({
state.isDragging = true;
isDraggingRef.current = true;
setDraggingClass(true);
// Capture pointer now that drag has started
if (state.pointerId !== null && containerRef.current?.setPointerCapture) {
try {
containerRef.current.setPointerCapture(state.pointerId);
} catch {
// Ignore capture failures
}
}
}
if (!state.isDragging) return;
@@ -371,13 +380,8 @@ export function SwipeTabs<T extends string | number>({
if (event.pointerType === 'mouse' && event.button !== 0) return;
if (dragRef.current.isActive) return;
startDrag(event.clientX, event.clientY, event.pointerId, null);
if (containerRef.current?.setPointerCapture) {
try {
containerRef.current.setPointerCapture(event.pointerId);
} catch {
// Ignore pointer capture failures.
}
}
// Don't capture pointer immediately - let taps work normally
// Capture will happen in updateDrag when drag actually starts
};
const handlePointerMove = (event: PointerEvent<HTMLDivElement>) => {