diff --git a/packages/components/src/components/checkbox/checkbox.tsx b/packages/components/src/components/checkbox/checkbox.tsx index 65b9a44936..a341a77324 100644 --- a/packages/components/src/components/checkbox/checkbox.tsx +++ b/packages/components/src/components/checkbox/checkbox.tsx @@ -65,6 +65,8 @@ export class Checkbox { @Prop() styles?: string; /** (optional) Input required */ @Prop() required?: boolean; + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; /** Emitted when the value has changed. */ @Event({ eventName: 'scale-change' }) scaleChange: EventEmitter; @@ -189,7 +191,8 @@ export class Checkbox { aria-label={this.ariaLabelCheckbox} aria-checked={this.indeterminate ? 'mixed' : false} aria-invalid={this.status === 'error' || this.invalid ? 'true' : null} - aria-describedBy={helperText.id} + aria-describedBy={helperText ? helperText.id : this.ariaDetailsId} + aria-details={this.ariaDetailsId} disabled={this.disabled} required={this.required} onChange={this.handleChange} diff --git a/packages/components/src/components/checkbox/readme.md b/packages/components/src/components/checkbox/readme.md index 1922303c48..4e083e2f83 100644 --- a/packages/components/src/components/checkbox/readme.md +++ b/packages/components/src/components/checkbox/readme.md @@ -7,22 +7,23 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------- | --------------------- | ----------------------------------------------------------------------------------------- | --------- | ----------- | -| `ariaLabelCheckbox` | `aria-label-checkbox` | (optional) Input label output | `string` | `undefined` | -| `checked` | `checked` | (optional) Active switch | `boolean` | `false` | -| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `false` | -| `helperText` | `helper-text` | (optional) Input helper text | `string` | `undefined` | -| `hideLabel` | `hide-label` | (optional) Hides the specified label visually | `boolean` | `false` | -| `indeterminate` | `indeterminate` | (optional) indeterminate | `boolean` | `false` | -| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | -| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | -| `label` | `label` | (optional) Input label | `string` | `''` | -| `name` | `name` | (optional) Input name | `string` | `undefined` | -| `required` | `required` | (optional) Input required | `boolean` | `undefined` | -| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | -| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | -| `value` | `value` | (optional) Input value | `string` | `''` | +| Property | Attribute | Description | Type | Default | +| ------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------- | --------- | ----------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | +| `ariaLabelCheckbox` | `aria-label-checkbox` | (optional) Input label output | `string` | `undefined` | +| `checked` | `checked` | (optional) Active switch | `boolean` | `false` | +| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `false` | +| `helperText` | `helper-text` | (optional) Input helper text | `string` | `undefined` | +| `hideLabel` | `hide-label` | (optional) Hides the specified label visually | `boolean` | `false` | +| `indeterminate` | `indeterminate` | (optional) indeterminate | `boolean` | `false` | +| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | +| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | +| `label` | `label` | (optional) Input label | `string` | `''` | +| `name` | `name` | (optional) Input name | `string` | `undefined` | +| `required` | `required` | (optional) Input required | `boolean` | `undefined` | +| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | +| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | +| `value` | `value` | (optional) Input value | `string` | `''` | ## Events diff --git a/packages/components/src/components/date-picker/date-picker.tsx b/packages/components/src/components/date-picker/date-picker.tsx index 5a15423b68..a202a02a30 100644 --- a/packages/components/src/components/date-picker/date-picker.tsx +++ b/packages/components/src/components/date-picker/date-picker.tsx @@ -151,6 +151,10 @@ export class DatePicker { @Prop() variant?: 'informational' | 'warning' | 'danger' | 'success' = 'informational'; + + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; + /** Whether the input element has focus */ @State() hasFocus: boolean = false; @@ -308,11 +312,15 @@ export class DatePicker { input.addEventListener('keyup', this.handleKeyPress); } - if (input && this.helperText) { - input.setAttribute( - 'aria-describedby', - `helper-message-${this.internalId}` - ); + if (input && (this.helperText || this.ariaDetailsId)) { + const describedBy = this.helperText + ? `helper-message-${this.internalId}` + : this.ariaDetailsId; + input.setAttribute('aria-describedby', describedBy); + } + + if (input && this.ariaDetailsId) { + input.setAttribute('aria-details', this.ariaDetailsId); } if (input && this.placeholder) { @@ -483,7 +491,7 @@ export class DatePicker { dateAdapter={this.dateAdapter} disabled={this.disabled} value={this.value} - ref={(element: HTMLElement & DuetDatePicker) => + ref={(element: HTMLDuetDatePickerElement & DuetDatePicker) => (this.duetInput = element) } > diff --git a/packages/components/src/components/date-picker/readme.md b/packages/components/src/components/date-picker/readme.md index 8b3077a06f..06836403f4 100644 --- a/packages/components/src/components/date-picker/readme.md +++ b/packages/components/src/components/date-picker/readme.md @@ -9,6 +9,7 @@ | Property | Attribute | Description | Type | Default | | ---------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | | `dateAdapter` | `date-adapter` | Date adapter, for custom parsing/formatting. Must be object with a `parse` function which accepts a `string` and returns a `Date`, and a `format` function which accepts a `Date` and returns a `string`. Default is IS0-8601 parsing and formatting. | `any` | `undefined` | | `direction` | `direction` | Forces the opening direction of the calendar modal to be always left or right. This setting can be useful when the input is smaller than the opening date picker would be as by default the picker always opens towards right. | `"left" \| "right"` | `'right'` | | `disabled` | `disabled` | Makes the date picker input component disabled. This prevents users from being able to interact with the input, and conveys its inactive state to assistive technologies. | `boolean` | `false` | diff --git a/packages/components/src/components/dropdown-select/dropdown-select.tsx b/packages/components/src/components/dropdown-select/dropdown-select.tsx index afe80c06ce..2c8e429f00 100644 --- a/packages/components/src/components/dropdown-select/dropdown-select.tsx +++ b/packages/components/src/components/dropdown-select/dropdown-select.tsx @@ -257,6 +257,8 @@ export class DropdownSelect { @Prop() ariaLabelSelected?: string = 'selected'; /** (optional) Text displayed in high contrast mode only to indicate disabled state */ @Prop() hcmLabelDisabled?: string = 'this field is disabled'; + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; @Event({ eventName: 'scale-change' }) scaleChange!: EventEmitter; @Event({ eventName: 'scale-focus' }) scaleFocus!: EventEmitter; @@ -490,7 +492,8 @@ export class DropdownSelect { const ValueElement = element.ItemElement; const hasEmptyValueElement = element.value === ''; const helperTextId = `helper-message-${generateUniqueId()}`; - const ariaDescribedByAttr = { 'aria-describedBy': helperTextId }; + const describedBy = this.helperText ? helperTextId : this.ariaDetailsId; + const ariaDescribedByAttr = { 'aria-describedBy': describedBy }; return ( @@ -505,6 +508,7 @@ export class DropdownSelect { aria-expanded={this.open ? 'true' : 'false'} aria-haspopup="listbox" aria-labelledby={`${this.comboboxId}-label`} + aria-details={this.ariaDetailsId} id={this.comboboxId} part="combobox" role="combobox" @@ -521,7 +525,7 @@ export class DropdownSelect { ).value, } : {})} - {...(this.helperText ? ariaDescribedByAttr : {})} + {...ariaDescribedByAttr} {...(this.invalid ? { 'aria-invalid': 'true' } : {})} > diff --git a/packages/components/src/components/dropdown-select/readme.md b/packages/components/src/components/dropdown-select/readme.md index 68ea780eba..31a69bfab3 100644 --- a/packages/components/src/components/dropdown-select/readme.md +++ b/packages/components/src/components/dropdown-select/readme.md @@ -7,22 +7,23 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------- | --------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------- | -------------------------- | -| `ariaLabelSelected` | `aria-label-selected` | (optional) Screen reader text appended to the selected element | `string` | `'selected'` | -| `comboboxId` | `combobox-id` | | `string` | `'combobox'` | -| `disabled` | `disabled` | | `boolean` | `undefined` | -| `floatingStrategy` | `floating-strategy` | | `"absolute" \| "fixed"` | `'absolute'` | -| `hcmLabelDisabled` | `hcm-label-disabled` | (optional) Text displayed in high contrast mode only to indicate disabled state | `string` | `'this field is disabled'` | -| `helperText` | `helper-text` | | `string` | `''` | -| `hideLabelVisually` | `hide-label-visually` | (optional) to hide the label | `boolean` | `false` | -| `invalid` | `invalid` | | `boolean` | `false` | -| `label` | `label` | | `string` | `undefined` | -| `name` | `name` | | `string` | `undefined` | -| `readonly` | `readonly` | | `boolean` | `undefined` | -| `transparent` | `transparent` | | `boolean` | `undefined` | -| `value` | `value` | | `any` | `undefined` | -| `variant` | `variant` | | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | +| Property | Attribute | Description | Type | Default | +| ------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | -------------------------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | +| `ariaLabelSelected` | `aria-label-selected` | (optional) Screen reader text appended to the selected element | `string` | `'selected'` | +| `comboboxId` | `combobox-id` | | `string` | `'combobox'` | +| `disabled` | `disabled` | | `boolean` | `undefined` | +| `floatingStrategy` | `floating-strategy` | | `"absolute" \| "fixed"` | `'absolute'` | +| `hcmLabelDisabled` | `hcm-label-disabled` | (optional) Text displayed in high contrast mode only to indicate disabled state | `string` | `'this field is disabled'` | +| `helperText` | `helper-text` | | `string` | `''` | +| `hideLabelVisually` | `hide-label-visually` | (optional) to hide the label | `boolean` | `false` | +| `invalid` | `invalid` | | `boolean` | `false` | +| `label` | `label` | | `string` | `undefined` | +| `name` | `name` | | `string` | `undefined` | +| `readonly` | `readonly` | | `boolean` | `undefined` | +| `transparent` | `transparent` | | `boolean` | `undefined` | +| `value` | `value` | | `any` | `undefined` | +| `variant` | `variant` | | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | ## Events diff --git a/packages/components/src/components/dropdown/dropdown.tsx b/packages/components/src/components/dropdown/dropdown.tsx index ffd36e0bba..2adfa3745c 100644 --- a/packages/components/src/components/dropdown/dropdown.tsx +++ b/packages/components/src/components/dropdown/dropdown.tsx @@ -70,6 +70,8 @@ export class Dropdown { @Prop() controlled?: boolean = false; /** (optional) to avoid displaying the label */ @Prop() hideLabelVisually?: boolean = false; + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; /** (optional) Injected CSS styles */ @Prop() styles?: string; @@ -242,7 +244,8 @@ export class Dropdown { const ariaInvalidAttr = this.status === 'error' || this.invalid ? { 'aria-invalid': 'true' } : {}; const helperTextId = `helper-message-${this.internalId}`; - const ariaDescribedByAttr = { 'aria-describedBy': helperTextId }; + const describedBy = this.helperText ? helperTextId : this.ariaDetailsId; + const ariaDescribedByAttr = { 'aria-describedBy': describedBy }; return ( @@ -268,7 +271,10 @@ export class Dropdown { name={this.name} size={this.visibleSize} {...ariaInvalidAttr} - {...(this.helperText ? ariaDescribedByAttr : {})} + {...(this.helperText || this.ariaDetailsId + ? ariaDescribedByAttr + : {})} + aria-details={this.ariaDetailsId} > diff --git a/packages/components/src/components/dropdown/readme.md b/packages/components/src/components/dropdown/readme.md index 2daa67e513..f673b4eb41 100644 --- a/packages/components/src/components/dropdown/readme.md +++ b/packages/components/src/components/dropdown/readme.md @@ -7,25 +7,26 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------- | --------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------------- | -| `controlled` | `controlled` | (optional) Makes type `select` behave as a controlled component in React | `boolean` | `false` | -| `disabled` | `disabled` | | `boolean` | `undefined` | -| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | -| `hideLabelVisually` | `hide-label-visually` | (optional) to avoid displaying the label | `boolean` | `false` | -| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | -| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | -| `label` | `label` | (optional) Input label | `string` | `''` | -| `multiple` | `multiple` | (optional) select multiple options | `boolean` | `undefined` | -| `name` | `name` | (optional) Input name | `string` | `''` | -| `required` | `required` | (optional) Input required | `boolean` | `undefined` | -| `size` | `size` | **[DEPRECATED]**

| `string` | `undefined` | -| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | -| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | -| `transparent` | `transparent` | (optional) input background transparent | `boolean` | `undefined` | -| `value` | `value` | (optional) Input value | `number \| string` | `''` | -| `variant` | `variant` | (optional) Variant | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | -| `visibleSize` | `visible-size` | (optional) the number of visible options in a select drop-down list | `number` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | +| `controlled` | `controlled` | (optional) Makes type `select` behave as a controlled component in React | `boolean` | `false` | +| `disabled` | `disabled` | | `boolean` | `undefined` | +| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | +| `hideLabelVisually` | `hide-label-visually` | (optional) to avoid displaying the label | `boolean` | `false` | +| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | +| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | +| `label` | `label` | (optional) Input label | `string` | `''` | +| `multiple` | `multiple` | (optional) select multiple options | `boolean` | `undefined` | +| `name` | `name` | (optional) Input name | `string` | `''` | +| `required` | `required` | (optional) Input required | `boolean` | `undefined` | +| `size` | `size` | **[DEPRECATED]**

| `string` | `undefined` | +| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | +| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | +| `transparent` | `transparent` | (optional) input background transparent | `boolean` | `undefined` | +| `value` | `value` | (optional) Input value | `number \| string` | `''` | +| `variant` | `variant` | (optional) Variant | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | +| `visibleSize` | `visible-size` | (optional) the number of visible options in a select drop-down list | `number` | `undefined` | ## Events diff --git a/packages/components/src/components/radio-button/radio-button.tsx b/packages/components/src/components/radio-button/radio-button.tsx index 42e84849b1..5ba1d3e7c9 100644 --- a/packages/components/src/components/radio-button/radio-button.tsx +++ b/packages/components/src/components/radio-button/radio-button.tsx @@ -53,6 +53,8 @@ export class RadioButton { @Prop() inputId?: string; /** (optional) Injected CSS styles */ @Prop() styles?: string; + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; @Event({ eventName: 'scale-change' }) scaleChange!: EventEmitter; @@ -124,7 +126,8 @@ export class RadioButton { const ariaInvalidAttr = this.status === 'error' || this.invalid ? { 'aria-invalid': 'true' } : {}; const helperTextId = `helper-message-${this.internalId}`; - const ariaDescribedByAttr = { 'aria-describedBy': helperTextId }; + const describedBy = this.helperText ? helperTextId : this.ariaDetailsId; + const ariaDescribedByAttr = { 'aria-describedBy': describedBy }; return ( @@ -138,7 +141,10 @@ export class RadioButton { checked={this.checked} disabled={this.disabled} {...ariaInvalidAttr} - {...(this.helperText ? ariaDescribedByAttr : {})} + {...(this.helperText || this.ariaDetailsId + ? ariaDescribedByAttr + : {})} + aria-details={this.ariaDetailsId} /> {!!this.helperText && ( diff --git a/packages/components/src/components/radio-button/readme.md b/packages/components/src/components/radio-button/readme.md index c0034e5871..5d4c086c81 100644 --- a/packages/components/src/components/radio-button/readme.md +++ b/packages/components/src/components/radio-button/readme.md @@ -7,18 +7,19 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------ | ------------- | ----------------------------------------------------------------------------------------- | ------------------ | ----------- | -| `checked` | `checked` | (optional) Input checked | `boolean` | `false` | -| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `undefined` | -| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | -| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | -| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | -| `label` | `label` | (optional) Input label | `string` | `''` | -| `name` | `name` | (optional) Input name | `string` | `''` | -| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | -| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | -| `value` | `value` | (optional) Input value | `number \| string` | `''` | +| Property | Attribute | Description | Type | Default | +| --------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------ | ----------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | +| `checked` | `checked` | (optional) Input checked | `boolean` | `false` | +| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `undefined` | +| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | +| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | +| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | +| `label` | `label` | (optional) Input label | `string` | `''` | +| `name` | `name` | (optional) Input name | `string` | `''` | +| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | +| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | +| `value` | `value` | (optional) Input value | `number \| string` | `''` | ## Events diff --git a/packages/components/src/components/textarea/readme.md b/packages/components/src/components/textarea/readme.md index 0111cfd0ba..c5e9044087 100644 --- a/packages/components/src/components/textarea/readme.md +++ b/packages/components/src/components/textarea/readme.md @@ -7,29 +7,30 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ---------------- | ----------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------------- | -| `cols` | `cols` | (optional) textarea column | `number` | `undefined` | -| `counter` | `counter` | (optional) Input counter | `boolean` | `undefined` | -| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `undefined` | -| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | -| `inputAutofocus` | `input-autofocus` | (optional) the input should automatically get focus when the page loads. | `boolean` | `undefined` | -| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | -| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | -| `label` | `label` | (optional) Input label | `string` | `''` | -| `maxLength` | `max-length` | (optional) Input max length | `number` | `undefined` | -| `minLength` | `min-length` | (optional) Input min length | `number` | `undefined` | -| `name` | `name` | (optional) Input name | `string` | `''` | -| `placeholder` | `placeholder` | (optional) Input placeHolder | `string` | `''` | -| `readonly` | `readonly` | (optional) Input readonly | `boolean` | `undefined` | -| `required` | `required` | (optional) Input required | `boolean` | `undefined` | -| `resize` | `resize` | (optional) textarea resize | `"horizontal" \| "none" \| "unset" \| "vertical"` | `undefined` | -| `rows` | `rows` | (optional) textarea row | `number` | `undefined` | -| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | -| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | -| `transparent` | `transparent` | (optional) input background transparent | `boolean` | `undefined` | -| `value` | `value` | (optional) Input value | `number \| string` | `''` | -| `variant` | `variant` | (optional) Variant | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | +| Property | Attribute | Description | Type | Default | +| ---------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------------- | +| `ariaDetailsId` | `aria-details-id` | (optional) id or space separated list of ids of elements that provide or link to additional related information. | `string` | `undefined` | +| `cols` | `cols` | (optional) textarea column | `number` | `undefined` | +| `counter` | `counter` | (optional) Input counter | `boolean` | `undefined` | +| `disabled` | `disabled` | (optional) Input disabled | `boolean` | `undefined` | +| `helperText` | `helper-text` | (optional) Input helper text | `string` | `''` | +| `inputAutofocus` | `input-autofocus` | (optional) the input should automatically get focus when the page loads. | `boolean` | `undefined` | +| `inputId` | `input-id` | (optional) Input checkbox id | `string` | `undefined` | +| `invalid` | `invalid` | (optional) Input status | `boolean` | `false` | +| `label` | `label` | (optional) Input label | `string` | `''` | +| `maxLength` | `max-length` | (optional) Input max length | `number` | `undefined` | +| `minLength` | `min-length` | (optional) Input min length | `number` | `undefined` | +| `name` | `name` | (optional) Input name | `string` | `''` | +| `placeholder` | `placeholder` | (optional) Input placeHolder | `string` | `''` | +| `readonly` | `readonly` | (optional) Input readonly | `boolean` | `undefined` | +| `required` | `required` | (optional) Input required | `boolean` | `undefined` | +| `resize` | `resize` | (optional) textarea resize | `"horizontal" \| "none" \| "unset" \| "vertical"` | `undefined` | +| `rows` | `rows` | (optional) textarea row | `number` | `undefined` | +| `status` | `status` | **[DEPRECATED]** - invalid should replace status

| `string` | `''` | +| `styles` | `styles` | (optional) Injected CSS styles | `string` | `undefined` | +| `transparent` | `transparent` | (optional) input background transparent | `boolean` | `undefined` | +| `value` | `value` | (optional) Input value | `number \| string` | `''` | +| `variant` | `variant` | (optional) Variant | `"danger" \| "informational" \| "success" \| "warning"` | `'informational'` | ## Events diff --git a/packages/components/src/components/textarea/textarea.tsx b/packages/components/src/components/textarea/textarea.tsx index 3405e05c51..b8d39bc831 100644 --- a/packages/components/src/components/textarea/textarea.tsx +++ b/packages/components/src/components/textarea/textarea.tsx @@ -77,6 +77,8 @@ export class Textarea { @Prop() inputAutofocus?: boolean; /** (optional) Injected CSS styles */ @Prop() styles?: string; + /** (optional) id or space separated list of ids of elements that provide or link to additional related information. */ + @Prop() ariaDetailsId?: string; /** Emitted when a keyboard input occurred. */ @Event({ eventName: 'scale-input' }) scaleInput!: EventEmitter; @@ -173,7 +175,8 @@ export class Textarea { const ariaInvalidAttr = this.status === 'error' || this.invalid ? { 'aria-invalid': 'true' } : {}; const helperTextId = `helper-message-${this.internalId}`; - const ariaDescribedByAttr = { 'aria-describedBy': helperTextId }; + const describedBy = this.helperText ? helperTextId : this.ariaDetailsId; + const ariaDescribedByAttr = { 'aria-describedBy': describedBy }; const readonlyAttr = this.readonly ? { readonly: 'readonly' } : {}; return ( @@ -212,7 +215,10 @@ export class Textarea { {...(!!this.rows ? { rows: this.rows } : {})} {...(!!this.cols ? { cols: this.cols } : {})} {...ariaInvalidAttr} - {...(this.helperText ? ariaDescribedByAttr : {})} + {...(this.helperText || this.ariaDetailsId + ? ariaDescribedByAttr + : {})} + aria-details={this.ariaDetailsId} ref={(el) => (this.focusableElement = el)} /> diff --git a/packages/storybook-vue/stories/components/checkbox/Checkbox.stories.mdx b/packages/storybook-vue/stories/components/checkbox/Checkbox.stories.mdx index 915a66902d..61b9b7c4fc 100644 --- a/packages/storybook-vue/stories/components/checkbox/Checkbox.stories.mdx +++ b/packages/storybook-vue/stories/components/checkbox/Checkbox.stories.mdx @@ -68,8 +68,9 @@ export const Template = (args, { argTypes }) => ({ ```css scale-checkbox { --spacing-x: var(--telekom-spacing-composition-space-04); - --transition: all var(--telekom-motion-duration-transition) - var(--telekom-motion-easing-standard); + --transition: all var(--telekom-motion-duration-transition) var( + --telekom-motion-easing-standard + ); --color-text: var(--telekom-color-text-and-icon-standard); --color-error: var(--telekom-color-functional-danger-standard); --color-disabled: var(--telekom-color-text-and-icon-disabled); @@ -254,4 +255,4 @@ scale-checkbox { >
-``` \ No newline at end of file +``` diff --git a/packages/storybook-vue/stories/components/checkbox/ScaleCheckbox.vue b/packages/storybook-vue/stories/components/checkbox/ScaleCheckbox.vue index 6aa6a2d29a..99353851b7 100644 --- a/packages/storybook-vue/stories/components/checkbox/ScaleCheckbox.vue +++ b/packages/storybook-vue/stories/components/checkbox/ScaleCheckbox.vue @@ -31,7 +31,8 @@ export default { value: { type: String }, inputId: { type: String }, required: { type: Boolean }, - ariaLabelCheckbox: { type: String} + ariaLabelCheckbox: { type: String }, + ariaDetailsId: { type: String }, }, methods: { scaleChange($event) { diff --git a/packages/storybook-vue/stories/components/date-picker/DatePicker.stories.mdx b/packages/storybook-vue/stories/components/date-picker/DatePicker.stories.mdx index d43cb7f1b9..4ae56bf53e 100644 --- a/packages/storybook-vue/stories/components/date-picker/DatePicker.stories.mdx +++ b/packages/storybook-vue/stories/components/date-picker/DatePicker.stories.mdx @@ -204,7 +204,7 @@ export const RangeTemplate = (args, { argTypes }) => ({ args={{ value: '2020-12-31', label: 'Standard', - placeholder: 'Select date' + placeholder: 'Select date', }} > {Template.bind({})} @@ -251,8 +251,9 @@ duet-date-picker { --font-size-day: var(--telekom-typography-font-size-body); --font-size-table-header: var(--telekom-typography-font-size-caption); --font-weight-table-header: var(--telekom-typography-font-weight-extra-bold); - --focus-outline: var(--telekom-line-weight-highlight) solid - var(--telekom-color-functional-focus-standard); + --focus-outline: var(--telekom-line-weight-highlight) solid var( + --telekom-color-functional-focus-standard + ); --z-index-label: 10; } @@ -290,7 +291,7 @@ duet-date-picker { label: 'With Error', invalid: true, helperText: 'something is wrong', - placeholder: 'select date' + placeholder: 'select date', }} > {Template.bind({})} diff --git a/packages/storybook-vue/stories/components/date-picker/ScaleDatePicker.vue b/packages/storybook-vue/stories/components/date-picker/ScaleDatePicker.vue index 7dc8496b8b..087eaeda1c 100644 --- a/packages/storybook-vue/stories/components/date-picker/ScaleDatePicker.vue +++ b/packages/storybook-vue/stories/components/date-picker/ScaleDatePicker.vue @@ -50,6 +50,7 @@ export default { styles: { type: String }, placeholder: { type: String }, size: { type: String }, + ariaDetailsId: { type: String }, }, methods: { scaleChange($event) { diff --git a/packages/storybook-vue/stories/components/dropdown-select/DropdownSelect.stories.mdx b/packages/storybook-vue/stories/components/dropdown-select/DropdownSelect.stories.mdx index b295b8e77e..ee7c61bec7 100644 --- a/packages/storybook-vue/stories/components/dropdown-select/DropdownSelect.stories.mdx +++ b/packages/storybook-vue/stories/components/dropdown-select/DropdownSelect.stories.mdx @@ -13,8 +13,8 @@ import { action } from '@storybook/addon-actions'; export const Template = (args, { argTypes }) => ({ components: { ScaleDropdownSelect }, props: { - itemProps: { default: {} }, - ...ScaleDropdownSelect.props, + itemProps: { default: {} }, + ...ScaleDropdownSelect.props, }, data() { return { @@ -106,18 +106,22 @@ export const Template = (args, { argTypes }) => ({ --color-disabled: var(--telekom-color-text-and-icon-disabled); --background-disabled: none; --background-hover: var(--telekom-color-ui-state-fill-hovered); - --border: var(--telekom-spacing-composition-space-01) solid - var(--telekom-color-ui-border-standard); + --border: var(--telekom-spacing-composition-space-01) solid var( + --telekom-color-ui-border-standard + ); --border-color-hover: var(--telekom-color-ui-border-hovered); --border-color-focus: var(--telekom-color-ui-border-hovered); --border-color-disabled: var(--telekom-color-ui-border-disabled); - --border-invalid: var(--telekom-spacing-composition-space-02) solid - var(--telekom-color-functional-danger-hovered); - --focus-outline: var(--telekom-line-weight-highlight) solid - var(--telekom-color-functional-focus-standard); + --border-invalid: var(--telekom-spacing-composition-space-02) solid var( + --telekom-color-functional-danger-hovered + ); + --focus-outline: var(--telekom-line-weight-highlight) solid var( + --telekom-color-functional-focus-standard + ); --spacing-x: var(--telekom-spacing-composition-space-05); - --transition: all var(--telekom-motion-duration-transition) - var(--telekom-motion-easing-standard); + --transition: all var(--telekom-motion-duration-transition) var( + --telekom-motion-easing-standard + ); --radius: var(--telekom-radius-standard); --spacing-x-for-helper-text: var(--telekom-spacing-composition-space-03); @@ -128,9 +132,9 @@ export const Template = (args, { argTypes }) => ({ 18px 32px 4px 12px (subtracting 1px from border) */ - --spacing-combobox: 1.125rem - calc(2rem - var(--telekom-spacing-composition-space-01)) 0.25rem - calc(0.75rem - var(--telekom-spacing-composition-space-01)); + --spacing-combobox: 1.125rem calc( + 2rem - var(--telekom-spacing-composition-space-01) + ) 0.25rem calc(0.75rem - var(--telekom-spacing-composition-space-01)); /*meta*/ --spacing-y-meta: var(--telekom-spacing-composition-space-03); @@ -155,17 +159,16 @@ export const Template = (args, { argTypes }) => ({ /*listbox*/ --background-listbox: var(--telekom-color-background-surface); - --box-shadow-listbox: 0 2px 4px 0 rgba(0, 0, 0, 0.1), - 0 4px 16px 0 rgba(0, 0, 0, 0.1); + --box-shadow-listbox: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 4px 16px 0 rgba(0, 0, 0, 0.1); --max-height-listbox: 300px; --z-index-listbox: 99; } - ``` ## Disabled ### Whole Dropdown Select disabled + ({ ``` ### Individual items disabled + ({ ```html - Caspar - Cedric + Caspar + Cedric Cem ``` diff --git a/packages/storybook-vue/stories/components/dropdown-select/ScaleDropdownSelect.vue b/packages/storybook-vue/stories/components/dropdown-select/ScaleDropdownSelect.vue index 7b4ad43c48..9b63c21bb4 100644 --- a/packages/storybook-vue/stories/components/dropdown-select/ScaleDropdownSelect.vue +++ b/packages/storybook-vue/stories/components/dropdown-select/ScaleDropdownSelect.vue @@ -35,6 +35,7 @@ export default { comboboxId: { type: String }, hideLabelVisually: { type: Boolean, default: false }, floatingStrategy: { type: String }, + ariaDetailsId: { type: String }, }, methods: { 'scale-change'($event) { diff --git a/packages/storybook-vue/stories/components/dropdown/DropDown.stories.mdx b/packages/storybook-vue/stories/components/dropdown/DropDown.stories.mdx index 4f6dea162e..39fee2f627 100644 --- a/packages/storybook-vue/stories/components/dropdown/DropDown.stories.mdx +++ b/packages/storybook-vue/stories/components/dropdown/DropDown.stories.mdx @@ -97,24 +97,31 @@ export const Template = (args, { argTypes }) => ({ --font-weight: var(--telekom-typography-font-weight-bold); --height: var(--telekom-spacing-composition-space-13); --spacing-x: var(--telekom-spacing-composition-space-05); - --spacing-dropdown: 18px var(--telekom-spacing-composition-space-12) 5px - calc(var(--spacing-x) - 1px); - --transition: all var(--telekom-motion-duration-transition) - var(--telekom-motion-easing-standard); + --spacing-dropdown: 18px var(--telekom-spacing-composition-space-12) 5px calc( + var(--spacing-x) - 1px + ); + --transition: all var(--telekom-motion-duration-transition) var( + --telekom-motion-easing-standard + ); --radius: var(--telekom-radius-standard); - --border: var(--telekom-spacing-composition-space-01) solid - var(--telekom-color-ui-border-standard); - --border-danger: var(--telekom-spacing-composition-space-02) solid - var(--telekom-color-functional-danger-standard); - --border-success: var(--telekom-spacing-composition-space-02) solid - var(--telekom-color-functional-success-standard); - --border-warning: var(--telekom-spacing-composition-space-02) solid - var(--telekom-color-functional-warning-standard); + --border: var(--telekom-spacing-composition-space-01) solid var( + --telekom-color-ui-border-standard + ); + --border-danger: var(--telekom-spacing-composition-space-02) solid var( + --telekom-color-functional-danger-standard + ); + --border-success: var(--telekom-spacing-composition-space-02) solid var( + --telekom-color-functional-success-standard + ); + --border-warning: var(--telekom-spacing-composition-space-02) solid var( + --telekom-color-functional-warning-standard + ); --border-color-hover: var(--telekom-color-ui-border-hovered); --border-color-focus: var(--telekom-color-ui-border-hovered); --border-color-disabled: var(--telekom-color-ui-border-disabled); - --focus-outline: var(--telekom-line-weight-highlight) solid - var(--telekom-color-functional-focus-standard); + --focus-outline: var(--telekom-line-weight-highlight) solid var( + --telekom-color-functional-focus-standard + ); --color-disabled: var(--telekom-color-text-and-icon-disabled); --background-disabled: none; --color: var(--telekom-color-text-and-icon-standard); @@ -267,6 +274,9 @@ The display error is on the browser side. - + ``` diff --git a/packages/storybook-vue/stories/components/dropdown/ScaleDropDown.vue b/packages/storybook-vue/stories/components/dropdown/ScaleDropDown.vue index d4de8dad51..34cded1916 100644 --- a/packages/storybook-vue/stories/components/dropdown/ScaleDropDown.vue +++ b/packages/storybook-vue/stories/components/dropdown/ScaleDropDown.vue @@ -40,6 +40,7 @@ export default { controlled: { type: Boolean }, styles: { type: String }, size: { type: String }, + ariaDetailsId: { type: String }, }, methods: { scaleInput($event) { diff --git a/packages/storybook-vue/stories/components/radio-button-group/RadioButtonGroup.stories.mdx b/packages/storybook-vue/stories/components/radio-button-group/RadioButtonGroup.stories.mdx index e7d12e2a55..3cc4a0ac29 100644 --- a/packages/storybook-vue/stories/components/radio-button-group/RadioButtonGroup.stories.mdx +++ b/packages/storybook-vue/stories/components/radio-button-group/RadioButtonGroup.stories.mdx @@ -54,8 +54,8 @@ export const Template = (args, context) => ({ :disabled="itemProps[index]?.disabled" > - ` -}) + `, +});
({ {Template.bind({})} @@ -137,8 +137,9 @@ scale-radio-button { --color-disabled: var(--telekom-color-text-and-icon-disabled); --background-disabled: var(--telekom-color-ui-disabled); --color-error: var(--telekom-color-text-and-icon-functional-danger); - --transition: all var(--telekom-motion-duration-transition) - var(--telekom-motion-easing-standard); + --transition: all var(--telekom-motion-duration-transition) var( + --telekom-motion-easing-standard + ); --color-primary: var(--telekom-color-text-and-icon-primary-standard); --color-primary-hover: var(--telekom-color-text-and-icon-standard); --color-primary-active: var(--telekom-color-text-and-icon-standard); @@ -171,26 +172,29 @@ scale-radio-button { --height-control: var(--telekom-spacing-composition-space-07); --transition-control: var(--transition); --background-color-control: var(--telekom-color-ui-base); - --border-control: var(--telekom-spacing-composition-space-01) solid - var(--telekom-color-ui-border-standard); + --border-control: var(--telekom-spacing-composition-space-01) solid var( + --telekom-color-ui-border-standard + ); --line-height-helper-text: var(--telekom-typography-line-spacing-standard); --border-control-checked: calc( 0.25 * var(--telekom-spacing-composition-space-05) - ) - solid var(--telekom-color-background-canvas); + ) solid var(--telekom-color-background-canvas); --border-control-checked-disabled: calc( 0.5 * var(--telekom-spacing-composition-space-05) - ) - solid var(--telekom-color-ui-border-disabled); + ) solid var(--telekom-color-ui-border-disabled); --background-control-checked-disabled: none; - --border-control-active: var(--telekom-spacing-composition-space-04) solid - var(--telekom-color-primary-pressed); - --border-control-disabled: 0 0 0 var(--telekom-spacing-composition-space-01) - var(--telekom-color-ui-border-disabled); - --border-control-error: var(--telekom-spacing-composition-space-02) solid - var(--telekom-color-functional-danger-standard); - --box-shadow-control-focus: 0 0 0 var(--telekom-spacing-composition-space-03) - var(--color-focus); + --border-control-active: var(--telekom-spacing-composition-space-04) solid var( + --telekom-color-primary-pressed + ); + --border-control-disabled: 0 0 0 var(--telekom-spacing-composition-space-01) var( + --telekom-color-ui-border-disabled + ); + --border-control-error: var(--telekom-spacing-composition-space-02) solid var( + --telekom-color-functional-danger-standard + ); + --box-shadow-control-focus: 0 0 0 var(--telekom-spacing-composition-space-03) var( + --color-focus + ); } ``` @@ -233,7 +237,10 @@ scale-radio-button { ```html - + {Template.bind({})} @@ -279,7 +286,11 @@ scale-radio-button { ```html - + {Template.bind({})} diff --git a/packages/storybook-vue/stories/components/radio-button-group/ScaleRadioButton.vue b/packages/storybook-vue/stories/components/radio-button-group/ScaleRadioButton.vue index 6254aaad3a..9404f7ed18 100644 --- a/packages/storybook-vue/stories/components/radio-button-group/ScaleRadioButton.vue +++ b/packages/storybook-vue/stories/components/radio-button-group/ScaleRadioButton.vue @@ -10,15 +10,16 @@ export default { checked: { type: Boolean }, value: { type: String }, inputId: { type: String }, - styles: { type: String } + styles: { type: String }, + ariaDetailsId: { type: String }, }, methods: { fireEvents() { this.$emit('scale-change'); - } + }, }, render() { return this.$slots.default; - } + }, }; diff --git a/packages/storybook-vue/stories/components/text-area/ScaleTextArea.vue b/packages/storybook-vue/stories/components/text-area/ScaleTextArea.vue index 28e4115f48..ac9931bec1 100644 --- a/packages/storybook-vue/stories/components/text-area/ScaleTextArea.vue +++ b/packages/storybook-vue/stories/components/text-area/ScaleTextArea.vue @@ -52,6 +52,7 @@ export default { transparent: { type: Boolean }, inputAutofocus: { type: Boolean }, styles: { type: String }, + ariaDetailsId: { type: String }, }, methods: { scaleInput($event) { diff --git a/packages/storybook-vue/stories/components/text-area/TextArea.stories.mdx b/packages/storybook-vue/stories/components/text-area/TextArea.stories.mdx index 64637c058e..a815809d15 100644 --- a/packages/storybook-vue/stories/components/text-area/TextArea.stories.mdx +++ b/packages/storybook-vue/stories/components/text-area/TextArea.stories.mdx @@ -89,20 +89,24 @@ export const Template = (args, { argTypes }) => ({ ```css scale-textarea { - --transition: all var(--telekom-motion-duration-transition) - var(--telekom-motion-easing-standard); + --transition: all var(--telekom-motion-duration-transition) var( + --telekom-motion-easing-standard + ); --radius: var(--telekom-radius-standard); - --border: var(--telekom-line-weight-standard) solid - var(--telekom-color-ui-border-standard); - --border-error: var(--telekom-line-weight-highlight) solid - var(--telekom-color-functional-danger-standard); + --border: var(--telekom-line-weight-standard) solid var( + --telekom-color-ui-border-standard + ); + --border-error: var(--telekom-line-weight-highlight) solid var( + --telekom-color-functional-danger-standard + ); --border-color-hover: var(--telekom-color-ui-border-hovered); --border-color-focus: var(--telekom-color-ui-border-hovered); --border-color-disabled: var(--telekom-color-ui-border-disabled); --background-color-hover: var(--telekom-color-ui-state-fill-hovered); --background-color-disabled: none; - --focus-outline: var(--telekom-line-weight-highlight) solid - var(--telekom-color-functional-focus-standard); + --focus-outline: var(--telekom-line-weight-highlight) solid var( + --telekom-color-functional-focus-standard + ); --spacing-x-control: var(--telekom-spacing-composition-space-05); --spacing-bottom-control: var(--telekom-spacing-composition-space-05); --spacing-top-control: calc( @@ -126,8 +130,8 @@ scale-textarea { 18px 32px 4px 12px (subtracting 1px from border) */ - --spacing-control: 0 calc(2rem - var(--telekom-spacing-composition-space-01)) - 0.25rem calc(0.75rem - var(--telekom-spacing-composition-space-01)); + --spacing-control: 0 calc(2rem - var(--telekom-spacing-composition-space-01)) 0.25rem + calc(0.75rem - var(--telekom-spacing-composition-space-01)); --transition-control: var(--transition); --background-control: var(--telekom-color-ui-state-fill-standard); @@ -236,9 +240,9 @@ scale-textarea { {Template.bind({})} @@ -246,7 +250,11 @@ scale-textarea { ```html - + ``` ## Max Length With Counter