Skip to content

Improve toolbar accessibility by following W3C APG Toolbar example - #114

Closed
riasvdv wants to merge 1 commit into
panphora:mainfrom
riasvdv:improve-toolbar-accessibility
Closed

riasvdv wants to merge 1 commit into
panphora:mainfrom
riasvdv:improve-toolbar-accessibility

Conversation

@riasvdv

@riasvdv riasvdv commented Jun 10, 2026

Copy link
Copy Markdown

This improves the toolbar accessibility by following the W3C APG Toolbar example and standards.

  • Gives the toolbar a roving tabindex
  • Left / Right / Home / End toolbar navigation
  • Toolbar focus is remembered between edits and going back to the toolbar

Summary by cubic

Makes the formatting toolbar follow the W3C APG Toolbar pattern for better accessibility. Adds predictable keyboard navigation, accurate pressed states, and stable focus between the editor and toolbar.

  • New Features
    • Roving tabindex across toolbar items with Left/Right/Home/End navigation; focus is remembered when returning from the toolbar.
    • ARIA: toolbar now links to the textarea via aria-controls; auto-ids are created when missing; toggle buttons update aria-pressed.
    • Button API: added isActive to set pressed state and the active class, plus optional actionId for canonical actions.
    • Docs and tests: README documents isActive; added test/toolbar.test.js; npm test includes the new suite.

Written for commit 80b9f7a. Summary will update on new commits.

Review in cubic

@riasvdv riasvdv left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments to explain some of the decisions made

Comment thread src/overtype.js
Comment on lines +451 to +460
/**
* Ensure the textarea can be referenced by aria-controls
* @private
*/
_ensureTextareaId() {
if (!this.textarea.id) {
this.textarea.id = `overtype-${this.instanceId}-input`;
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed for the toolbar to correctly be able to reference the instance with aria-controls

Comment thread src/toolbar.js
Comment on lines -247 to -279
let isActive = false;

switch(name) {
case 'bold':
isActive = activeFormats.includes('bold');
break;
case 'italic':
isActive = activeFormats.includes('italic');
break;
case 'code':
isActive = false; // Disabled: unreliable in code blocks
break;
case 'bulletList':
isActive = activeFormats.includes('bullet-list');
break;
case 'orderedList':
isActive = activeFormats.includes('numbered-list');
break;
case 'taskList':
isActive = activeFormats.includes('task-list');
break;
case 'quote':
isActive = activeFormats.includes('quote');
break;
case 'h1':
isActive = activeFormats.includes('header');
break;
case 'h2':
isActive = activeFormats.includes('header-2');
break;
case 'h3':
isActive = activeFormats.includes('header-3');
break;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not every button can be toggled, which was causing aria-pressed issues, this moves the logic into the button itself so custom buttons can also determine if they're active

Comment thread src/toolbar.js
@@ -139,14 +294,20 @@ export class Toolbar {
* Not exposed to users - viewMode button behavior is fixed
*/
toggleViewModeDropdown(button) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of viewMode dropdown specific logic in the toolbar file now. I'd suggest maybe moving all the implementation to a separate file at some point

@riasvdv
riasvdv marked this pull request as ready for review June 10, 2026 20:08
panphora added a commit that referenced this pull request Jun 18, 2026
…JSON, Safari fix

Bundles several community fixes and features into one minor release.

Added:
- transformLinkUrl option for the link tooltip (#85)
- Tab/Shift+Tab indent on selection, Cmd/Ctrl+] and Cmd/Ctrl+[ shortcuts, and public indentSelection()/outdentSelection() (#115)
- JSON-aware data-ot-* parsing and data-ot-textarea-* shortcuts so textareaProps (e.g. required) works from HTML (#112)
- Autocomplete recipe for @mention/#issue popups in docs/AUTOCOMPLETE.md (#96)

Fixed:
- Keyboard focus trap: collapsed Tab/Shift+Tab now uses native focus traversal so keyboard users can leave the editor, WCAG 2.1.2 (#113)
- Toolbar accessibility following the W3C APG Toolbar pattern: roving tabindex, aria-pressed on toggle buttons only, aria-controls, menu-button semantics (#114)
- Safari: re-flow the textarea after edits so caret/wrap stop desyncing from the overlay (#116)
- exports.browser pointed to a non-existent file (overtype.iife.min.js); now overtype.min.js
- Link tooltip sanitizes the URL before opening, closing a latent javascript: vector

dist/ rebuilt from source. Full test suite passes, including the new keyboard-accessibility and toolbar a11y suites.

Claude-Session: https://claude.ai/code/session_013uxKmCY2gqHzfV2jBQq27J
@panphora

panphora commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Landed in v2.4.0 (22742e0). I integrated your toolbar accessibility work, rebuilt dist/ from source, and shipped it as a combined accessibility release alongside #115: roving tabindex, aria-pressed on toggle buttons only, aria-controls linking the toolbar to the textarea, and full menu-button semantics for the view-mode dropdown.

Thank you for the thorough, well-tested PR! Closing manually since it landed via a rebuilt combined commit rather than a direct GitHub merge.

@panphora panphora closed this Jun 18, 2026
panphora added a commit that referenced this pull request Jun 19, 2026
…JSON, Safari fix

Bundles several community fixes and features into one minor release.

Added:
- transformLinkUrl option for the link tooltip (#85)
- Tab/Shift+Tab indent on selection, Cmd/Ctrl+] and Cmd/Ctrl+[ shortcuts, and public indentSelection()/outdentSelection() (#115)
- JSON-aware data-ot-* parsing and data-ot-textarea-* shortcuts so textareaProps (e.g. required) works from HTML (#112)
- Autocomplete recipe for @mention/#issue popups in docs/AUTOCOMPLETE.md (#96)

Fixed:
- Keyboard focus trap: collapsed Tab/Shift+Tab now uses native focus traversal so keyboard users can leave the editor, WCAG 2.1.2 (#113)
- Toolbar accessibility following the W3C APG Toolbar pattern: roving tabindex, aria-pressed on toggle buttons only, aria-controls, menu-button semantics (#114)
- Safari: re-flow the textarea after edits so caret/wrap stop desyncing from the overlay (#116)
- exports.browser pointed to a non-existent file (overtype.iife.min.js); now overtype.min.js
- Link tooltip sanitizes the URL before opening, closing a latent javascript: vector

dist/ rebuilt from source. Full test suite passes, including the new keyboard-accessibility and toolbar a11y suites.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants