Edge Gesture Collision
Status: ready
Symptom
A drag control sits on a screen edge that the system already uses. The user tries to scroll the app's control and triggers a system gesture instead, or the other way around.
Task: choose a delivery day
Control: horizontal date scroller at the bottom edge
Actual: a horizontal drag switches to the previous app,
a downward drag triggers Reachability
Result: the screen moves, the task context is gone
Where it shows up
Date scrollers at the bottom, sticky checkout bars, bottom sheet handles, bottom carousels, media scrubbers, custom tab bars, drag-to-confirm controls, web views that ignore the safe area.
Why it blocks the task
The bottom edge of a Face ID iPhone belongs to the system: swipe up for Home, swipe along the edge to switch apps, swipe down for Reachability. A drag control placed there competes with all three. Everyone hits it occasionally. A user with a tremor or using the phone with one hand hits it constantly. Switch Control and Voice Control can't drag the control at all.
The problem isn't Reachability. The problem is a custom gesture where the system's gestures already are.
Root cause
- The bottom edge was treated as free space.
- A drag is the only input for a primary choice.
- The safe area was respected visually but not for interaction.
- Nobody tested with one hand or with Reachability on.
Before
VStack {
Spacer()
DateScroller(days: days, selection: $day)
.frame(height: 48)
}
.ignoresSafeArea(edges: .bottom)
Fix
Verdict: move the drag area above the system gesture zone, and add Previous and Next buttons. For long ranges, add a list.
Why: distance from the edge reduces collisions for touch users. Buttons remove the drag for everyone who can't do it.
VStack {
Spacer()
HStack {
Button("Previous day", systemImage: "chevron.left") { day = day.previous }
DateScroller(days: days, selection: $day)
Button("Next day", systemImage: "chevron.right") { day = day.next }
}
.labelStyle(.iconOnly)
.padding(.horizontal)
.safeAreaPadding(.bottom)
}
For 30+ options, a "Choose date" button that opens a list or a DatePicker is faster than scrolling.
What we don't do
- We don't use
.defersSystemGestures(on: .bottom)in a regular app. It makes the user swipe twice to go Home. It's for games. - We don't fix it by making the scroller taller. It's still a drag at the edge.
Check
Profile: Reachability on, one hand
Task: choose a day 3 days ahead
Expected: the screen never moves down, the app never switches
Profile: Switch Control
Task: choose the next day
Expected: Previous and Next are scan targets, no drag needed
Profile: VoiceOver
Task: choose the next day
Expected: each date is named, the selected one says "Selected"
Next day is reachable
WCAG mapping
2.5.1 Pointer Gestures: path-based gestures have an alternative.2.5.7 Dragging Movements: a drag has an alternative without dragging.2.5.8 Target Size (Minimum): the buttons are large enough to hit.
Related patterns
- System Gesture Safe Zone
- Gesture Alternative
- Semantic Control
- Platform Interaction Contract
- List Alternative