Task #141: Make schedule row reordering work on iPad/touch devices
Original task: Fix iPad/touch drag-to-reorder of meeting rows in the
Executive Meetings daily schedule. Two root causes identified in the
spec:
1. dnd-kit was wired with PointerSensor only, so iOS Safari claimed
the touch as a vertical scroll before the 6px activation distance
was reached and the drag never started.
2. The grip handle was opacity-0 group-hover:opacity-70 — invisible
on touch devices that have no hover state, so iPad users had no
affordance to discover the drag.
Changes (all in artifacts/tx-os/src/pages/executive-meetings.tsx):
- Imported TouchSensor from @dnd-kit/core and added it to useSensors
with activationConstraint { delay: 200, tolerance: 8 } as the spec
explicitly required. PointerSensor (distance: 6) and KeyboardSensor
are unchanged.
- Updated the row grip button className with arbitrary Tailwind
media-query variants:
[@media(hover:none)_and_(pointer:coarse)]:opacity-40
[@media(hover:none)_and_(pointer:coarse)]:group-hover:opacity-40
[@media(hover:none)_and_(pointer:coarse)]:p-1.5
Desktop hover-only behaviour (opacity-0 → group-hover:opacity-70 →
hover:opacity-100) is preserved.
- Enlarged the GripVertical icon on touch (w-3.5/h-3.5 → w-4/h-4)
for a friendlier tap target.
- touch-action:none stays only on the grip button itself; the rest
of the row keeps default touch-action so vertical page scroll
outside the handle still works.
Verified manually on a 768x1024 hasTouch context:
- getComputedStyle(grip).opacity = "0.4"
- matchMedia('(hover:none) and (pointer:coarse)').matches = true
- touch-action on grip = "none"
- title cell (td:nth-child(2)) has no role and no aria-roledescription
— confirms drag listeners are still scoped to the grip only and
desktop click-to-edit on title/attendee/time cells is preserved.
Code review: PASS (architect).
Follow-up proposed: #149 — add a Playwright mobile/touch e2e test
covering long-press + drag of the grip on /executive-meetings.
Pre-existing test workflow failure (api-server tests + admin.tsx
codegen drift from earlier tasks) is unrelated and out of scope.
This commit is contained in:
@@ -1126,13 +1126,12 @@ function ScheduleSection({
|
|||||||
// vertical scroll before the finger has moved 6px, so the drag never
|
// vertical scroll before the finger has moved 6px, so the drag never
|
||||||
// activates. A long-press activation (delay+tolerance) lets the user
|
// activates. A long-press activation (delay+tolerance) lets the user
|
||||||
// press-and-hold the row's grip handle to start dragging while still
|
// press-and-hold the row's grip handle to start dragging while still
|
||||||
// leaving normal scrolling intact everywhere else on the row. Values
|
// leaving normal scrolling intact everywhere else on the row.
|
||||||
// match home.tsx (250ms / 5px) for a consistent feel across the OS.
|
|
||||||
// - KeyboardSensor for accessibility / keyboard reordering.
|
// - KeyboardSensor for accessibility / keyboard reordering.
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
|
useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
|
||||||
useSensor(TouchSensor, {
|
useSensor(TouchSensor, {
|
||||||
activationConstraint: { delay: 250, tolerance: 5 },
|
activationConstraint: { delay: 200, tolerance: 8 },
|
||||||
}),
|
}),
|
||||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user