Review

Keyboard-sortable boarding pass sections

Airline ops asked for drag reorder of boarding-pass layout blocks (gate map, bag tags, lounge codes). Wires @dnd-kit sortable with pointer + keyboard sensors so agents can reorder without a mouse, using closestCenter collision and sortableKeyboardCoordinates.

dnd-kitTier 2a11ydnd-kitfrontend

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

components/boarding/PassSectionOrder.tsx+21-7
1818export function PassSectionOrder({ sections, onChange }: Props) {
19+ const sensors = useSensors(
20+ useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
21+ useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
22+ );
1923
24+ function handleDragEnd({ active, over }: DragEndEvent) {
25+ if (!over || active.id === over.id) return;
26+ const oldIndex = sections.findIndex((s) => s.id === active.id);
27+ const newIndex = sections.findIndex((s) => s.id === over.id);
28+ onChange(arrayMove(sections, oldIndex, newIndex));
29+ }
2030
21- return (
22- <ul className="section-list">
23- {sections.map((s) => (
24- <li key={s.id}>{s.label}</li>
25- ))}
26- </ul>
27- );
31+ return (
32+ <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
33+ <SortableContext items={sections.map((s) => s.id)} strategy={verticalListSortingStrategy}>
34+ <ul className="section-list" aria-label="Boarding pass section order">
35+ {sections.map((s) => (
36+ <SortableSection key={s.id} id={s.id} label={s.label} />
37+ ))}
38+ </ul>
39+ </SortableContext>
40+ </DndContext>
41+ );
2842}