From 5ff00f91acb1a97695af97a9d8b9ef9a7e7018aa Mon Sep 17 00:00:00 2001 From: mertsincan Date: Fri, 29 Jul 2022 01:56:28 +0100 Subject: [PATCH] Fixed #2811 - Improve Dropdown implementation for Accessibility --- api-generator/components/dropdown.js | 171 +++-- src/components/dropdown/Dropdown.d.ts | 134 ++-- src/components/dropdown/Dropdown.vue | 975 +++++++++++++++----------- 3 files changed, 768 insertions(+), 512 deletions(-) diff --git a/api-generator/components/dropdown.js b/api-generator/components/dropdown.js index 8bad4e2db..bb728aed6 100644 --- a/api-generator/components/dropdown.js +++ b/api-generator/components/dropdown.js @@ -107,12 +107,6 @@ const DropdownProps = [ default: "false", description: "When enabled, a clear icon is displayed to clear the value." }, - { - name: "tabindex", - type: "number", - default: "null", - description: "Index of the element in tabbing order." - }, { name: "inputId", type: "string", @@ -120,22 +114,28 @@ const DropdownProps = [ description: "Identifier of the underlying input element." }, { - name: "ariaLabelledBy", + name: "inputStyle", + type: "object", + default: "null", + description: "Inline style of the input field." + }, + { + name: "inputClass", type: "string", default: "null", - description: '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.' + description: "Style class of the input field." }, { - name: "emptyFilterMessage", - 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: "inputProps", + type: "object", + default: "null", + description: "Uses to pass all properties of the HTMLInputElement/HTMLSpanElement to the focusable input element inside the component." }, { - name: "emptyMessage", - type: "string", - default: "No results found", - description: "Text to display when there are no options available. Defaults to value from PrimeVue locale configuration." + name: "panelStyle", + type: "object", + default: "null", + description: "Inline style of the overlay panel." }, { name: "panelClass", @@ -143,6 +143,30 @@ const DropdownProps = [ 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: "filterInputProps", + type: "object", + default: "null", + description: "Uses to pass all properties of the HTMLInputElement to the filter input inside the component." + }, + { + name: "clearIconProps", + type: "object", + default: "null", + description: "Uses to pass all properties of the HTMLElement to the clear icon inside the component." + }, + { + name: "appendTo", + type: "string", + default: "body", + description: "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." + }, { name: "loading", type: "boolean", @@ -160,6 +184,60 @@ const DropdownProps = [ type: "object", default: "null", description: "Whether to use the virtualScroller feature. The properties of VirtualScroller component can be used like an object in it." + }, + { + name: "autoOptionFocus", + type: "boolean", + default: "true", + description: "Whether to focus on the first visible or selected element when the overlay panel is shown." + }, + { + name: "filterMessage", + 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: "emptyFilterMessage", + 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: "emptyMessage", + type: "string", + default: "No results found", + description: "Text to display when there are no options available. Defaults to value from PrimeVue locale configuration." + }, + { + name: "tabindex", + type: "number", + default: "null", + description: "Index of the element in tabbing order." + }, + { + name: "ariaLabel", + type: "string", + default: "null", + description: "Defines a string value that labels an interactive element." + } + { + name: "ariaLabelledby", + type: "string", + default: "null", + description: "Identifier of the underlying input element." } ]; @@ -181,8 +259,19 @@ const DropdownEvents = [ ] }, { - name: "input", - description: "Callback to invoke on value change.", + 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", @@ -207,28 +296,6 @@ const DropdownEvents = [ name: "hide", description: "Callback to invoke when the overlay is hidden." }, - { - 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: "filter", description: "Callback to invoke when the overlay is shown.", @@ -248,18 +315,14 @@ const DropdownEvents = [ ]; const DropdownSlots = [ - { - name: "option", - description: "Custom content for the item's option" - }, - { - name: "optiongroup", - description: "Custom content for the item's optiongroup" - }, { name: "value", description: "Custom content for the item's value" }, + { + name: "indicator", + description: "Custom content for the dropdown indicator" + }, { name: "header", description: "Custom content for the component's header" @@ -268,6 +331,14 @@ const DropdownSlots = [ name: "footer", description: "Custom content for the component's footer" }, + { + name: "option", + description: "Custom content for the item's option" + }, + { + name: "optiongroup", + description: "Custom content for the item's optiongroup" + }, { name: "emptyfilter", description: "Custom content when there is no filtered data to display" @@ -283,10 +354,6 @@ const DropdownSlots = [ { name: "loader", description: "Custom content for the virtual scroller loader items" - }, - { - name: "indicator", - description: "Custom content for the dropdown indicator" } ]; diff --git a/src/components/dropdown/Dropdown.d.ts b/src/components/dropdown/Dropdown.d.ts index 03ba11352..e99240d6d 100755 --- a/src/components/dropdown/Dropdown.d.ts +++ b/src/components/dropdown/Dropdown.d.ts @@ -2,13 +2,13 @@ import { VNode } from 'vue'; import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers'; import { VirtualScrollerProps, VirtualScrollerItemOptions } from '../virtualscroller'; -type DropdownOptionLabelType = string | ((data: any) => string) | undefined; +type DropdownOptionLabelType = string | ((data: any) => string) | undefined; -type DropdownOptionValueType = string | ((data: any) => any) | undefined; +type DropdownOptionValueType = string | ((data: any) => any) | undefined; -type DropdownOptionDisabledType = string | ((data: any) => boolean) | undefined; +type DropdownOptionDisabledType = string | ((data: any) => boolean) | undefined; -type DropdownOptionChildrenType = string | ((data: any) => any[]) | undefined; +type DropdownOptionChildrenType = string | ((data: any) => any[]) | undefined; type DropdownFilterMatchModeType = 'contains' | 'startsWith' | 'endsWith' | undefined; @@ -117,38 +117,48 @@ export interface DropdownProps { * When enabled, a clear icon is displayed to clear the value. */ showClear?: boolean | undefined; - /** - * Index of the element in tabbing order. - */ - tabindex?: number | string | undefined; /** * Identifier of the underlying input element. */ inputId?: string | undefined; /** - * Identifier of the underlying input element. + * Inline style of the input field. */ - ariaLabelledBy?: string | undefined; + inputStyle?: any; + /** + * Style class of the input field. + */ + inputClass?: any; + /** + * Uses to pass all properties of the HTMLInputElement/HTMLSpanElement to the focusable input element inside the component. + */ + inputProps?: HTMLInputElement | HTMLSpanElement | 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; + /** + * Uses to pass all properties of the HTMLInputElement to the filter input inside the component. + */ + filterInputProps?: HTMLInputElement | undefined; + /** + * Uses to pass all properties of the HTMLElement to the clear icon inside the component. + */ + clearIconProps?: HTMLElement | 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 DropdownAppendToType * Default value is 'body'. */ appendTo?: DropdownAppendToType; - /** - * Text to display when filtering does not return any results. Defaults to value from PrimeVue locale configuration. - * Default value is 'No results found'. - */ - emptyFilterMessage?: string | undefined; - /** - * Text to display when there are no options available. Defaults to value from PrimeVue locale configuration. - * Default value is 'No results found'. - */ - emptyMessage?: string | undefined; - /** - * Style class of the overlay panel. - */ - panelClass?: any; /** * Whether the dropdown is in loading state. */ @@ -163,6 +173,48 @@ export interface DropdownProps { * @see VirtualScroller.VirtualScrollerProps */ virtualScrollerOptions?: VirtualScrollerProps; + /** + * Whether to focus on the first visible or selected element when the overlay panel is shown. + * Default value is true. + */ + autoOptionFocus?: boolean | undefined; + /** + * 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'. + */ + filterMessage?: 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'. + */ + selectionMessage?: string | undefined; + /** + * 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'. + */ + 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'. + */ + emptyFilterMessage?: string | undefined; + /** + * Text to display when there are no options available. Defaults to value from PrimeVue locale configuration. + * Default value is 'No results found'. + */ + emptyMessage?: string | undefined; + /** + * Index of the element in tabbing order. + */ + tabindex?: number | string | undefined; + /** + * Defines a string value that labels an interactive element. + */ + ariaLabel?: string | undefined; + /** + * Identifier of the underlying input element. + */ + ariaLabelledby?: string | undefined; } export interface DropdownSlots { @@ -180,6 +232,10 @@ export interface DropdownSlots { */ placeholder: string; }) => VNode[]; + /** + * Custom indicator template. + */ + indicator: () => VNode[]; /** * Custom header template of panel. * @param {Object} scope - header slot's params. @@ -279,10 +335,6 @@ export interface DropdownSlots { */ options: any[]; }) => VNode[]; - /** - * Custom indicator template. - */ - indicator: () => VNode[]; } export declare type DropdownEmits = { @@ -296,6 +348,16 @@ export declare type DropdownEmits = { * @param {DropdownChangeEvent} event - Custom change event. */ 'change': (event: DropdownChangeEvent) => void; + /** + * Callback to invoke when the component receives focus. + * @param {Event} event - Browser event. + */ + 'focus': (event: Event) => void; + /** + * Callback to invoke when the component loses focus. + * @param {Event} event - Browser event. + */ + 'blur': (event: Event) => void; /** * Callback to invoke before the overlay is shown. */ @@ -312,16 +374,6 @@ export declare type DropdownEmits = { * Callback to invoke when the overlay is hidden. */ 'hide': () => void; - /** - * Callback to invoke when the component receives focus. - * @param {Event} event - Browser event. - */ - 'focus': (event: Event) => void; - /** - * Callback to invoke when the component loses focus. - * @param {Event} event - Browser event. - */ - 'blur': () => void; /** * Callback to invoke on filter input. * @param {DropdownFilterEvent} event - Custom filter event. @@ -332,16 +384,18 @@ export declare type DropdownEmits = { declare class Dropdown extends ClassComponent { /** * Shows the overlay. + * @param {boolean} [isFocus] - Decides whether to focus on the component. Default value is false. * * @memberof Dropdown */ - show: () => void; + show: (isFocus?: boolean) => void; /** * Hides the overlay. + * @param {boolean} [isFocus] - Decides whether to focus on the component. Default value is false. * * @memberof Dropdown */ - hide: () => void; + hide: (isFocus?: boolean) => void; } declare module '@vue/runtime-core' { diff --git a/src/components/dropdown/Dropdown.vue b/src/components/dropdown/Dropdown.vue index 8684667f3..2e50b6a01 100755 --- a/src/components/dropdown/Dropdown.vue +++ b/src/components/dropdown/Dropdown.vue @@ -1,65 +1,68 @@