# App handles both landscape and portrait orientations

- **Pattern:** `ab-001964` (`mobile-ux-patterns.layout-safe-areas.orientation-handling`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001964
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001964)

## Why it matters

Leaving `orientation` unset in `app.json` lets users rotate the device, but if layouts use column-only flex or fixed heights, the landscape view clips inputs and stacks the tab bar on top of content. Tablet users — who default to landscape — see a broken experience on first launch. Locking to portrait without justification blocks accessibility use cases like one-handed reading on a stand and fails Google Play's large-screen quality signals.

## Severity rationale

High because rotation bugs break entire classes of devices and hurt tablet and foldable quality rankings.

## Remediation

Either lock orientation intentionally in `app.json` or make every screen adapt via `useWindowDimensions`:

```tsx
import { useWindowDimensions } from 'react-native';
function Screen() {
  const { width, height } = useWindowDimensions();
  const isLandscape = width > height;
  return <View style={{ flex: 1, flexDirection: isLandscape ? 'row' : 'column' }}>{/* content */}</View>;
}
```

Test the primary flows in both orientations before each release.

## Detection

- **ID:** `orientation-handling`
- **Severity:** `high`
- **What to look for:** Check `app.json` for the `orientation` setting — quote the actual value found (e.g., `"default"`, `"portrait"`, `"landscape"`). If orientation is not locked, enumerate all screen components and check whether each uses `useWindowDimensions` or similar to adapt to orientation changes.
- **Pass criteria:** App supports both portrait and landscape (or explicitly locks to portrait-only in `app.json` with `"orientation": "portrait"` for a clear UX reason). At least 100% of screens reflow correctly on orientation change. No content is lost or hidden.
- **Fail criteria:** Orientation change breaks the layout, or app allows rotation (orientation not locked) but layout does not adapt, causing content to be cut off.
- **Skip (N/A) when:** App explicitly locks orientation to portrait-only in `app.json` with `"orientation": "portrait"` and the UX justification is clear (e.g., camera app, single-screen utility).
- **Detail on fail:** Quote the orientation config. `"App allows rotation but navigation stack and tab bar overlap in landscape on iPhone."` or `"Input fields and buttons are cut off when device rotates to landscape."`
- **Remediation:** Ensure layout reflows on orientation change. Use Dimensions API or useWindowDimensions to adapt layout:

  ```tsx
  // app.json - allow both orientations (default)
  {
    "orientation": "default"
  }

  // Component - adapt layout to orientation
  import { useWindowDimensions } from 'react-native';

  function Screen() {
    const { width, height } = useWindowDimensions();
    const isLandscape = width > height;

    return (
      <View style={{ flex: 1, flexDirection: isLandscape ? 'row' : 'column' }}>
        {/* Content */}
      </View>
    );
  }
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001964
