Keyboard and focus behavior
Designs predictable keyboard navigation and visible focus across widgets, overlays, deletion and route changes.
keyboard-focus-engineering
See how it helpsWhen is it useful?
Use when mouse-free navigation gets trapped or loses its current position.
What does it help you do?
- Keeps a logical tab order and avoids positive tabindex workarounds.
- Chooses the appropriate focus model for composite widgets.
- Restores meaningful focus after closing, deleting or navigating.
Try asking this
Fix a table-row action dialog so closing returns focus correctly, including when its row was deleted. Delete the originating row while its dialog is open. On closing, place focus on a meaningful remaining table control instead of the removed button.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Keyboard & Focus Engineering
Every interactive user journey must work end-to-end with a keyboard alone, with a clearly visible focus indicator, predictable tab order and deliberate focus restoration when overlays open, close or remove elements (WCAG 2.1.1, 2.1.2, 2.4.1, 2.4.3, 2.4.7, 2.4.11).
1. Tab Order & Tabindex Discipline
- DOM order drives focus order: arrange elements in the DOM so
TabandShift+Tabfollow the visual reading and task sequence (WCAG 2.4.3). Avoid CSS reordering (flex-direction: row-reverse, arbitraryorderor absolute positioning) that disconnects visual order from DOM tab order. - Tabindex rules:
- Prefer native focusable elements (
<button>,<a href>,<input>,<select>,<textarea>,<summary>). - Use
tabindex="0"only to add a custom widget's active entry point to the tab sequence or make a scrollable region keyboard-scrollable. - Use
tabindex="-1"for elements targeted by programmatic.focus()(headings, dialog containers or inactive items inside a roving-tabindex composite widget). - Never use positive
tabindex(tabindex="1",2, etc.) — it hijacks page-wide tab order.
- Prefer native focusable elements (
- Bypass blocks (WCAG 2.4.1): provide a working "Skip to main content" link as the first focusable item on shells with repeated navigation.
2. Composite Widgets: Roving Tabindex vs. aria-activedescendant
Complex widgets (tablists, menus, toolbars, radio groups, tree views, grids) must be a single tab stop:
Tab/Shift+Tabmoves into and out of the composite widget as a whole; Arrow keys,HomeandEndmove between items inside it.- Roving
tabindexpattern: give the active itemtabindex="0"and all sibling itemstabindex="-1". On arrow key press, movetabindex="0"to the target item, set the previous item to-1, and call.focus(). aria-activedescendantpattern (for comboboxes where focus stays on the text<input>): keep DOM focus on the<input>, updatearia-activedescendant="option-id"onArrowDown/ArrowUp, and scroll the active option into view (scrollIntoView({ block: 'nearest' })).
3. Focus Lifecycle in Overlays, Deletions & Route Changes
Plan where focus goes before, during and after every structural UI transition:
- Opening a modal dialog or drawer:
- Save
document.activeElementbefore opening. - Move initial focus inside the dialog (first primary field, primary action, or dialog heading/container with
tabindex="-1"). - Contain
Tab/Shift+Tabinside the modal (<dialog>.showModal(),inerton background siblings, or focus trap) and close onEscape.
- Save
- Closing a dialog or popover: restore focus to the opener, or to the nearest logical parent/trigger if the opener was unmounted.
- Deleting an item from a list or table: never let focus drop to
<body>. Move focus to the next sibling item, the previous item if the last one was deleted, or the list heading / "Add" button when empty. - Hidden and inert content: ensure elements inside closed drawers, inactive tabs or collapsed panels are unfocusable (
hidden,inertordisplay: none). Never place a focusable element inside anaria-hidden="true"container.
4. Visible Focus Indicators (WCAG 2.4.7 & 2.4.11)
- Use
:focus-visibleto render a high-contrast focus ring (at least2pxsolid outline withoutline-offsetand>= 3:1contrast). - Never use
outline: nonewithout a visible:focus-visiblereplacement that survivesforced-colors: activemode. - Prevent sticky headers or footers from obscuring focused elements (
scroll-margin-top/scroll-margin-bottom).
Included files 1
SKILL.md
About this skill package
keyboard-focus-engineering
keyboard-focus-engineering: Remove accessibility barriers through semantic markup, keyboard and screen-reader support, usable forms and regression checks.
Show less
keyboard-focus-engineering
keyboard-focus-engineering: Remove accessibility barriers through semantic markup, keyboard and screen-reader support, usable forms and regression checks.
Includes the complete skill and its supporting files (1 files). The exact authored scope is preserved below.
Original skill description (source language)
Use when engineering keyboard operability, tab order, roving tabindex, visible focus indicators and predictable focus lifecycle across dialogs, menus and dynamic views.
Install the skill, review its source and trust settings, then enable it for the relevant project or agent.
Requirements
- Orqestria installed on your computer.
