Skip to content

Improve toolbar accessibility by following W3C APG Toolbar example#114

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

Improve toolbar accessibility by following W3C APG Toolbar example#114
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
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.

1 participant