diff --git a/.changeset/ripe-baths-rush.md b/.changeset/ripe-baths-rush.md new file mode 100644 index 00000000000..b4274f32094 --- /dev/null +++ b/.changeset/ripe-baths-rush.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Only shows the aria-describedby id for loading when the component is in the loading state diff --git a/packages/react/src/Button/ButtonBase.tsx b/packages/react/src/Button/ButtonBase.tsx index ba376b52eae..d2ae5a0b6ba 100644 --- a/packages/react/src/Button/ButtonBase.tsx +++ b/packages/react/src/Button/ButtonBase.tsx @@ -56,6 +56,9 @@ const ButtonBase = forwardRef(({children, as: Component = 'button', ...props}, f const uuid = useId(id) const loadingAnnouncementID = `${uuid}-loading-announcement` + // Only include the loading aria-describedby if there is a loading state + const ariaDescribedByIds = loading ? [loadingAnnouncementID, ariaDescribedBy] : [ariaDescribedBy] + if (__DEV__) { /** * The Linter yells because it thinks this conditionally calls an effect, @@ -100,9 +103,7 @@ const ButtonBase = forwardRef(({children, as: Component = 'button', ...props}, f data-variant={variant} data-label-wrap={labelWrap} data-has-count={count !== undefined ? true : undefined} - aria-describedby={[loadingAnnouncementID, ariaDescribedBy] - .filter(descriptionID => Boolean(descriptionID)) - .join(' ')} + aria-describedby={ariaDescribedByIds.filter(descriptionID => Boolean(descriptionID)).join(' ') || undefined} // aria-labelledby is needed because the accessible name becomes unset when the button is in a loading state. // We only set it when the button is in a loading state because it will supersede the aria-label when the screen // reader announces the button name. diff --git a/packages/react/src/Button/__tests__/Button.test.tsx b/packages/react/src/Button/__tests__/Button.test.tsx index 5251ed5491d..4f42fbb1b15 100644 --- a/packages/react/src/Button/__tests__/Button.test.tsx +++ b/packages/react/src/Button/__tests__/Button.test.tsx @@ -170,6 +170,8 @@ describe('Button', () => { ) const buttonNode = container.getByRole('button') + fireEvent.click(buttonNode) + expect(buttonNode.getAttribute('aria-describedby')).toBe(`${buttonId}-loading-announcement`) fireEvent.click(buttonNode) @@ -192,6 +194,8 @@ describe('Button', () => { ) const buttonNode = container.getByRole('button') + fireEvent.click(buttonNode) + expect(buttonNode.getAttribute('aria-describedby')).toBe(`${buttonId}-loading-announcement`) fireEvent.click(buttonNode) @@ -213,6 +217,10 @@ describe('Button', () => { content , ) + const buttonNode = container.getByRole('button') + + fireEvent.click(buttonNode) + const buttonDescribedBy = container.getByRole('button').getAttribute('aria-describedby') const loadingAnnouncementId = `${buttonId}-loading-announcement` diff --git a/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap b/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap index 0ddfa63424b..0e24734daa4 100644 --- a/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap +++ b/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap @@ -2,7 +2,6 @@ exports[`Button > respects block prop 1`] = `