From f66fc40c3cef5490d079f6a35c69c5e887e53ff3 Mon Sep 17 00:00:00 2001 From: mertsincan Date: Sun, 7 Aug 2022 23:49:21 +0100 Subject: [PATCH] Fixed #2831 - Improve CascadeSelect implementation for Accessibility --- api-generator/components/cascadeselect.js | 137 +++- .../cascadeselect/CascadeSelect.d.ts | 103 ++- .../cascadeselect/CascadeSelect.vue | 713 ++++++++++++++---- .../cascadeselect/CascadeSelectSub.vue | 179 ++--- 4 files changed, 801 insertions(+), 331 deletions(-) diff --git a/api-generator/components/cascadeselect.js b/api-generator/components/cascadeselect.js index c7dc8519e..cf188cf63 100644 --- a/api-generator/components/cascadeselect.js +++ b/api-generator/components/cascadeselect.js @@ -23,6 +23,12 @@ const CascadeSelectProps = [ default: "null", description: "Property name or getter function to use as the value of an option, defaults to the option itself when not defined." }, + { + name: "optionDisabled", + type: "boolean", + default: "null", + description: "Property name or getter function to use as the disabled flag of an option, defaults to false when not defined." + }, { name: "optionGroupLabel", type: "string | function", @@ -54,10 +60,40 @@ const CascadeSelectProps = [ description: "A property to uniquely identify an option." }, { - name: "tabindex", - type: "number", + name: "inputStyle", + type: "object", default: "null", - description: "Index of the element in tabbing order." + description: "Inline style of the input field." + }, + { + name: "inputClass", + type: "string", + default: "null", + description: "Style class of the input field." + }, + { + name: "inputProps", + type: "object", + default: "null", + description: "Uses to pass all properties of the HTMLInputElement/HTMLSpanElement to the focusable input element inside the component." + }, + { + name: "panelStyle", + type: "object", + default: "null", + description: "Inline style of the overlay panel." + }, + { + name: "panelClass", + type: "string", + default: "null", + description: "Style class of the overlay panel." + }, + { + name: "panelProps", + type: "object", + default: "null", + description: "Uses to pass all properties of the HTMLDivElement to the overlay panel inside the component." }, { name: "appendTo", @@ -78,22 +114,58 @@ const CascadeSelectProps = [ description: "Icon to display in loading state." }, { - name: "inputId", + name: "autoOptionFocus", + type: "boolean", + default: "true", + description: "Whether to focus on the first visible or selected element when the overlay panel is shown." + }, + { + name: "searchLocale", + type: "string", + default: "undefined", + description: "Locale to use in searching. The default locale is the host environment's current locale." + }, + { + name: "searchMessage", + type: "string", + default: "{0} results are available", + description: "Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration." + }, + { + name: "selectionMessage", + type: "string", + default: "{0} items selected", + description: "Text to be displayed in hidden accessible field when options are selected. Defaults to value from PrimeVue locale configuration." + }, + { + name: "emptySelectionMessage", + type: "string", + default: "No selected item", + description: "Text to be displayed in hidden accessible field when any option is not selected. Defaults to value from PrimeVue locale configuration." + }, + { + name: "emptySearchMessage", + type: "string", + default: "No results found", + description: "Text to display when filtering does not return any results. Defaults to value from PrimeVue locale configuration." + }, + { + name: "tabindex", + type: "number", + default: "0", + description: "Index of the element in tabbing order." + }, + { + name: "aria-label", + type: "string", + default: "null", + description: "Defines a string value that labels an interactive element." + }, + { + name: "aria-labelledby", type: "string", default: "null", description: "Identifier of the underlying input element." - }, - { - name: "inputClass", - type: "any", - default: "null", - description: "Style class of the input field." - }, - { - name: "inputStyle", - type: "any", - default: "null", - description: "Inline style of the input field." } ]; @@ -114,6 +186,39 @@ const CascadeSelectEvents = [ } ] }, + { + name: "focus", + description: "Callback to invoke when component receives focus.", + arguments: [ + { + name: "event", + type: "object", + description: "Browser event" + } + ] + }, + { + name: "blur", + description: "Callback to invoke when component loses focus.", + arguments: [ + { + name: "event", + type: "object", + description: "Browser event" + } + ] + }, + { + name: "click", + description: "Callback to invoke on click.", + arguments: [ + { + name: "event", + type: "object", + description: "Browser event" + } + ] + }, { name: "group-change", description: "Callback to invoke when a group changes.", diff --git a/src/components/cascadeselect/CascadeSelect.d.ts b/src/components/cascadeselect/CascadeSelect.d.ts index 162b0e907..68221250c 100644 --- a/src/components/cascadeselect/CascadeSelect.d.ts +++ b/src/components/cascadeselect/CascadeSelect.d.ts @@ -1,11 +1,13 @@ import { VNode } from 'vue'; import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers'; -type CascadeSelectOptionLabelType = string | ((data: any) => string) | undefined; +type CascadeSelectOptionLabelType = string | ((data: any) => string) | undefined; -type CascadeSelectOptionValueType = string | ((data: any) => any) | undefined; +type CascadeSelectOptionValueType = string | ((data: any) => any) | undefined; -type CascadeSelectOptionChildrenType = string[] | string | ((data: any) => any[]) | undefined; +type CascadeSelectOptionDisabledType = string | ((data: any) => boolean) | undefined; + +type CascadeSelectOptionChildrenType = string[] | string | ((data: any) => any[]) | undefined; type CascadeSelectAppendToType = 'body' | 'self' | string | undefined | HTMLElement; @@ -23,7 +25,7 @@ export interface CascadeSelectChangeEvent { /** * @extends CascadeSelectChangeEvent */ -export interface CascadeSelectChangeGroupEvent extends CascadeSelectChangeEvent { } +export interface CascadeSelectGroupChangeEvent extends CascadeSelectChangeEvent { } export interface CascadeSelectProps { /** @@ -44,6 +46,11 @@ export interface CascadeSelectProps { * @see CascadeSelectOptionValueType */ optionValue?: CascadeSelectOptionValueType; + /** + * Property name or getter function to use as the disabled flag of an option, defaults to false when not defined. + * @see CascadeSelectOptionDisabledType + */ + optionDisabled?: CascadeSelectOptionDisabledType; /** * Property name or getter function to use as the label of an option group. * @see CascadeSelectOptionLabelType @@ -67,9 +74,33 @@ export interface CascadeSelectProps { */ dataKey?: string | undefined; /** - * Index of the element in tabbing order. + * Identifier of the underlying input element. */ - tabindex?: string | undefined; + inputId?: string | undefined; + /** + * Inline style of the input field. + */ + inputStyle?: any; + /** + * Style class of the input field. + */ + inputClass?: any; + /** + * Uses to pass all properties of the HTMLInputElement to the focusable input element inside the component. + */ + inputProps?: HTMLInputElement | undefined; + /** + * Inline style of the overlay panel. + */ + panelStyle?: any; + /** + * Style class of the overlay panel. + */ + panelClass?: any; + /** + * Uses to pass all properties of the HTMLDivElement to the overlay panel inside the component. + */ + panelProps?: HTMLDivElement | undefined; /** * A valid query selector or an HTMLElement to specify where the overlay gets attached. Special keywords are 'body' for document body and 'self' for the element itself. * @see CascadeSelectAppendToType @@ -86,30 +117,43 @@ export interface CascadeSelectProps { */ loadingIcon?: string | undefined; /** - * Identifier of the underlying input element. + * Whether to focus on the first visible or selected element when the overlay panel is shown. + * Default value is true. */ - inputId?: string | undefined; + autoOptionFocus?: boolean | undefined; /** - * Style class of the input field. + * Locale to use in searching. The default locale is the host environment's current locale. */ - inputClass?: any | undefined; + searchLocale?: string | undefined; /** - * Inline style of the input field. + * Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration. + * Default value is '{0} results are available'. */ - inputStyle?: any | undefined; + searchMessage?: string | undefined; /** - * + * Text to be displayed in hidden accessible field when options are selected. Defaults to value from PrimeVue locale configuration. + * Default value is '{0} items selected'. */ - inputProps?: object | undefined; + selectionMessage?: string | undefined; /** - * Style class of the overlay panel. + * Text to be displayed in hidden accessible field when any option is not selected. Defaults to value from PrimeVue locale configuration. + * Default value is 'No selected item'. */ - panelClass?: any; + emptySelectionMessage?: string | undefined; /** - * + * Text to display when filtering does not return any results. Defaults to value from PrimeVue locale configuration. + * Default value is 'No results found'. */ - panelProps?: object | undefined; - + emptySearchMessage?: string | undefined; + /** + * Text to be displayed when there are no options available. Defaults to value from PrimeVue locale configuration. + * Default value is 'No available options'. + */ + emptyMessage?: string | undefined; + /** + * Index of the element in tabbing order. + */ + tabindex?: number | string | undefined; /** * Establishes relationships between the component and label(s) where its value should be one or more element IDs. */ @@ -163,10 +207,25 @@ export declare type CascadeSelectEmits = { */ 'change': (event: CascadeSelectChangeEvent) => void; /** - * Callback to invoke when a group changes. - * @param { CascadeSelectChangeGroupEvent } event - Custom change event. + * Callback to invoke when the component receives focus. + * @param {Event} event - Browser event. */ - 'change-group': (event: CascadeSelectChangeGroupEvent) => void; + 'focus': (event: Event) => void; + /** + * Callback to invoke when the component loses focus. + * @param {Event} event - Browser event. + */ + 'blur': (event: Event) => void; + /** + * Callback to invoke on click. + * @param { Event } event - Browser event. + */ + 'click': (event: Event) => void; + /** + * Callback to invoke when a group changes. + * @param { CascadeSelectGroupChangeEvent } event - Custom change event. + */ + 'group-change': (event: CascadeSelectGroupChangeEvent) => void; /** * Callback to invoke before the overlay is shown. */ diff --git a/src/components/cascadeselect/CascadeSelect.vue b/src/components/cascadeselect/CascadeSelect.vue index f3635da95..badf1b062 100644 --- a/src/components/cascadeselect/CascadeSelect.vue +++ b/src/components/cascadeselect/CascadeSelect.vue @@ -1,27 +1,34 @@