Skip to content

feat(desktop): keyboard shortcuts cheatsheet + a11y landmarks / focus#3125

Open
HUQIANTAO wants to merge 1 commit into
esengine:main-v2from
HUQIANTAO:feat/a11y-pass
Open

feat(desktop): keyboard shortcuts cheatsheet + a11y landmarks / focus#3125
HUQIANTAO wants to merge 1 commit into
esengine:main-v2from
HUQIANTAO:feat/a11y-pass

Conversation

@HUQIANTAO
Copy link
Copy Markdown
Contributor

Three related improvements to make the desktop app reachable from the keyboard and readable by screen readers.

  1. Shortcuts cheatsheet (press ?). New component renders a kbd+description table, grouped by section. Triggered by a '?' keypress from anywhere outside an editable element, or from a Help icon in the topbar. role=dialog + aria-modal; focus moves to close button on open, returns to trigger on close.
  2. ARIA landmarks + labels. App.tsx's // get role=banner / role=main / role=contentinfo, every icon-only topbar button gets an explicit aria-label, the error banner is role=alert, the composer textarea gets id+aria-label so a skip-link can target it.
  3. Skip-to-composer link. The first Tab from the topbar lands on a visually-hidden link that jumps focus to the textarea.
  4. Focus rings. :focus-visible paints a 2px accent outline with a 2px offset.

@github-actions github-actions Bot added the v2 Go rewrite (1.x) — main-v2 branch, active development label Jun 4, 2026
Three related improvements to make the desktop app reachable from the
keyboard and readable by screen readers.

1. Shortcuts cheatsheet (press ?). New component
   components/ShortcutsCheatsheet.tsx renders a single-column
   kbd+description table, grouped by section (Composer / Transcript /
   Global). Triggered by a '?' keypress from anywhere outside an
   editable element, or from a Help icon in the topbar. The dialog is
   role=dialog + aria-modal + aria-labelledby; on open, focus moves to
   the close button; on close, focus returns to the trigger.

2. ARIA landmarks + labels. App.tsx's <header>/<main>/<footer> get
   role=banner / role=main / role=contentinfo, and every icon-only
   topbar button gets an explicit aria-label. The error banner is
   role=alert. The composer textarea gets id=composer-input +
   aria-label so a skip-link can target it. The status-bar model name
   is aria-live=polite so a model switch is announced.

3. Skip-to-composer link. The first Tab from the topbar lands on a
   visually-hidden link that, when activated, jumps focus to the
   textarea. Saves keyboard-only users from tabbing through every
   topbar chip on every reload.

4. Focus rings. :focus-visible paints a 2px accent outline with a 2px
   offset across every interactive element. Disabled buttons skip the
   ring (it's not actionable). :focus (without -visible) is reset
   globally so the OS-default ring on mouse-clicks doesn't double up
   with the WebKitGTK focus rectangle on Linux.

i18n: en + zh both gain a 'shortcuts' section (title, close, open,
section.*, desc.*).
@HUQIANTAO HUQIANTAO requested a review from SivanCola as a code owner June 5, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant