Role and semantics
Section titled “Role and semantics”AppShell gives the page its landmarks: the nav in the sidebar (“Main menu”), the header (banner) and main. The first focusable element is the “Skip to content” link, which goes to main; main carries tabIndex={-1} so focus can move there. Groups are role="group" tied to their headings. The current page carries aria-current="page". The collapse button is tied to the sidebar with aria-expanded and aria-controls. The drawer uses Base UI Dialog with role="dialog" and aria-modal. The indicator bar and icons carry aria-hidden.
Keyboard
Section titled “Keyboard”| Key | Behaviour |
|---|---|
| Tab | In order: the skip link, sidebar links, the collapse button, the top bar and the content. |
| Enter | Follows a link; the skip link moves focus to main. |
| Enter or Space | Runs a group heading and the collapse and menu buttons. |
| Escape | Closes the drawer. |
| Ctrl+B or Cmd+B | Narrows or widens the sidebar; below 1024 px opens or closes the drawer. The collapse button announces it with aria-keyshortcuts. |
Links show a 2 px color-focus-ring inner ring on keyboard focus only. When the drawer opens, focus moves into it and stays there; when it closes, focus returns to the menu button. Collapsing leaves focus on the button.
Screen reader output
Section titled “Screen reader output”| Example | Read as |
|---|---|
| Current page | “Home, link, current page” |
| Link with a badge | “Inbox 3, link” |
| Collapse button | “Collapse menu, button, expanded” |
| Drawer | “Main menu, dialog” |
Contrast
Section titled “Contrast”Labels keep at least 4.5:1 on the background, icons and the indicator bar at least 3:1. The current page is shown by the indicator bar and aria-current, not by colour alone.
WCAG 2.2
Section titled “WCAG 2.2”| Criterion | How AppShell meets it | What the product team must do |
|---|---|---|
| 1.3.1 Info and relationships | nav, header, main and group. |
Do not add another main to the page. |
| 2.4.1 Bypass blocks | The skip link. | Keep mainId unique. |
| 2.4.8 Location | aria-current="page" and the indicator. |
Always mark the current page. |
| 2.4.11 Focus not obscured (minimum) | The top bar is sticky but does not cover focus in the content. | Add scroll-padding when you add sticky parts in the content. |
| 2.5.8 Target size (minimum) | Links and the collapse button are 32 px. The edge rail is an extra pointer shortcut, hidden from screen readers and the tab order. | Give every link an icon for the narrow sidebar. |
| 4.1.2 Name, role, value | The collapse and menu buttons are named and carry their state. | Pass router links through render. |