a11y(chat-sidebar): promote header icon-divs to keyboard-reachable buttons#305
Merged
Merged
Conversation
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.
mbektas
approved these changes
May 19, 2026
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-visibleoutline instyle/base.cssusing--jp-brand-color1, matching the seven existing focus-ring rules already in the stylesheet. Thebutton.user-input-footer-buttonreset keeps the converted elements visually identical to the previous divs, withline-height: 1added so the tools-button badge stays aligned.Testing
jlpm tsc --noEmitclean.jlpm lint:checkclean.jlpm jest181 passed.ui-tests/tests/chat-sidebar.spec.tsnow tabs to the gear, presses Enter, and asserts the settings panel appears.Risks / follow-ups
jsx-a11yESLint rule to ban new<div onClick>(five other offenders survive elsewhere insrc/), and a richer adoption of@jupyterlab/ui-componentsToolbarButton. Both were deferred to keep this diff narrowly scoped.