Skip to content

A11y: Surface required args and keyboard-reachable Setup controls in ArgsTable - #35306

Merged
Sidnioulz merged 4 commits into
nextfrom
sidnioulz/argstable-required-hovered
Jun 29, 2026
Merged

Sidnioulz merged 4 commits into
nextfrom
sidnioulz/argstable-required-hovered

Conversation

@Sidnioulz

@Sidnioulz Sidnioulz commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

What I did

These two changes were originally developed alongside the lang-attribute work in #35207 but are unrelated, so they have been split out into this dedicated PR (and reverted on #35207).

Both are accessibility improvements to the docs ArgsTable controls:

  • Expose required args to assistive tech. The required flag from an arg's type is now threaded from ArgRow → ArgControl → each control, which renders aria-required on its underlying input (Boolean, Color, Date, Files, Number, Object, Range, Text, Select single/multi, and the Checkbox/Radio fieldsets). The required prop is added to the shared ControlProps type.
  • Keep the "Setup controls" link reachable for keyboard users. Previously the link for args without a usable control only appeared on mouse :hover (driven by JS onMouseEnter/isHovered). It now renders both the link and a placeholder dash at all times, and the row toggles their visibility purely via CSS on :hover, :focus-within (StyledTr), so keyboard focus reveals the link too. The aria-hidden attribute is added to the decorative required * marker.

Note

This was mostly hand-coded, but split from another branch by AI. PR description is AI.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

  1. Run a sandbox, e.g. yarn task --task sandbox --start-from auto --template react-vite/default-ts
  2. Open Storybook and view a story with a Controls/ArgsTable panel where some args are marked required and some args have no usable control.
  3. Required args: inspect the control inputs and confirm aria-required="true" is present on the input/fieldset.
  4. Keyboard reachability: with the mouse away, Tab through an arg row that has no control and confirm the "Setup controls" link becomes visible and focusable (it should also still appear on mouse hover).

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Declare whether manual QA will be needed for this PR during the next release, through qa:needed or qa:skip

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features
    • Improved required-field support across form controls: required state is now reflected via aria-required and clearer screen-reader labeling (including required markers in option legends).
  • Bug Fixes
    • Improved the “Setup controls” vs placeholder behavior for both hover and keyboard focus by switching to CSS-based visibility.
    • Updated required indicator rendering in the args table to stay consistent, including when controls are unavailable.

@Sidnioulz Sidnioulz added bug ci:normal Run our default set of CI jobs (choose this for most PRs). qa:skip Pull Requests that do not need any QA. (e.g. documentation) labels Jun 26, 2026
@Sidnioulz Sidnioulz self-assigned this Jun 26, 2026
Sidnioulz added a commit that referenced this pull request Jun 26, 2026
These changes — `aria-required` on controls and the hover/focus rework of
the "Setup controls" link — are unrelated to the `lang` attribute work in
this PR and have been split out into #35306.

This reverts commits 6a38434 and 25385d3.
@Sidnioulz
Sidnioulz requested a review from ghengeveld June 26, 2026 14:28
@Sidnioulz
Sidnioulz marked this pull request as ready for review June 26, 2026 14:29
Copilot AI review requested due to automatic review settings June 26, 2026 14:29

This comment was marked as spam.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: edd14f52-e1b3-4bf7-912e-adde0f22faf0

📥 Commits

Reviewing files that changed from the base of the PR and between 461b9ba and dee640f.

📒 Files selected for processing (17)
  • code/addons/docs/src/blocks/components/ArgsTable/ArgControl.tsx
  • code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx
  • code/addons/docs/src/blocks/controls/Boolean.tsx
  • code/addons/docs/src/blocks/controls/Color.tsx
  • code/addons/docs/src/blocks/controls/Date.tsx
  • code/addons/docs/src/blocks/controls/Files.tsx
  • code/addons/docs/src/blocks/controls/Number.tsx
  • code/addons/docs/src/blocks/controls/Object.tsx
  • code/addons/docs/src/blocks/controls/Range.tsx
  • code/addons/docs/src/blocks/controls/Text.tsx
  • code/addons/docs/src/blocks/controls/options/Checkbox.tsx
  • code/addons/docs/src/blocks/controls/options/Radio.tsx
  • code/addons/docs/src/blocks/controls/options/Select.tsx
  • code/addons/docs/src/blocks/controls/types.ts
  • code/core/src/manager/globals/exports.ts
  • code/core/src/theming/global.ts
  • code/core/src/theming/index.ts
