How to build an accessible AppShell in React

The hidden nav uses transform/inline-size + inert (never display:none alone), so it stays in the a11y tree and is keyboard-reachable when open while leaving the tab order when closed; Escape and a scrim close the mobile drawer and focus returns to the toggle.

When to use a AppShell

When not to use it

Keyboard interactions

Role none, verified at WCAG 2.2-AA.

Common mistakes

Avoid: Animating the nav collapse with grid-template-columns: 1fr → 0fr on an auto-width sidebar

Prefer: AppShell animates an explicit inline-size (desktop) / transform (mobile drawer)

fr units have no definite size to resolve against on a shrink-to-fit flex item, so the track never animates

Example

<AppShell
  header={<ShellHeader brand={{ name: 'Acme' }} />}
  nav={<SideNav items={items} />}
>
  <h1>Dashboard</h1>
</AppShell>

See the full AppShell reference →