From b60e9c1cb60227c8dc86c6d1be046e5419f9ca65 Mon Sep 17 00:00:00 2001 From: Akshat Patel Date: Wed, 12 Jun 2024 18:51:38 -0400 Subject: [PATCH 1/4] fix: add labelID to label so screen readers can read the label Signed-off-by: Akshat Patel --- src/combobox/combobox.component.ts | 13 +++++++++++-- src/combobox/combobox.stories.ts | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/combobox/combobox.component.ts b/src/combobox/combobox.component.ts index 1d2a71c531..946c1f9d22 100644 --- a/src/combobox/combobox.component.ts +++ b/src/combobox/combobox.component.ts @@ -40,8 +40,12 @@ import { Observable } from "rxjs"; @@ -105,7 +109,7 @@ import { Observable } from "rxjs"; [ngClass]="{'bx--text-input--empty': !showClearButton}" tabindex="0" [id]="id" - [attr.aria-labelledby]="id" + [attr.aria-labelledby]="labelId" [attr.aria-expanded]="open" aria-haspopup="listbox" [attr.maxlength]="maxLength" @@ -253,6 +257,7 @@ export class ComboBox implements OnChanges, AfterViewInit, AfterContentInit, OnD } static comboBoxCount = 0; @Input() id = `dropdown-${ComboBox.comboBoxCount++}`; + @Input() labelId = `dropdown-label-${ComboBox.comboBoxCount}`; /** * List of items to fill the content with. * @@ -298,6 +303,10 @@ export class ComboBox implements OnChanges, AfterViewInit, AfterContentInit, OnD * Label for the combobox. */ @Input() label: string | TemplateRef; + /** + * Hide label while keeping it available for screen readers + */ + @Input() hideLabel = false; /** * Sets the optional helper text. */ diff --git a/src/combobox/combobox.stories.ts b/src/combobox/combobox.stories.ts index 9118a8b7d0..a348465a53 100644 --- a/src/combobox/combobox.stories.ts +++ b/src/combobox/combobox.stories.ts @@ -29,6 +29,7 @@ const getOptions = (override = {}) => { warn: boolean("Show the warning state", false), warnText: text("Text for the warning", "This is a warning"), label: text("Label", "ComboBox label"), + hideLabel: boolean("Hide label", false), helperText: text("Helper text", "Optional helper text."), items: object("items", [ { content: "one" }, @@ -131,7 +132,8 @@ class DynamicListComboBox implements AfterViewInit { [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" - [items]="_items"> + [items]="_items" + [hideLabel]="hideLabel"> selected: {{ sampleForm.get("combobox").value | json }} @@ -147,7 +149,8 @@ class DynamicListComboBox implements AfterViewInit { [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" - [items]="_items"> + [items]="_items" + [hideLabel]="hideLabel"> selected: {{ sampleForm.get("multibox").value | json }} @@ -164,6 +167,7 @@ class ReactiveFormsCombobox implements OnInit { @Input() helperText = ""; @Input() size = "md"; @Input() theme = "dark"; + @Input() hideLabel = false; @Input() set items(newItems) { if (!isEqual(this._items, newItems)) { this._items = newItems; @@ -290,6 +294,7 @@ storiesOf("Components|Combobox", module) [warn]="warn" [warnText]="warnText" [label]="label" + [hideLabel]="hideLabel" [helperText]="helperText" [items]="items" [theme]="theme" @@ -322,6 +327,7 @@ storiesOf("Components|Combobox", module) [size]="size" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [helperText]="helperText" [items]="items" [theme]="theme" @@ -347,6 +353,7 @@ storiesOf("Components|Combobox", module) [size]="size" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [helperText]="helperText" [items]="items" [theme]="theme" @@ -382,6 +389,7 @@ storiesOf("Components|Combobox", module) [invalid]="invalid" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [size]="size" [helperText]="helperText" [items]="items" @@ -421,6 +429,7 @@ storiesOf("Components|Combobox", module) [invalid]="invalid" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [warn]="warn" [disabled]="disabled" [size]="size" @@ -472,6 +481,7 @@ storiesOf("Components|Combobox", module) [invalid]="invalid" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [helperText]="helperText" [items]="items" [theme]="theme" @@ -508,6 +518,7 @@ storiesOf("Components|Combobox", module) [invalid]="invalid" [invalidText]="invalidText" [label]="label" + [hideLabel]="hideLabel" [size]="size" itemValueKey="content" [helperText]="helperText" From baaeb179429fea8a0e4f926bd6c6949ab591fec6 Mon Sep 17 00:00:00 2001 From: Akshat Patel Date: Wed, 12 Jun 2024 18:52:01 -0400 Subject: [PATCH 2/4] fix: allow labels to be hidden but accessibile to screen readers Signed-off-by: Akshat Patel --- src/dropdown/dropdown.component.ts | 9 ++++++++- src/dropdown/dropdown.stories.ts | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/dropdown/dropdown.component.ts b/src/dropdown/dropdown.component.ts index d107ed0b49..8de6323431 100644 --- a/src/dropdown/dropdown.component.ts +++ b/src/dropdown/dropdown.component.ts @@ -55,7 +55,10 @@ import { hasScrollableParents } from "carbon-components-angular/utils"; *ngIf="label" [for]="id" class="bx--label" - [ngClass]="{'bx--label--disabled': disabled}"> + [ngClass]="{ + 'bx--label--disabled': disabled, + 'bx--visually-hidden': hideLabel + }"> {{label}} @@ -176,6 +179,10 @@ export class Dropdown implements OnInit, AfterContentInit, AfterViewInit, OnDest * Label for the dropdown. */ @Input() label: string | TemplateRef; + /** + * Hide label while keeping it available for screen readers + */ + @Input() hideLabel = false; /** * Sets the optional helper text. */ diff --git a/src/dropdown/dropdown.stories.ts b/src/dropdown/dropdown.stories.ts index 14abc596e0..22b7121937 100644 --- a/src/dropdown/dropdown.stories.ts +++ b/src/dropdown/dropdown.stories.ts @@ -58,6 +58,7 @@ const getProps = (overrides = {}) => Object.assign({}, { warnText: text("Text for the warning", "This is a warning"), disabled: boolean("disabled", false), label: text("Label", "Dropdown label"), + hideLabel: boolean("Hide label", false), helperText: text("Helper text", "Optional helper text."), items: object("items", [ { content: "one" }, @@ -84,6 +85,7 @@ const getProps = (overrides = {}) => Object.assign({}, {
Date: Wed, 12 Jun 2024 19:10:38 -0400 Subject: [PATCH 3/4] fix: keep the auto generated labelID and ID the same index Signed-off-by: Akshat Patel --- src/combobox/combobox.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combobox/combobox.component.ts b/src/combobox/combobox.component.ts index 946c1f9d22..728f33f70b 100644 --- a/src/combobox/combobox.component.ts +++ b/src/combobox/combobox.component.ts @@ -256,7 +256,7 @@ export class ComboBox implements OnChanges, AfterViewInit, AfterContentInit, OnD return this._clearSelectionAria.value; } static comboBoxCount = 0; - @Input() id = `dropdown-${ComboBox.comboBoxCount++}`; + @Input() id = `dropdown-${++ComboBox.comboBoxCount}`; @Input() labelId = `dropdown-label-${ComboBox.comboBoxCount}`; /** * List of items to fill the content with. From 204dc52c299b6343df042f7dc0c19468d2000dd3 Mon Sep 17 00:00:00 2001 From: Akshat Patel Date: Wed, 12 Jun 2024 19:12:59 -0400 Subject: [PATCH 4/4] fix: Ensure there are no duplicates of labelID and ID Signed-off-by: Akshat Patel --- src/combobox/combobox.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/combobox/combobox.component.ts b/src/combobox/combobox.component.ts index 728f33f70b..c81d0940ec 100644 --- a/src/combobox/combobox.component.ts +++ b/src/combobox/combobox.component.ts @@ -256,8 +256,8 @@ export class ComboBox implements OnChanges, AfterViewInit, AfterContentInit, OnD return this._clearSelectionAria.value; } static comboBoxCount = 0; - @Input() id = `dropdown-${++ComboBox.comboBoxCount}`; - @Input() labelId = `dropdown-label-${ComboBox.comboBoxCount}`; + @Input() id = `dropdown-${ComboBox.comboBoxCount++}`; + @Input() labelId = `dropdown-label-${ComboBox.comboBoxCount++}`; /** * List of items to fill the content with. *