✅ Files skipped from review due to trivial changes (2)
  • code/core/src/manager/globals/exports.ts
  • code/addons/docs/src/blocks/controls/types.ts
🚧 Files skipped from review as they are similar to previous changes (12)
  • code/addons/docs/src/blocks/controls/Boolean.tsx
  • code/addons/docs/src/blocks/controls/Files.tsx
  • code/addons/docs/src/blocks/controls/Number.tsx
  • code/addons/docs/src/blocks/controls/options/Radio.tsx
  • code/addons/docs/src/blocks/controls/Object.tsx
  • code/addons/docs/src/blocks/controls/Text.tsx
  • code/addons/docs/src/blocks/controls/options/Select.tsx
  • code/addons/docs/src/blocks/controls/Range.tsx
  • code/addons/docs/src/blocks/controls/options/Checkbox.tsx
  • code/addons/docs/src/blocks/controls/Color.tsx
  • code/addons/docs/src/blocks/controls/Date.tsx
  • code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx

📝 Walkthrough

Walkthrough

The docs addon threads a new required prop through control props and the args table. Several controls now expose required state via ARIA, option legends add required text, and the args table switches setup-link visibility to CSS-driven row behavior.

Changes

Required state propagation

Layer / File(s) Summary
SR-only theming support
code/core/src/theming/global.ts, code/core/src/theming/index.ts, code/core/src/manager/globals/exports.ts
srOnlyUnsetStyles is added to theming globals and re-exported through the theming package and globals map.
Args table required wiring
code/addons/docs/src/blocks/components/ArgsTable/ArgControl.tsx, code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx
ArgControl and ArgRow switch from hover state to required state, change setup-control visibility behavior, and pass required into the selected control.
Control accessibility updates
code/addons/docs/src/blocks/controls/types.ts, code/addons/docs/src/blocks/controls/Boolean.tsx, code/addons/docs/src/blocks/controls/Color.tsx, code/addons/docs/src/blocks/controls/Date.tsx, code/addons/docs/src/blocks/controls/Files.tsx, code/addons/docs/src/blocks/controls/Number.tsx, code/addons/docs/src/blocks/controls/Object.tsx, code/addons/docs/src/blocks/controls/Range.tsx, code/addons/docs/src/blocks/controls/Text.tsx, code/addons/docs/src/blocks/controls/options/Checkbox.tsx, code/addons/docs/src/blocks/controls/options/Radio.tsx, code/addons/docs/src/blocks/controls/options/Select.tsx
ControlProps<T> gains required, and the boolean, color, date, files, number, object, range, text, checkbox, radio, and select controls use it for aria-required or required legend text.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/addons/docs/src/blocks/controls/Boolean.tsx (1)

136-147: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the required cue in the unset-state fallback.

When value === undefined, this returns the "Set boolean" button and never uses required, so a required arg that starts unset is still silent to assistive tech. The same setter-button pattern exists in the other controls that gate rendering on an initial value, so this accessibility gap remains on the most important path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/addons/docs/src/blocks/controls/Boolean.tsx` around lines 136 - 147, The
unset-state fallback in Boolean’s control renderer drops the required cue, so a
required arg that starts undefined is announced like a normal optional setter.
Update the `value === undefined` branch in `Boolean` to carry through the
`required` state to the fallback `Button` (and any similar setter-button
branches in related controls), preserving the accessibility cue while keeping
the existing `getControlSetterButtonId` and `onSetFalse` behavior intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@code/addons/docs/src/blocks/components/ArgsTable/ArgControl.tsx`:
- Around line 30-37: The default `display: none` on `SetupControlsLink` makes
the `Link` unreachable for keyboard focus, so `StyledTr` in `ArgRow` can’t ever
trigger `:focus-within` from the keyboard. Change `SetupControlsLink` to use a
visually-hidden-but-focusable style instead of removing it from the
accessibility tree, and update the hover/focus rules in `ArgRow`’s `StyledTr` to
restore the link to a visible state without relying on `display`. Keep
`NoControlPlaceholder` as the fallback for rows without controls.

