fix(a11y): aria-modal, keyboard-operable ExpandingList, and focus rings [sc-217428] - #190
Open
mnutt wants to merge 3 commits into
Open
fix(a11y): aria-modal, keyboard-operable ExpandingList, and focus rings [sc-217428]#190mnutt wants to merge 3 commits into
mnutt wants to merge 3 commits into
Conversation
The dialog set aria-labelledby unconditionally, so a modal rendered without a title pointed at an element that never existed and had no accessible name. Only emit it when a title or header block is present; titleless modals can pass their own aria-label through ...attributes.
Six components dropped the outline unconditionally with no replacement indicator, at a specificity that beats a consuming app's :focus-visible baseline. Scope each reset to :focus:not(:focus-visible) so pointer focus stays clean and keyboard focus stays visible. Left fluid-input and fluid-text-input alone: they pair the reset with a designed focus state, and :focus-visible always matches text-entry elements so the rewrite would be a no-op there.
The header and toggle were click-only role="button" elements with no tabindex and no key handler, so the disclosure could not be operated by keyboard at all. The toggle is now a real button carrying aria-expanded and a visually-hidden label; the header drops role="button" and keeps its click handler as a mouse convenience, since the toggle usually renders inside it and making both interactive would nest a button in a button. Adds a storybook story and docs page, which the component never had.
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.
Upstream
@movable/fluidwork called for by canvas'spackages/canvas/docs/accessibility-plan.md. The plan names one item explicitly; auditing fluid against its own findings surfaced three more in this repo.Shortcut: [sc-217428]
FluidModal — WCAG 4.1.2 (A)
aria-modal="true", the plan's Phase 1 upstream follow-up. Covers the ~25 canvas modals that go throughFluidModalin one change.aria-labelledbywas emitted unconditionally, so a modal rendered without a title pointed at an element that never existed and had no accessible name. Now only emitted when a title or header block is present; titleless modals can passaria-labelthrough...attributes.ExpandingList — WCAG 2.1.1 + 4.1.2 (A)
Header and toggle were click-only
role="button"elements with notabindexand no key handler, so the disclosure could not be operated by keyboard at all. The toggle was also an unnamed SVG.<button type="button">witharia-expanded,disabled, anaria-hiddenchevron, and a visually-hidden name via@label(falls back to "Toggle section").role="button"and keeps its click handler as a mouse convenience. It deliberately does not become a button: every consumer nests the toggle inside the header, so that would nest a button in a button. There's atemplate-lint-disablerecording this..expanding-list-toggle— this is the only visual diff in the PR, so worth a look in Percy.Consumed by hogwarts (4 files, 6 instances). Canvas has its own fork of this component carrying the identical bug — tracked separately, not fixed here.
Focus visibility — WCAG 2.4.7 (AA)
Six components dropped the focus outline unconditionally with no replacement indicator, at a specificity that beats a consuming app's
:focus-visiblebaseline. This is the same failure canvas documented in finding F1, just sourced from fluid rather than@movable/tailwind-config.Scoped each reset to
:focus:not(:focus-visible)inclassy-select,input-fieldtextarea,on-off-switch,token-field,fluid-select__optionandfluid-checkbox. Pointer focus stays clean; keyboard focus stays visible. Browsers without:focus-visibledrop the whole rule and keep the default outline, so it fails safe.Deliberately left alone:
fluid-input,fluid-text-input,fluid-date-inputandpower-calendar-daysalso remove the outline, but each pairs it with a designed focus state (border-transparent→border-primary-darkplus a background change). That is a visible indicator, so it passes 2.4.7 — and:focus-visiblealways matches text-entry elements, so the rewrite would be a no-op there and would just stack a browser ring on the designed border on every click.Also
Storybook story and docs page for
ExpandingList, which had neither. Under Components → Fluid Lab → Expanding List.Testing
yarn lint-hbsandyarn lint-jsclean.yarn test: 88 tests, 87 pass, 1 pre-existing skip. New assertions coveraria-modal, the absentaria-labelledby, externalaria-label,aria-expandedflipping, and the toggle's accessible name.aria-expanded.Notes for reviewers
Consuming apps only pick this up on the next
release-itpublish. Canvas's plan checkboxes shouldn't be ticked until that lands.