From e44a6a918f88545789ce6cf181374c5f0cba4383 Mon Sep 17 00:00:00 2001 From: Gery Hirschfeld Date: Tue, 24 Sep 2024 10:46:05 +0200 Subject: [PATCH] chore: add a11y --- packages/core/src/components.d.ts | 2 ++ .../src/components/bal-field/bal-field.tsx | 3 +++ .../bal-segment-item/bal-segment-item.tsx | 27 ++++++++++++++++++- .../components/bal-segment/bal-segment.tsx | 18 +++++++++++++ .../app/cypress/e2e/bal-segment.spec.cy.ts | 2 +- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 9ff772b57..11ab6a1c5 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -2741,6 +2741,7 @@ export namespace Components { * If `true`, and is vertical then the list height is limited and scrollable. */ "scrollable": boolean; + "setAriaForm": (ariaForm: BalAriaForm) => Promise; /** * the value of the segment. */ @@ -2765,6 +2766,7 @@ export namespace Components { * Label of the segment control */ "label": string; + "setAriaForm": (ariaForm: BalAriaForm) => Promise; "setFocus": () => Promise; /** * The value of the segment button. diff --git a/packages/core/src/components/bal-field/bal-field.tsx b/packages/core/src/components/bal-field/bal-field.tsx index 7af5e7efc..0385658ee 100644 --- a/packages/core/src/components/bal-field/bal-field.tsx +++ b/packages/core/src/components/bal-field/bal-field.tsx @@ -28,6 +28,7 @@ export class Field implements ComponentInterface, BalMutationObserver { 'bal-input-slider', 'bal-file-upload', 'bal-dropdown', + 'bal-segment', ] private formElements = [...this.formControlElement, 'bal-field-label', 'bal-field-message'] @@ -172,6 +173,8 @@ export class Field implements ComponentInterface, BalMutationObserver { 'bal-field-control bal-dropdown', 'bal-field-control bal-checkbox', 'bal-field-control bal-radio', + 'bal-field-control bal-segment-item', + 'bal-field-control bal-segment', 'bal-field-control bal-checkbox-group', 'bal-field-control bal-radio-group', 'bal-field-control bal-number-input', diff --git a/packages/core/src/components/bal-segment/bal-segment-item/bal-segment-item.tsx b/packages/core/src/components/bal-segment/bal-segment-item/bal-segment-item.tsx index 19bba5a07..a1d03719d 100644 --- a/packages/core/src/components/bal-segment/bal-segment-item/bal-segment-item.tsx +++ b/packages/core/src/components/bal-segment/bal-segment-item/bal-segment-item.tsx @@ -3,6 +3,7 @@ import { BEM } from '../../../utils/bem' import { SegmentValue } from '../bal-segment.types' import { Attributes, inheritAttributes } from '../../../utils/attributes' import { addEventListener, raf, removeEventListener } from '../../../utils/helpers' +import { BalAriaForm, defaultBalAriaForm } from '../../../utils/form' let SegmentItemIds = 0 @@ -15,6 +16,7 @@ export class SegmentItem implements ComponentInterface { private nativeEl: HTMLButtonElement | undefined private inheritedAttributes: Attributes = {} private internalId = SegmentItemIds++ + private inputId = `bal-si-${this.internalId}` @Element() el!: HTMLElement @@ -24,6 +26,7 @@ export class SegmentItem implements ComponentInterface { @State() isLast = false @State() isFirst = false @State() hasEmptyValue = true + @State() ariaForm: BalAriaForm = defaultBalAriaForm /** * If `true`, the user cannot interact with the segment button. @@ -114,6 +117,14 @@ export class SegmentItem implements ComponentInterface { } } + /** + * @internal + */ + @Method() + async setAriaForm(ariaForm: BalAriaForm): Promise { + this.ariaForm = { ...ariaForm } + } + private updateVertical = (ev: BalEvents.BalSegmentVertical) => { this.isVertical = ev.detail } @@ -183,6 +194,19 @@ export class SegmentItem implements ComponentInterface { const hasTabindex = (hasEmptyValue && isFirst) || (isFocusable && !disabled) + const id = (hasTabindex && this.ariaForm.controlId) || this.inputId + + let buttonAttributes: any = {} + + if (hasTabindex) { + let labelId = this.ariaForm.labelId || null + labelId = `${labelId || ''} ${id}-lbl`.trim() + buttonAttributes = { + 'aria-labelledby': labelId, + 'aria-describedby': this.ariaForm.messageId, + } + } + return (