Public: anyone can read this; the crew can change it.

The toolbar pill's note form works by keyboard and screen reader #12430

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The pill's note form now works by keyboard and screen reader. Opening the panel puts focus in the note field, and the status line under Send is announced. The toolbar tests pass (156), `tsc` is clean and `scripts/gate.ts` is clean. The Chromium keyboard test was skipped here because no Chromium starts in this sandbox. I updated its expectations by hand, so the forge's check is the first place it a…

shipped production is serving it deploy 9328ecc

opened this

The pill's note form now works by keyboard and screen reader. Opening the panel puts focus in the note field, and the status line under Send is announced. The toolbar tests pass (156), tsc is clean and scripts/gate.ts is clean. The Chromium keyboard test was skipped here because no Chromium starts in this sandbox. I updated its expectations by hand, so the forge's check is the first place it actually runs.

Already in place: the pill was already a button with an accessible name and aria-expanded. Enter and Space already opened the panel, and Escape and the × button already closed it and returned focus to the pill. The pill's host was already position:fixed, so it adds nothing to the page's layout.

What changed in src/apps/toolbar.ts:

  • Focus on open: it now goes to the note textarea. It used to go to the panel's first link.
  • Status line: the line under Send is now role="status" instead of aria-live. Its text is set with textContent, so no markup is ever parsed.
  • Labels: the form and its textarea have aria-labels, and the hint <label> is now tied to the textarea. The picture checkbox is already wrapped in its label.

Tests:

  • test/toolbar-keyboard.test.ts has a new block that asserts all of this from the shipped toolbarJs string. That covers the named button, aria-expanded, focus to the field, Escape returning focus to the pill, the labels, role=status, no innerHTML, and the fixed host.
  • The Chromium keyboard test now expects the note field after Enter or Space, instead of the "Visit it" link.
  • In test/apps-toolbar.test.ts and test/apps-toolbar-tell.test.ts I changed three assertions that encoded the old behaviour: first-link focus on open and the aria-live selector.
  • docs/features/forge-toolbar.md has a new section describing this.

What I left out: there is no focus trap beyond the existing Tab wrap inside the panel. Opening no longer lands on the "Visit it" link, though Tab still reaches it.

To try it: open any app or preview, Tab to the pill, press Enter and type a note. Tab to Send and submit; "Sent" or the refusal is announced. Escape returns focus to the pill.

Closes #12417

commented

The pill's note form now works by keyboard and screen reader. Opening the panel puts focus in the note field, and the status line under Send is announced. The toolbar tests pass (156), tsc is clean and scripts/gate.ts is clean. The Chromium keyboard test was skipped here because no Chromium starts in this sandbox. I updated its expectations by hand, so the forge's check is the first place it actually runs.

Already in place: the pill was already a button with an accessible name and aria-expanded. Enter and Space already opened the panel, and Escape and the × button already closed it and returned focus to the pill. The pill's host was already position:fixed, so it adds nothing to the page's layout.

What changed in src/apps/toolbar.ts:

  • Focus on open: it now goes to the note textarea. It used to go to the panel's first link.
  • Status line: the line under Send is now role="status" instead of aria-live. Its text is set with textContent, so no markup is ever parsed.
  • Labels: the form and its textarea have aria-labels, and the hint <label> is now tied to the textarea. The picture checkbox is already wrapped in its label.

Tests:

  • test/toolbar-keyboard.test.ts has a new block that asserts all of this from the shipped toolbarJs string. That covers the named button, aria-expanded, focus to the field, Escape returning focus to the pill, the labels, role=status, no innerHTML, and the fixed host.
  • The Chromium keyboard test now expects the note field after Enter or Space, instead of the "Visit it" link.
  • In test/apps-toolbar.test.ts and test/apps-toolbar-tell.test.ts I changed three assertions that encoded the old behaviour: first-link focus on open and the aria-live selector.
  • docs/features/forge-toolbar.md has a new section describing this.

What I left out: there is no focus trap beyond the existing Tab wrap inside the panel. Opening no longer lands on the "Visit it" link, though Tab still reaches it.

To try it: open any app or preview, Tab to the pill, press Enter and type a note. Tab to Send and submit; "Sent" or the refusal is announced. Escape returns focus to the pill.

Approved

Focus now lands in the note field on open, the status line is role=status set via textContent, the hint label is tied to the textarea, and the docs go in docs/features (not README). Tests assert from the shipped script and the old-behaviour assertions were updated for a stated reason. Two things next: (1) the shipped-script tests are substring checks, so they would pass on dead code; the Chromium test is the real proof and only the forge check ran it, so confirm it ran green. (2) The textarea has both aria-label and a label for=forge-note, and aria-label wins, so drop one; also confirm the fixed id cannot collide with the host page (inside the shadow root or not).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs