Skip to content

Commit

Permalink
Fixes AB#936: Duration picker labels
Browse files Browse the repository at this point in the history
Ensures aria-label on combobox includes control label and value.
  • Loading branch information
gingi committed May 30, 2023
1 parent 0bc8e7e commit 8dbbb6b
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ describe("DurationPickerComponent", () => {
expect(component.value instanceof Duration).toBe(true);
expect(testComponent.control.value.toISO()).toEqual("P4DT4H");
});

it("should set aria-label to include label, time, and duration", () => {
testComponent.control.setValue(Duration.fromISO("P50D"));
fixture.detectChanges();
expect(de.nativeElement.getAttribute("aria-label")).toEqual("My duration picker: 50 days");
});
});

describe("writing value", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ export class DurationPickerComponent implements FormFieldControl<any>,
@Input()
public label: string;

@HostBinding("attr.aria-label")
public get ariaLabel() { return `${this.label}: ${this.time} ${this.unit}`; }

@Input() public allowUnlimited: boolean = true;
@Input() public defaultDuration: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
<bl-select [ngModel]="unit"
(ngModelChange)="updateUnit($event)"
[placeholder]="'duration-picker.unit.label' | i18n"
[disabled]="disabled">
[disabled]="disabled"
[aria-label]="ariaLabel">

<bl-option [value]="DurationUnit.Unlimited" [label]="'duration-picker.unit.unlimited' | i18n" *ngIf="allowUnlimited"></bl-option>
<bl-option [value]="DurationUnit.Days" [label]="'duration-picker.unit.days' | i18n"></bl-option>
Expand Down
8 changes: 8 additions & 0 deletions desktop/src/@batch-flask/ui/select/select.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ describe("SelectComponent", () => {
fixture.detectChanges();
expect(labelEl.nativeElement.textContent).toContain("Carrot");
expect(de.nativeElement.getAttribute("aria-label")).toEqual("Myselect: Carrot");
expect(de.nativeElement.title).toEqual("Myselect: Carrot");
});

it("should respect an explicit aria-label attribute", () => {
de.nativeElement.setAttribute("aria-label", "foo");
fixture.detectChanges();
expect(de.nativeElement.getAttribute("aria-label")).toEqual("foo");
expect(de.nativeElement.title).toEqual("Myselect: ");
});

it("list all options when clicking on button", async () => {
Expand Down
7 changes: 6 additions & 1 deletion desktop/src/@batch-flask/ui/select/select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export class SelectComponent<TValue = any> implements FormFieldControl<any>, Opt
get id(): string { return this._id; }
set id(value: string) { this._id = value; }

@Input() @HostBinding("attr.label") public label: string;

@Input() @FlagInput() public required = false;

@Input()
Expand Down Expand Up @@ -114,9 +116,11 @@ export class SelectComponent<TValue = any> implements FormFieldControl<any>, Opt
@HostBinding("attr.aria-describedby") public ariaDescribedby: string;
@HostBinding("attr.role") public readonly role = "combobox";
@HostBinding("attr.aria-haspopup") public readonly ariaHasPopup = "listbox";
@Input("attr.aria-label") @HostBinding("attr.aria-label")

@Input("aria-label") @HostBinding("attr.aria-label")
public set ariaLabel(label: string) { this._ariaLabel = label; }
public get ariaLabel() { return this._ariaLabel || this.title; }

@HostBinding("attr.aria-expanded") public get ariaExpanded() { return this.dropdownOpen; }
@HostBinding("attr.aria-owns") public get ariaOwns() { return this.dropdownId; }
@HostBinding("attr.tabindex") public readonly tabindex = -1;
Expand Down Expand Up @@ -268,6 +272,7 @@ export class SelectComponent<TValue = any> implements FormFieldControl<any>, Opt
return this._optionsMap.get([...this.selected].first());
}

@HostBinding("title")
public get title() {
if (this.hasValueSelected) {
const values = [...this.selected].map(x => this._optionsMap.get(x)).map(x => x && x.label).join(", ");
Expand Down
1 change: 1 addition & 0 deletions desktop/src/@batch-flask/ui/select/select.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[attr.aria-label]="ariaLabel"
[attr.aria-controls]="dropdownId"
[attr.aria-activedescendant]="focusedOption?.id"
[title]="title"
attr.aria-autocomplete="list"
[attr.aria-readonly]="true"
(blur)="onButtonBlur()">
Expand Down

0 comments on commit 8dbbb6b

Please sign in to comment.