Skip to content

fix(Spinner): define default aria-label via destructuring#12420

Open
mvanhorn wants to merge 1 commit intopatternfly:mainfrom
mvanhorn:fix/spinner-aria-label-default
Open

fix(Spinner): define default aria-label via destructuring#12420
mvanhorn wants to merge 1 commit intopatternfly:mainfrom
mvanhorn:fix/spinner-aria-label-default

Conversation

@mvanhorn
Copy link
Copy Markdown

@mvanhorn mvanhorn commented May 8, 2026

What: Closes #11750

The Spinner component's default aria-label of "Contents" was emitted by an inline conditional in the JSX ({...(!ariaLabel && !ariaLabelledBy && { 'aria-label': 'Contents' })}), so the props table for the component didn't show that there was a default value at all. Per the maintainer's edit on the issue, this PR is scoped to just updating how that default is defined.

The destructuring now sets the default directly:

'aria-label': ariaLabel = 'Contents',

and the three conditional spreads in the JSX collapse to a direct aria-label={ariaLabel} plus the still-conditional aria-labelledBy spread.

Behavior

  • Existing snapshots are unchanged: <Spinner /> still renders aria-label="Contents".
  • An explicitly passed aria-label continues to take precedence.
  • A consumer that only provides aria-labelledBy will now also see the default aria-label="Contents" on the SVG. The two ARIA attributes coexist (per WAI-ARIA, an assistive technology will use aria-labelledby when both are present), and this matches the existing pattern for sibling components like TabAction, DrawerCloseButton, PageToggleButton, and FileUploadField that all use destructuring defaults for aria-label.

Tests

Added three unit tests covering the default value, an explicitly provided value, and aria-labelledBy propagation. Existing snapshot tests still pass unchanged.

Summary by CodeRabbit

Spinner Accessibility Improvements

  • Refactor

    • Simplified Spinner component's accessibility labeling logic to ensure consistent ARIA attributes.
  • Tests

    • Added test coverage verifying default and custom ARIA label behavior for the Spinner component.