In `@code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx`:
- Line 151: The ArgControl render in ArgRow is passing a possibly undefined
required value through isRequired, and the cast to ArgControlProps is hiding the
type mismatch. Update the ArgRow/ArgControlProps usage so isRequired is always a
boolean, coercing row.type?.required to a boolean before passing it into
ArgControl and avoiding the unsafe cast where possible.

In `@code/addons/docs/src/blocks/controls/options/Radio.tsx`:
- Around line 77-82: The radio group is only announcing “required” in the legend
text, but the group itself is not marked required for assistive tech. Update the
Radio component around Wrapper and the legend so the actual radio group gets a
programmatic required state, using the existing required prop rather than
relying on the visible label text alone.

---

Outside diff comments:
In `@code/addons/docs/src/blocks/controls/Boolean.tsx`:
- Around line 136-147: The unset-state fallback in Boolean’s control renderer
drops the required cue, so a required arg that starts undefined is announced
like a normal optional setter. Update the `value === undefined` branch in
`Boolean` to carry through the `required` state to the fallback `Button` (and
any similar setter-button branches in related controls), preserving the
accessibility cue while keeping the existing `getControlSetterButtonId` and
`onSetFalse` behavior intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 166a50be-e116-4533-a6f2-3f89d7ac48dc

📥 Commits

Reviewing files that changed from the base of the PR and between 1e51b9a and bd6eb70.

📒 Files selected for processing (14)
  • code/addons/docs/src/blocks/components/ArgsTable/ArgControl.tsx
  • code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx
  • code/addons/docs/src/blocks/controls/Boolean.tsx
  • code/addons/docs/src/blocks/controls/Color.tsx
  • code/addons/docs/src/blocks/controls/Date.tsx
  • code/addons/docs/src/blocks/controls/Files.tsx
  • code/addons/docs/src/blocks/controls/Number.tsx
  • code/addons/docs/src/blocks/controls/Object.tsx
  • code/addons/docs/src/blocks/controls/Range.tsx
  • code/addons/docs/src/blocks/controls/Text.tsx
  • code/addons/docs/src/blocks/controls/options/Checkbox.tsx
  • code/addons/docs/src/blocks/controls/options/Radio.tsx
  • code/addons/docs/src/blocks/controls/options/Select.tsx
  • code/addons/docs/src/blocks/controls/types.ts

Comment thread code/addons/docs/src/blocks/components/ArgsTable/ArgControl.tsx Outdated
Comment thread code/addons/docs/src/blocks/components/ArgsTable/ArgRow.tsx Outdated
Comment thread code/addons/docs/src/blocks/controls/options/Radio.tsx
Sidnioulz added a commit that referenced this pull request Jun 29, 2026
These changes — `aria-required` on controls and the hover/focus rework of
the "Setup controls" link — are unrelated to the `lang` attribute work in
this PR and have been split out into #35306.

This reverts commits 6a38434 and 25385d3.
@Sidnioulz
Sidnioulz force-pushed the sidnioulz/argstable-required-hovered branch from 461b9ba to 630bdcf Compare June 29, 2026 09:31
@ndelangen

Copy link
Copy Markdown
Member

@Sidnioulz, I am seeing changes to the hovering mechanic, but that's not covered by the manual testing steps.
Did you manually verify that the functionality is preserved?

@Sidnioulz

Copy link
Copy Markdown
Contributor Author

@Sidnioulz, I am seeing changes to the hovering mechanic, but that's not covered by the manual testing steps. Did you manually verify that the functionality is preserved?

It's step 4:

Keyboard reachability: with the mouse away, Tab through an arg row that has no control and confirm the "Setup controls" link becomes visible and focusable (it should also still appear on mouse hover).

I did verify it. There is a story in ArgsTable where you can see it: https://635781f3500dd2c49e189caf-elyriepama.chromatic.com/?path=/story/addons-docs-components-argstable-argstable--in-addon-panel-no-controls

@Sidnioulz
Sidnioulz merged commit 5e02302 into next Jun 29, 2026
154 of 155 checks passed
@Sidnioulz
Sidnioulz deleted the sidnioulz/argstable-required-hovered branch June 29, 2026 12:22
@github-project-automation github-project-automation Bot moved this from In review to Done in Accessibility Improvements Jun 29, 2026
@github-actions github-actions Bot mentioned this pull request Jun 29, 2026
2 tasks done
This was referenced Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal Run our default set of CI jobs (choose this for most PRs). qa:skip Pull Requests that do not need any QA. (e.g. documentation)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants