From bb2d55b98c9d60609592337540a3a685b27ed6fe Mon Sep 17 00:00:00 2001 From: Pema Sangpo Lama Date: Tue, 27 Oct 2026 02:00:39 -0500 Subject: [PATCH 1/2] fix(button): forward expanded state to the interactive control --- src/components/Button/Button.tsx | 2 ++ src/components/__tests__/Button.test.tsx | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 6f07113572..98b2c7e6ca 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -171,6 +171,7 @@ const Button = ({ textColor: customTextColor, children, 'aria-label': ariaLabel, + 'aria-expanded': ariaExpanded, accessibilityHint, role = 'button', hitSlop, @@ -328,6 +329,7 @@ const Button = ({ onPressOut={hasPassedTouchHandler ? handlePressOut : undefined} delayLongPress={delayLongPress} aria-label={ariaLabel} + aria-expanded={ariaExpanded} accessibilityHint={accessibilityHint} role={role} aria-disabled={disabled} diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx index 7ea496a419..b836d37849 100644 --- a/src/components/__tests__/Button.test.tsx +++ b/src/components/__tests__/Button.test.tsx @@ -24,6 +24,21 @@ it('renders text button by default', async () => { expect(tree).toMatchSnapshot(); }); +it.each([true, false])( + 'exposes aria-expanded=%s on the interactive button', + async (expanded) => { + await render( + + ); + + expect( + screen.getByRole('button', { name: 'Show details', expanded }) + ).toBeEnabled(); + } +); + it('renders text button with mode', async () => { const tree = ( await render() From f057c51e6feb242660a70ea7d25565b3da67c1f6 Mon Sep 17 00:00:00 2001 From: Pema Sangpo Lama Date: Thu, 5 Nov 2026 19:15:24 -0600 Subject: [PATCH 2/2] fix(button): address expanded state review feedback --- src/components/Button/Button.tsx | 4 ++++ src/components/__tests__/Button.test.tsx | 11 ++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 98b2c7e6ca..dfb14683f2 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -82,6 +82,10 @@ export type Props = Omit & { * Accessibility label for the button. This is read by the screen reader when the user taps the button. */ 'aria-label'?: string; + /** + * Indicates whether the element's controlled content is expanded. + */ + 'aria-expanded'?: boolean; /** * Accessibility hint for the button. This is read by the screen reader when the user taps the button. */ diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx index b836d37849..6209d3e4e8 100644 --- a/src/components/__tests__/Button.test.tsx +++ b/src/components/__tests__/Button.test.tsx @@ -24,18 +24,19 @@ it('renders text button by default', async () => { expect(tree).toMatchSnapshot(); }); -it.each([true, false])( +it.each<[boolean, 'toBeExpanded' | 'toBeCollapsed']>([ + [true, 'toBeExpanded'], + [false, 'toBeCollapsed'], +])( 'exposes aria-expanded=%s on the interactive button', - async (expanded) => { + async (expanded, matcher) => { await render( ); - expect( - screen.getByRole('button', { name: 'Show details', expanded }) - ).toBeEnabled(); + expect(screen.getByRole('button', { name: 'Show details' }))[matcher](); } );