The Spinner default "Contents" aria-label was emitted by an inline
conditional in the JSX, so the props table for the component did not
show that there was a default value at all (patternfly#11750). Move the default
to the destructuring pattern so react-docgen surfaces it, and replace
the three conditional spread expressions with a direct attribute plus
the still-conditional aria-labelledBy spread.

Existing snapshots are unchanged (`<Spinner />` still renders with
aria-label="Contents"). Added unit tests cover the default value, an
explicitly provided aria-label, and aria-labelledBy.

Closes patternfly#11750
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack

Walkthrough

The Spinner component's ARIA labeling logic is refactored to assign aria-label a default value of 'Contents' during prop destructuring, replacing conditional JSX spread logic. The SVG now unconditionally includes the aria-label attribute while aria-labelledBy remains conditionally applied. New tests verify default labeling, custom labels, and aria-labelledBy functionality.

Changes

Spinner ARIA Labeling Refactor

Layer / File(s) Summary
Core Implementation
packages/react-core/src/components/Spinner/Spinner.tsx
The aria-label prop is destructured with a default value of 'Contents' instead of being undefined, and the SVG element now directly applies aria-label={ariaLabel} while aria-labelledBy remains conditionally applied only when provided.
Test Coverage
packages/react-core/src/components/Spinner/__tests__/Spinner.test.tsx
Imports screen from Testing Library and adds three test cases: one verifying the default aria-label of "Contents", one confirming a provided aria-label prop is applied, and one confirming a provided aria-labelledBy prop is set as the corresponding attribute.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: moving the default aria-label definition from conditional JSX to prop destructuring, which is the core objective.
Linked Issues check ✅ Passed The PR addresses the scoped requirement from #11750 by defining the default aria-label via destructuring so documentation tooling can surface it, without changing runtime behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to the aria-label default definition refactoring and corresponding test coverage; aria-valuetext concern mentioned in the issue was explicitly excluded from scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@patternfly-build
Copy link
Copy Markdown
Collaborator

patternfly-build commented May 8, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/react-core/src/components/Spinner/Spinner.tsx (1)

26-26: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Pre-existing: aria-labelledBy is not a valid ARIA attribute name.

The WAI-ARIA spec defines this attribute as aria-labelledby (all lowercase). React passes aria-* attributes as-is to the DOM without normalization. On an SVG element (XML-based, case-sensitive), 'aria-labelledBy' produces a non-standard DOM attribute that assistive technologies will not recognize.

Lines 26, 36, and 46 in Spinner.tsx are pre-existing. However, the new test at lines 19–21 in Spinner.test.tsx adds coverage for this prop with the incorrect spelling, perpetuating the issue in new code. A full fix would require renaming the public prop from 'aria-labelledBy' to 'aria-labelledby' (a breaking API change best addressed in a dedicated PR), but now is a good time to track this known issue.

🤖 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 `@packages/react-core/src/components/Spinner/Spinner.tsx` at line 26, The
Spinner component uses the incorrect prop name 'aria-labelledBy' which produces
a non-standard DOM attribute; to avoid a breaking API change, update the Spinner
component (Spinner.tsx) to detect the incoming prop 'aria-labelledBy' and
forward it as the correct DOM attribute name 'aria-labelledby' (ensure the prop
is included in the SVG/element props passed to the DOM), update Spinner.test.tsx
to assert that the rendered DOM has 'aria-labelledby' set, and add a brief TODO
note in Spinner.tsx mentioning the planned public prop rename to
'aria-labelledby' in a follow-up breaking-change PR.
🤖 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 `@packages/react-core/src/components/Spinner/__tests__/Spinner.test.tsx`:
- Around line 19-22: Change the misspelled ARIA prop from "aria-labelledBy" to
the correct "aria-labelledby" across the API and tests: update the test case
(the 'renders aria-labelledBy when provided' test) to render <Spinner
aria-labelledby="external-label" /> and assert for 'aria-labelledby'; rename the
prop in SpinnerProps from 'aria-labelledBy'?: string to 'aria-labelledby'?:
string and update Spinner component's prop destructuring/spread where it uses
that key so the SVG receives aria-labelledby; if this is a breaking public API
change, mark for separate PR/deprecation notice as appropriate.

---

Outside diff comments:
In `@packages/react-core/src/components/Spinner/Spinner.tsx`:
- Line 26: The Spinner component uses the incorrect prop name 'aria-labelledBy'
which produces a non-standard DOM attribute; to avoid a breaking API change,
update the Spinner component (Spinner.tsx) to detect the incoming prop
'aria-labelledBy' and forward it as the correct DOM attribute name
'aria-labelledby' (ensure the prop is included in the SVG/element props passed
to the DOM), update Spinner.test.tsx to assert that the rendered DOM has
'aria-labelledby' set, and add a brief TODO note in Spinner.tsx mentioning the
planned public prop rename to 'aria-labelledby' in a follow-up breaking-change
PR.
🪄 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: b3812dc0-383f-44b9-a904-73a661f5b4d2

📥 Commits

Reviewing files that changed from the base of the PR and between ea832af and bd7e869.

📒 Files selected for processing (2)
  • packages/react-core/src/components/Spinner/Spinner.tsx
  • packages/react-core/src/components/Spinner/__tests__/Spinner.test.tsx

Comment on lines +19 to +22
test('renders aria-labelledBy when provided', () => {
render(<Spinner aria-labelledBy="external-label" />);
expect(screen.getByRole('progressbar')).toHaveAttribute('aria-labelledBy', 'external-label');
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

New test codifies the pre-existing aria-labelledBy (wrong casing) behavior.

The prop and assertion both use aria-labelledBy (capital B). Since React camelCases all attributes except data-* and aria-*, it passes aria-* names as-is to the DOM. On the SVG element (XML/case-sensitive), this produces a non-standard aria-labelledBy attribute that screen readers won't find — they look for aria-labelledby (all lowercase, per WAI-ARIA spec).

The test will pass today (JSDOM stores aria-labelledBy exactly as written and toHaveAttribute finds it), but it is asserting broken accessibility behavior. The correct attribute name throughout — interface, component, and test — should be aria-labelledby.

✅ Corrected test (aligned with WAI-ARIA spec)
 test('renders aria-labelledBy when provided', () => {
-  render(<Spinner aria-labelledBy="external-label" />);
-  expect(screen.getByRole('progressbar')).toHaveAttribute('aria-labelledBy', 'external-label');
+  render(<Spinner aria-labelledby="external-label" />);
+  expect(screen.getByRole('progressbar')).toHaveAttribute('aria-labelledby', 'external-label');
 });

The full fix also requires renaming the prop in SpinnerProps from 'aria-labelledBy'?: string to 'aria-labelledby'?: string and updating the corresponding destructuring and spread in Spinner.tsx. Because that is a public API rename, it may warrant its own PR and a deprecation notice.

🤖 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 `@packages/react-core/src/components/Spinner/__tests__/Spinner.test.tsx` around
lines 19 - 22, Change the misspelled ARIA prop from "aria-labelledBy" to the
correct "aria-labelledby" across the API and tests: update the test case (the
'renders aria-labelledBy when provided' test) to render <Spinner
aria-labelledby="external-label" /> and assert for 'aria-labelledby'; rename the
prop in SpinnerProps from 'aria-labelledBy'?: string to 'aria-labelledby'?:
string and update Spinner component's prop destructuring/spread where it uses
that key so the SVG receives aria-labelledby; if this is a breaking public API
change, mark for separate PR/deprecation notice as appropriate.

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.

[Spinner] - hardcoded aria-label attribute

2 participants