Skip to content

a11y(chat-sidebar): promote header icon-divs to keyboard-reachable buttons#305

Merged
mbektas merged 3 commits into
plmbr:mainfrom
pjdoland:a11y/sidebar-header-buttons
May 19, 2026
Merged

a11y(chat-sidebar): promote header icon-divs to keyboard-reachable buttons#305
mbektas merged 3 commits into
plmbr:mainfrom
pjdoland:a11y/sidebar-header-buttons

Conversation

@pjdoland
Copy link
Copy Markdown
Collaborator

Summary

The new-chat, resume-session, settings, and agent-mode tools icons in the chat sidebar were <div onClick> nodes with no tabIndex or keyboard handler. Keyboard-only users could not reach them at all, and screen readers announced them as generic group nodes. The resume-session and tools-button were additionally missing aria-labels, so they announced as empty even when navigation reached them.

Solution

Promote the four icons to <button type='button'> so they pick up native Enter/Space activation, the browser focus ring, and 'button' role announcement. Differentiate the title (longer descriptive hint) from the aria-label (short name) so NVDA/JAWS do not announce the same string twice. Add a :focus-visible outline in style/base.css using --jp-brand-color1, matching the seven existing focus-ring rules already in the stylesheet. The button.user-input-footer-button reset keeps the converted elements visually identical to the previous divs, with line-height: 1 added so the tools-button badge stays aligned.

Testing

  • jlpm tsc --noEmit clean. jlpm lint:check clean. jlpm jest 181 passed.
  • Galata regression: ui-tests/tests/chat-sidebar.spec.ts now tabs to the gear, presses Enter, and asserts the settings panel appears.
  • Manual Playwright walk: tab focus lands on each header icon, the brand-color focus ring is visible in light and dark themes, Enter activates the click handler.

Risks / follow-ups

  • Two cleaner refactors remain for separate PRs: a jsx-a11y ESLint rule to ban new <div onClick> (five other offenders survive elsewhere in src/), and a richer adoption of @jupyterlab/ui-components ToolbarButton. Both were deferred to keep this diff narrowly scoped.
  • No tracked GitHub issue; the audit identifiers (D155, D156) are internal.

pjdoland added 3 commits May 18, 2026 12:24
The new-chat, resume-session, settings, and tools-button icons in the
chat sidebar were <div onClick> nodes with no tabIndex or keyboard
handler. Keyboard users could not reach them at all and screen readers
announced them as generic group nodes. Promote to <button type='button'>
so they pick up native Enter/Space, the browser focus ring, and 'button'
role announcement.

Also fills in missing aria-labels (resume-session, tools-button) so the
icon-only buttons no longer announce as empty.

Adds a :focus-visible outline using --jp-brand-color1 so the converted
buttons surface a visible focus ring without firing on plain clicks.
Six-reviewer pass surfaced two convergent points: identical title and
aria-label strings get read twice by NVDA, and the focus-ring fallback
color drifts from the rest of base.css. Differentiate the strings (short
name in aria-label, longer description in title) and drop the literal
#2196f3 fallback. Also adds line-height: 1 to the button reset so the
tools-button badge stays aligned across the div-to-button conversion.
Sixth-reviewer pass flagged that the existing gear test pinned a title
attribute, not the underlying button semantics. Update the assertion to
target the new aria-label, then drive the gear via Tab/Enter so the test
fails if a future refactor regresses the div→button conversion.
@pjdoland pjdoland added the enhancement New feature or request label May 18, 2026
@pjdoland pjdoland added this to the 5.0.x milestone May 19, 2026
@mbektas mbektas merged commit eced276 into plmbr:main May 19, 2026
4 of 5 checks passed
pjdoland added a commit to pjdoland/notebook-intelligence that referenced this pull request May 22, 2026
Promotes the [Unreleased] CHANGELOG snapshot to [5.0.0] - 2026-05-22
and expands it to cover everything merged into upstream/main after
PR plmbr#287's docs refresh. Bumps package.json to 5.0.0.

CHANGELOG additions cover the post-plmbr#287 surface:

- Settings tabs: plugin marketplace picker (plmbr#284), plugin marketplace
  details + Update button (plmbr#303), per-workspace MCP disable (plmbr#286),
  JSON-paste path in Add MCP server (plmbr#285).
- Launchers: hide-with-policy (plmbr#288), brand icons for Codex / opencode
  (plmbr#325, plmbr#333), per-launch directory picker (plmbr#332).
- Chat sidebar and agentic UX: workspace @-mention in Claude mode
  (plmbr#327), reload-open-files-on-disk (plmbr#330), steered system prompt
  away from over-eager notebook creation (plmbr#336).
- Skills: multi-manifest support (plmbr#321), tracks-upstream for user-
  imported skills (plmbr#322), HTTP kill switch for the reconciler (plmbr#291).
- Accessibility: full sub-section covering plmbr#305-plmbr#320.
- Security: shell-tool sandbox (plmbr#290), Claude UI-bridge sandbox (plmbr#323),
  0o600 on encrypted token (plmbr#293), env-secret scrubbing (plmbr#295), MCP
  config shape validation (plmbr#299), XSS allowlist (plmbr#296), Copilot WS
  auth + origin (plmbr#301), GHE host detection (plmbr#292), fastmcp -> mcp SDK
  swap (plmbr#324).
- Fixed: session listing unification (plmbr#310), session preview unwrap
  (plmbr#331), down-area runtime throw (plmbr#330 follow-up), WS message-handler
  leak (plmbr#294).
- Removed: fastmcp dependency, history.jsonl session gate.

Adds a Migration note covering the five behavior changes operators
should review before upgrading from 4.x: fastmcp swap, path
sandboxes, history.jsonl gate removal, workspace @-mention pointer
shape, and the Copilot WebSocket auth/origin tightening.

Two reviewer rounds (six personas each) applied:
- Round 1 caught security overclaims (plmbr#293, plmbr#299, plmbr#323), the
  plmbr#284/plmbr#303 mis-attribution, missing migration note, 3 em dashes,
  and the stale `fastmcp==2.x.*` recommendation in the admin guide.
- Round 2 caught the missing plmbr#301 migration bullet, missing version-
  matrix 5.0.x row, missing README TOC entry, and a couple of style
  nits (sub-heading overpromise, orphan bullet).

Skipped (deferred to future PRs):
- README first-run tour mention.
- Admin guide HTTP kill-switch row in Failure-modes table.
- Terminal drag-drop trust-model precision update after plmbr#327.
- Cipher description nit in plmbr#293 (Fernet AES-128-CBC+HMAC, not
  AES-GCM).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants