Skip to content

Accessibility

Keyboard access and correct semantics are requirements here, not extras.

One tab stop, not one per row

The list uses a roving tabindex: the whole list is a single tab stop, and the arrow keys move within it. Tabbing through five hundred rows is the classic accessibility failure of a hand-rolled file browser.

The keyboard contract

KeyAction
Move between rows (and in grid view)
Home / EndFirst / last item
PageUp / PageDownMove by a page
EnterOpen the focused item
SpaceToggle selection
Shift + arrow, Shift + clickExtend the selection as a range
Ctrl / Cmd + ASelect everything visible
Ctrl / Cmd + clickToggle a single row
BackspaceGo up a folder
EscapeClear the selection
any letterJump to the next name starting with it

Type-ahead accumulates: typing d, a quickly jumps to date.pdf, while pausing starts a fresh search. Repeating a letter cycles through matches.

This mapping lives in createKeyboardNavigator() in @document-explorer/core and is shared by every renderer — the shortcuts cannot drift between React and Angular, because there is only one implementation of them.

Resizing without a mouse

Each column's resize handle is a focusable role="separator". and resize it by 16px, and Enter or Home resets it — so column widths are adjustable without a pointer, which a drag-only implementation would not be.

Roles

ViewSemantics
Listrole="grid" with row / columnheader / gridcell, and aria-sort on the sorted column
Gridrole="listbox" with options — a flat set of selectable cards is a listbox, and option is what carries aria-selected
Treerole="tree" with treeitems carrying aria-level and aria-expanded

Checkboxes sit inside a gridcell, never as bare children of a row. The grid's check indicator is decorative, because an option may not contain interactive descendants.

Announcements

A single live region reports the current folder and item count after navigation, and the result count after a search — so a screen-reader user hears what changed without focus being moved around.

Reduced motion

The already-minimal transitions are zeroed under prefers-reduced-motion: reduce.

Verification

Every view — list, grid, tree, plus the empty and error states — is checked with axe in the test suite, alongside manual keyboard-only passes. Automated checks catch roughly a third of real accessibility problems, so they run alongside manual testing rather than instead of it.

Released under the MIT License.