System Gesture Safe Zone

Status: ready

Intent

Drag interactions stay away from the screen edges the system uses. A control that has to be near an edge also has a way to use it without dragging.

Problem

A date scroller, a media scrubber or a sheet handle sits at the bottom edge. A horizontal drag switches apps, an upward drag goes Home, a downward drag triggers Reachability. Touch users hit it occasionally. Users with a tremor or using one hand hit it constantly. Switch Control can't drag at all.

Solution

Verdict: the bottom edge is shared with the system. Drag controls go above the safe area, and each one has buttons or a list next to it.

Why: distance from the edge cuts accidental system gestures for touch users. Buttons remove the drag for everyone else. Safe area padding alone does only the first.

Review shortcut for the bottom edge:

Fine:   a primary button with a 44 pt hit area
        a system tab bar
        passive content

Avoid:  a horizontal scroller
        drag to confirm
        swipe to dismiss as the only exit
        a scrubber without step buttons

Implementation

A date scroller:

HStack {
    Button("Previous day", systemImage: "chevron.left") { day = day.previous }
    DateScroller(selection: $day)
    Button("Next day", systemImage: "chevron.right") { day = day.next }
}
.labelStyle(.iconOnly)
.safeAreaPadding(.bottom)

The drag stays as a shortcut. The task doesn't depend on it.

A sheet handle isn't the only way to expand or close:

VStack {
    Capsule().frame(width: 36, height: 5)
        .accessibilityHidden(true)
    Button("Show details") { expand() }
    Button("Close") { close() }
}

Native .sheet with .presentationDetents already gives VoiceOver an adjustable handle and a close path. Custom sheets need the buttons.

Check

Profile:   touch, one hand, Reachability on
Task:      choose a day 3 days ahead
Expected:  no Reachability, no app switch, no Home
Profile:   VoiceOver
Task:      choose the next day
Expected:  the selected day says "Selected"
           Next day is reachable, no drag needed
Profile:   Larger Text AX3
Task:      use the bottom controls
Expected:  controls stay above the Home indicator, text isn't clipped

Pitfalls

  1. "Fixing" the conflict with .defersSystemGestures. It makes the user swipe twice to go Home.
  2. All controls behind a sheet handle.
  3. A haptic as the only sign that the drag worked.
  4. Assuming safe area padding makes a drag accessible.

WCAG mapping

  1. 2.5.1 Pointer Gestures: path gestures have an alternative.
  2. 2.5.7 Dragging Movements: a drag has an alternative.
  3. 2.5.8 Target Size (Minimum): edge controls are large enough.
  1. Edge Gesture Collision
  2. Swipe Trap
  3. Tiny Target
  4. Clipped Large Text
  1. Gesture Alternative
  2. Semantic Control
  3. List Alternative
  4. Platform Interaction Contract
  1. Chapter 3
  2. Chapter 7
  3. Chapter 17

Sources

  1. Apple Support: Reach the top of the iPhone screen with one hand
  2. Apple HIG: Gestures
  3. Apple HIG: Layout