Skip to content

Enhance accessibility for editor, modals, notifications, and menus - #969

Merged
giuscris merged 11 commits into
2.xfrom
a11y/panel-accessibility-fixes
Oct 24, 2026
Merged

giuscris merged 11 commits into
2.xfrom
a11y/panel-accessibility-fixes

Conversation

@giuscris

Copy link
Copy Markdown
Member

This pull request introduces significant accessibility improvements and keyboard navigation enhancements to form components and dropdowns in the panel UI. The changes ensure that interactive elements like dropdowns, select inputs, tags inputs, and notifications are more accessible to keyboard users and screen readers. The updates include adding appropriate ARIA attributes, improving focus management, and enhancing keyboard interactions.

Accessibility and ARIA Improvements:

Keyboard Navigation and Focus Management:

Other Accessibility Enhancements:

These improvements collectively make the panel's UI components more accessible and user-friendly for all users, especially those relying on assistive technologies.

giuscris and others added 11 commits October 21, 2026 19:56
The ProseMirror contenteditable had no role and was not tied to the
"Text:" label, so assistive technology did not announce it as an
editable multiline field. Expose role, aria-multiline, aria-labelledby,
aria-required and aria-readonly, and render an id on field labels in the
template so the editor can refer to its label.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Tab and Shift+Tab could leave an open modal and reach the page behind
it, and closing the modal left focus on <body>. Keep focus inside the
topmost open modal, redirect focus that escapes it, and return focus to
the element that opened it (the dropdown button when the trigger was a
menu item that is no longer visible).

Also close a modal on Escape only when it is open: every Modal instance
listened for Escape and called close() even when it was already closed,
running its before-close and close callbacks.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Notifications were added to a container created on demand, with no live
region semantics, so assistive technology did not announce them. They
also disappeared after the interval with no way to pause or dismiss
them from the keyboard.

- Render a persistent role="status" live region in the panel and login
  layouts and mark error and warning notifications with role="alert"
- Make notifications focusable: focus pauses the countdown and Escape,
  Enter or Space dismisses them
- Pass mouseleaveDelay to setTimeout, which was previously ignored so
  the notification was removed immediately on mouseleave
- Add a visible focus style

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Dropdown buttons did not expose their state, Escape did not close the
menus, arrow keys did nothing, clicking an open menu's button reopened
it instead of closing it, and two caret buttons had no accessible name.

- Set aria-controls and aria-expanded on dropdown buttons
- Open with ArrowDown/ArrowUp, move between items with arrows, Home and
  End, close with Escape returning focus to the button
- Toggle the menu when its button is clicked again
- Give the Save and Clear cache caret buttons a "More options" name
  (new panel.dropdown.moreOptions string in all languages)
- Expose aria-expanded/aria-controls on the mobile navigation toggle and
  close the sidebar with Escape, returning focus to the toggle

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Tabs could not be switched with the arrow keys, every tab was a tab
stop and tabs were not linked to their panels.

- Link each tab to its panel with aria-controls and a panel id
- Use a roving tabindex, rendered by the template, so only the active
  tab is in the tab order
- Support ArrowLeft, ArrowRight, Home and End to move and activate tabs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Markdown editor toolbar put every button in the tab order, so
reaching the text meant tabbing through all of them. Expose the toolbar
with role="toolbar" and a roving tabindex: it is one tab stop, and the
arrow keys, Home and End move between enabled buttons.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The remove control of each tag was an <i role="button"> with no
tabindex or accessible name, so it could not be reached or announced.
Use a real button with the accessible name "Remove: <tag>" (the tooltip
still shows "Remove"), restyled to look unchanged, and return focus to
the tag field after a keyboard removal.

Exclude the button from the Sortable drag handling (without cancelling
its mouse events) so that clicking it does not start a drag, and remove
the tooltips when a tag is removed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The select input replaces the native <select> with a text input and a
div list that had no roles or state, so assistive technology could not
tell what it was. Give the input role="combobox" with aria-expanded,
aria-controls and aria-activedescendant, and the list role="listbox",
named by the field label, with role="option" items, aria-selected and
aria-disabled.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The files list was built from plain divs, so column headers were not
associated with their cells. Expose it as an ARIA table (header row,
row group, rows, cells) without changing the layout, name it "Files",
and hide the decorative thumbnails from assistive technology with an
empty alt (or aria-hidden for videos), including those created when
files are uploaded.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Help text under a field was not associated with it, so it was not
announced when the field received focus. Give the description element
an id derived from the field name and reference it from the field
(including inputs that replace the original element: select, tags
and the Markdown editor).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tooltip of a dropdown button appeared over the first item of the
menu it had just opened (for example "Duplicate page"). Skip the
tooltip while the button's menu is expanded and remove tooltips when a
menu opens.

Also ignore mousemove events whose target is no longer in the document
and never show a tooltip for a removed element: the event is debounced,
so a tooltip could be created for a button removed by the click itself
and stay on screen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@giuscris giuscris added this to the 2.4.0 milestone Oct 24, 2026
@giuscris giuscris self-assigned this Oct 24, 2026
@giuscris
giuscris merged commit b986818 into 2.x Oct 24, 2026
2 checks passed
@giuscris
giuscris deleted the a11y/panel-accessibility-fixes branch October 24, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant