Skip to content

feat(a11y): keyboard accessibility & focus management for the answer bubble - #153

Open
zhongnansu wants to merge 1 commit into
mainfrom
fix/bubble-a11y
Open

feat(a11y): keyboard accessibility & focus management for the answer bubble#153
zhongnansu wants to merge 1 commit into
mainfrom
fix/bubble-a11y

Conversation

@zhongnansu

Copy link
Copy Markdown
Member

The inline answer bubble (Shadow DOM) was effectively unusable without a mouse — no keyboard navigation, no screen-reader labels, no visible focus rings, and preset chips responded only to clicks.

Changes (src/content/bubble/core.js, styles.js)

  • Focus on open moves to the most relevant control — preset/custom input, or the follow-up input in response mode. Shadow root uses delegatesFocus: true (matches the existing trigger toolbar).
  • Focus trap: Tab / Shift+Tab cycle within the bubble's focusable controls instead of leaking to the page; Escape still closes.
  • Keyboard-operable preset chips: role="button", tabindex="0", Enter/Space activate via the same path as click.
  • Visible focus indicators: :focus-visible outlines (2px #7c3aed) on chips, pin/close/history/send buttons and inputs. Copy button now appears on keyboard focus, not only hover.
  • ARIA labels on icon-only buttons (Close chat, Pin chat bubble, View history, send) — aria-label, since screen readers ignore title.

Testing

  • tests/bubble.test.js passes, with added tests for chip Enter/Space activation, focus-moves-to-input on open, and the Tab/Shift+Tab focus trap.

Behavioral/a11y change only — no visual redesign, so the demo-GIF/visual-verification step was skipped per maintainer direction.

🤖 Generated with Claude Code

The Shadow DOM answer bubble was effectively mouse-only.

- Move focus into the relevant input when the bubble opens (preset/custom
  input, or follow-up input in response mode); delegatesFocus on the root.
- Focus trap: Tab/Shift+Tab cycle within the bubble; Escape still closes.
- Preset chips are keyboard-operable: role=button, tabindex=0, Enter/Space
  run the same path as click.
- Visible :focus-visible outlines (2px #7c3aed) on chips, pin/close/history/
  send buttons and inputs; copy button shows on focus, not only hover.
- aria-label on icon-only buttons (screen readers ignore title).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the tests Changes to test files label May 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📦 PR Preview — Ask AI Extension

Version: 1.2.1
Zip size: 343.2 KB

⬇️ Download artifact


Permissions

No permission changes detected. ✅


Preview Checklist

Before merging, manually test with the artifact above:

  • Load unpacked extension in chrome://extensions (developer mode)
  • Select text on any webpage and verify the trigger button appears
  • Click the trigger button and confirm the popup renders correctly
  • Right-click selected text and verify context menu items are present
  • Open a CSP-restricted page (e.g. chrome://extensions) and verify fallback works
  • Check the DevTools console for errors

Updated by PR Preview Bot — workflow run

@github-actions

Copy link
Copy Markdown
Contributor

📊 Code Coverage Report

File Coverage Status
proxy/src/index.js 98.0% 🟢
proxy/src/openai.js 100.0% 🟢
proxy/src/rate-limit.js 100.0% 🟢
proxy/src/validate.js 95.3% 🟢
src/options.js 97.6% 🟢
src/popup.js 100.0% 🟢
src/background/index.js 83.2% 🟢
src/content/api.js 88.2% 🟢
src/content/detection.js 99.3% 🟢
src/content/history.js 86.1% 🟢
src/content/image-capture.js 91.6% 🟢
src/content/presets.js 100.0% 🟢
src/content/prompt.js 97.4% 🟢
src/content/autosuggest/context.js 100.0% 🟢
src/content/autosuggest/debounce.js 100.0% 🟢
src/content/autosuggest/ghost-text.js 100.0% 🟢
src/content/autosuggest/index.js 75.9% 🔴
src/content/autosuggest/styles.js 100.0% 🟢
src/content/bubble/core.js 91.1% 🟢
src/content/bubble/history.js 85.3% 🟢
src/content/bubble/markdown.js 96.0% 🟢
src/content/bubble/stream.js 97.0% 🟢
src/content/bubble/styles.js 100.0% 🟢
src/content/shared/constants.js 100.0% 🟢
src/content/shared/dom-utils.js 100.0% 🟢
src/content/shared/preset-usage.js 91.8% 🟢
src/content/shared/state.js 100.0% 🟢
src/content/trigger/button.js 92.6% 🟢
src/content/trigger/progress-ring.js 100.0% 🟢
src/content/trigger/screenshot.js 98.6% 🟢
src/content/trigger/selection.js 72.8% 🔴
src/content/trigger/styles.js 100.0% 🟢
src/shared/autosuggest-limits.js 100.0% 🟢
src/shared/brand.js 100.0% 🟢
Overall 94.3% 🟢 PASS

Threshold: 80%

✅ Coverage meets the minimum threshold.


Updated by Code Coverage workflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Changes to test files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant