Skip to content

Commit 14945bd

Browse files
annawangggshleewhite
andauthored
HDS-5265: Adds a11y guardrails in Dropdown ToggleIcon component (#3087)
Co-authored-by: shleewhite <[email protected]>
1 parent c587433 commit 14945bd

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

.changeset/deep-wings-arrive.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@hashicorp/design-system-components": major
3+
---
4+
5+
<!-- START components/dropdown -->
6+
7+
`Dropdown` - Added assertion to the `ToggleIcon` to provide improved developer guidance for the `hasChevron` attribute
8+
9+
<!-- END -->

packages/components/src/components/hds/dropdown/toggle/icon.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import Component from '@glimmer/component';
77
import { action } from '@ember/object';
88
import { assert } from '@ember/debug';
99
import { tracked } from '@glimmer/tracking';
10-
import { HdsDropdownToggleIconSizeValues } from './types.ts';
10+
import {
11+
HdsDropdownToggleIconSizeValues,
12+
HdsDropdownToggleIconAllowedIconValues,
13+
} from './types.ts';
1114

1215
import type { HdsIconSignature } from '../../icon';
1316
import type { HdsDropdownToggleIconSizes } from './types';
@@ -20,6 +23,9 @@ export const SIZES: HdsDropdownToggleIconSizes[] = Object.values(
2023
HdsDropdownToggleIconSizeValues
2124
);
2225

26+
export const ALLOWED_ICON_LIST: HdsIconSignature['Args']['name'][] =
27+
Object.values(HdsDropdownToggleIconAllowedIconValues);
28+
2329
export interface HdsDropdownToggleIconSignature {
2430
Args: {
2531
hasChevron?: boolean;
@@ -107,13 +113,25 @@ export default class HdsDropdownToggleIcon extends Component<HdsDropdownToggleIc
107113
}
108114

109115
/**
110-
* Indicates if a dropdown chevron icon should be displayed; should be displayed unless the "more-horizontal" icon is used.
116+
* Indicates if a dropdown chevron icon should be displayed; should be displayed unless the "more-horizontal" or "more-vertical" icons are used.
111117
*
112118
* @param hasChevron
113119
* @type {boolean}
114120
* @default true
115121
*/
116122
get hasChevron(): boolean {
123+
if (
124+
this.args.icon &&
125+
!ALLOWED_ICON_LIST.includes(this.args.icon) &&
126+
this.args.hasChevron === false
127+
) {
128+
assert(
129+
`@hasChevron for "Hds::Dropdown::Toggle::Icon" must be true unless the icon is one of the following: ${ALLOWED_ICON_LIST.join(
130+
', '
131+
)}; received: ${this.args.icon}`
132+
);
133+
}
134+
117135
return this.args.hasChevron ?? true;
118136
}
119137

packages/components/src/components/hds/dropdown/toggle/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,10 @@ export enum HdsDropdownToggleButtonColorValues {
2222
}
2323
export type HdsDropdownToggleButtonColors =
2424
`${HdsDropdownToggleButtonColorValues}`;
25+
26+
export enum HdsDropdownToggleIconAllowedIconValues {
27+
MoreHorizontal = 'more-horizontal',
28+
MoreVertical = 'more-vertical',
29+
}
30+
export type HdsDropdownToggleIconAllowedIcons =
31+
`${HdsDropdownToggleIconAllowedIconValues}`;

showcase/tests/integration/components/hds/dropdown/toggle/icon-test.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ module('Integration | Component | hds/dropdown/toggle/icon', function (hooks) {
6969
});
7070
test('toggle-icon renders no chevron when hasChevron is set to false', async function (assert) {
7171
await render(
72-
hbs`<Hds::Dropdown::Toggle::Icon @icon="user" @text="user menu" id="test-toggle-icon" @hasChevron={{false}} />`,
72+
hbs`<Hds::Dropdown::Toggle::Icon @icon="more-horizontal" @text="user menu" id="test-toggle-icon" @hasChevron={{false}} />`,
7373
);
7474
assert.dom('.hds-icon.hds-icon-chevron-down').doesNotExist();
7575
});
@@ -155,4 +155,18 @@ module('Integration | Component | hds/dropdown/toggle/icon', function (hooks) {
155155
throw new Error(errorMessage);
156156
});
157157
});
158+
test('it should throw an assertion if an incorrect value for @icon is provided while @hasChevron is false', async function (assert) {
159+
const errorMessage =
160+
'@hasChevron for "Hds::Dropdown::Toggle::Icon" must be true unless the icon is one of the following: more-horizontal, more-vertical; received: apple';
161+
assert.expect(2);
162+
setupOnerror(function (error) {
163+
assert.strictEqual(error.message, `Assertion Failed: ${errorMessage}`);
164+
});
165+
await render(
166+
hbs`<Hds::Dropdown::Toggle::Icon @icon="apple" @text="user menu" @hasChevron={{false}}/>`,
167+
);
168+
assert.throws(function () {
169+
throw new Error(errorMessage);
170+
});
171+
});
158172
});

website/docs/components/dropdown/partials/code/component-api.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ The Dropdown component is composed of different child components each with their
6868
If an `@isInline` parameter is provided, then the element will be displayed as `inline-block` (useful to achieve specific layouts like in a container with right alignment). Otherwise, it will have a `block` layout.
6969
</C.Property>
7070
<C.Property @name="enableCollisionDetection" @type="boolean" @default="false" @values={{array "true" "false"}}>
71-
Setting it to `true` will automatically flip the list position to remain visible when near the edges of the viewport.
71+
Setting it to `true` will automatically flip the list position to remain visible when near the edges of the viewport.
7272
</C.Property>
7373
<C.Property @name="isOpen" @type="boolean" @default="false" @values={{array "true" "false"}}>
7474
Controls if the list should be rendered initially opened.
@@ -136,7 +136,7 @@ The `Dropdown::Toggle::Icon` component, yielded as contextual component.
136136
Acceptable value: any [icon](/icons/library) name.
137137
</C.Property>
138138
<C.Property @name="hasChevron" @type="boolean" @default="true">
139-
Per design, `false` is only currently allowed when the "more-horizontal" icon is used; it is set to `true` by default.
139+
Per design, `false` is only currently allowed when the "more-horizontal" or "more-vertical" icons are used; it is set to `true` by default.
140140
</C.Property>
141141
<C.Property @name="imageSrc" @type="string"/>
142142
<C.Property @name="...attributes">
@@ -295,7 +295,7 @@ The `Dropdown::ListItem::Checkmark` component, yielded as contextual component.
295295
</C.Property>
296296
<C.Property @name="...attributes">
297297
This component supports use of [`...attributes`](https://guides.emberjs.com/release/in-depth-topics/patterns-for-components/#toc_attribute-ordering).
298-
<br/><br/>
298+
<br/><br/>
299299
In this component, the `...attributes` are not supported on the root element (an `<li>` element) but on the underlying element/component (`<button>`, `<a>`, `<LinkTo>` or `<LinkToExternal>` depending on the `@route/@href` arguments).
300300
</C.Property>
301301
</Doc::ComponentApi>

0 commit comments

Comments
 (0)