Skip to content

Commit 49cc9d3

Browse files
authored
Merge pull request #2383 from hashicorp/hds-3809/unique-accordion-item-label
`Accordion`: make toggle button names unique
2 parents eae516a + e3095b0 commit 49cc9d3

File tree

6 files changed

+66
-8
lines changed

6 files changed

+66
-8
lines changed

.changeset/khaki-bats-admire.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hashicorp/design-system-components": patch
3+
---
4+
5+
`Accordion`: changed the default name of the `Accordion` item toggles. Now, they are labelled by the content in the `Accordion` title.

packages/components/src/components/hds/accordion/item/button.hbs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
aria-controls={{@contentId}}
1111
aria-expanded={{if @isOpen "true" "false"}}
1212
aria-label={{@ariaLabel}}
13+
aria-labelledby={{@ariaLabelledBy}}
1314
...attributes
1415
>
1516
<Hds::Icon @name="chevron-down" @size={{if (eq @size "large") "24" "16"}} />

packages/components/src/components/hds/accordion/item/button.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import type { HdsAccordionSizes } from '../types.ts';
1111
interface HdsAccordionItemButtonSignature {
1212
Args: {
1313
ariaLabel?: string;
14+
ariaLabelledBy?: string;
1415
contentId?: string;
1516
isOpen?: boolean;
1617
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1718
onClickToggle?: (event: MouseEvent, ...args: any[]) => void;
1819
parentContainsInteractive?: boolean;
1920
size?: HdsAccordionSizes;
21+
id?: string;
2022
};
2123
Element: HTMLButtonElement;
2224
}

packages/components/src/components/hds/accordion/item/index.hbs

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
@isOpen={{t.isOpen}}
1616
@onClickToggle={{t.onClickToggle}}
1717
@contentId={{this.contentId}}
18-
@ariaLabel={{this.ariaLabel}}
18+
@ariaLabel={{@ariaLabel}}
19+
@ariaLabelledBy={{this.ariaLabelledBy}}
1920
@size={{this.size}}
2021
@parentContainsInteractive={{this.containsInteractive}}
2122
/>
@@ -25,6 +26,7 @@
2526
@size={{this.toggleTextSize}}
2627
@weight="semibold"
2728
@color="strong"
29+
id={{this.titleId}}
2830
class="hds-accordion-item__toggle-content"
2931
>
3032
{{yield to="toggle"}}

packages/components/src/components/hds/accordion/item/index.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,13 @@ export default class HdsAccordionItem extends Component<HdsAccordionItemSignatur
6363
* @param contentId
6464
*/
6565
contentId = 'content-' + guidFor(this);
66+
titleId = 'title-' + guidFor(this);
6667

67-
/**
68-
* @param ariaLabel
69-
* @type {string}
70-
* @default 'Toggle display'
71-
*/
72-
get ariaLabel(): string {
73-
return this.args.ariaLabel ?? 'Toggle display';
68+
get ariaLabelledBy(): string | undefined {
69+
if (!this.args.ariaLabel) {
70+
return this.titleId;
71+
}
72+
return undefined;
7473
}
7574

7675
/**

showcase/tests/integration/components/hds/accordion/index-test.js

+49
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,55 @@ module('Integration | Component | hds/accordion/index', function (hooks) {
213213
);
214214
});
215215

216+
test('the AccordionItem toggle has an aria-labelledby attribute set to the id of the toggle text by default', async function (assert) {
217+
await render(
218+
hbs`
219+
<Hds::Accordion as |A|>
220+
<A.Item>
221+
<:toggle>Item one</:toggle>
222+
<:content>Additional content</:content>
223+
</A.Item>
224+
</Hds::Accordion>
225+
`
226+
);
227+
228+
assert.dom('.hds-accordion-item__button').hasAttribute('aria-labelledby');
229+
230+
assert
231+
.dom('.hds-accordion-item__button')
232+
.doesNotHaveAttribute('aria-label');
233+
234+
assert.strictEqual(
235+
this.element
236+
.querySelector('.hds-accordion-item__toggle-content')
237+
.getAttribute('id'),
238+
this.element
239+
.querySelector('.hds-accordion-item__button')
240+
.getAttribute('aria-labelledby')
241+
);
242+
});
243+
244+
test('the AccordionItem toggle has an aria-label attribute when the argument is passed', async function (assert) {
245+
await render(
246+
hbs`
247+
<Hds::Accordion as |A|>
248+
<A.Item @ariaLabel="Custom toggle label">
249+
<:toggle>Item one</:toggle>
250+
<:content>Additional content</:content>
251+
</A.Item>
252+
</Hds::Accordion>
253+
`
254+
);
255+
256+
assert
257+
.dom('.hds-accordion-item__button')
258+
.hasAttribute('aria-label', 'Custom toggle label');
259+
260+
assert
261+
.dom('.hds-accordion-item__button')
262+
.doesNotHaveAttribute('aria-labelledby');
263+
});
264+
216265
// OPTIONS
217266

218267
// isOpen

0 commit comments

Comments
 (0)