Improve experimental select control accessibility (#34510)

* Use downshift built in methods to handle selection of items

* Fix menu styling

* Fix removal a11y announcement

* Don't show menu without results

* Fix async example a11y

* Add changelog entry

* Deselect item in state on remove

* Fix formatting issues

* Update lock file

* Update lock file after pnpm7

* Skip lib check breaking oclif build in package-release

* Rebase again and fix up lock file

* Skip lib check in monorepo-merge

* Fix the lock

* Ignore lint

Co-authored-by: Sam Seay <samueljseay@gmail.com>
Co-authored-by: Jonathan Sadowski <sadowski@automattic.com>
This commit is contained in:
Joshua T Flowers 2022-09-20 14:29:27 -07:00 committed by GitHub
parent d2b20dc993
commit f39d8b6b39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 22 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: enhancement
Improve experimental SelectControl accessibility

View File

@ -4,14 +4,11 @@
top: 100%;
box-sizing: border-box;
display: none;
background: $studio-white;
border: 1px solid $studio-gray-5;
border-radius: 3px;
&.is-open {
&.is-open.has-results {
display: block;
}
.woocommerce-experimental-select-control__menu-inner {
background: $studio-white;
border: 1px solid $studio-gray-5;
border-radius: 3px;
}
}

View File

@ -17,21 +17,19 @@ type MenuProps = {
export const Menu = ( { children, getMenuProps, isOpen }: MenuProps ) => {
return (
<div
<ul
{ ...getMenuProps() }
className={ classnames(
'woocommerce-experimental-select-control__menu',
{
'is-open': isOpen,
'has-results': Array.isArray( children )
? children.length
: Boolean( children ),
}
) }
>
{ isOpen &&
( ! Array.isArray( children ) || !! children.length ) && (
<ul className="woocommerce-experimental-select-control__menu-inner">
{ children }
</ul>
) }
</div>
{ isOpen && children }
</ul>
);
};

View File

@ -84,7 +84,14 @@ function SelectControl< ItemType = DefaultItemType >( {
}: SelectControlProps< ItemType > ) {
const [ isFocused, setIsFocused ] = useState( false );
const [ inputValue, setInputValue ] = useState( '' );
const { getSelectedItemProps, getDropdownProps } = useMultipleSelection();
const {
addSelectedItem,
getSelectedItemProps,
getDropdownProps,
removeSelectedItem,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
} = useMultipleSelection( { itemToString } );
let selectedItems = selected === null ? [] : selected;
selectedItems = Array.isArray( selectedItems )
? selectedItems
@ -104,11 +111,14 @@ function SelectControl< ItemType = DefaultItemType >( {
getComboboxProps,
highlightedIndex,
getItemProps,
} = useCombobox( {
selectItem,
selectedItem: singleSelectedItem,
} = useCombobox< ItemType | null >( {
inputValue,
items: filteredItems,
itemToString: getItemLabel,
selectedItem: null,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
onStateChange: ( { inputValue: value, type, selectedItem } ) => {
switch ( type ) {
case useCombobox.stateChangeTypes.InputChange:
@ -121,9 +131,18 @@ function SelectControl< ItemType = DefaultItemType >( {
case useCombobox.stateChangeTypes.InputBlur:
if ( selectedItem ) {
onSelect( selectedItem );
setInputValue(
multiple ? '' : getItemLabel( selectedItem )
);
if ( multiple ) {
addSelectedItem( selectedItem );
setInputValue( '' );
break;
}
selectItem( selectedItem );
setInputValue( getItemLabel( selectedItem ) );
}
if ( ! selectedItem && ! multiple ) {
setInputValue( getItemLabel( singleSelectedItem ) );
}
break;
@ -133,6 +152,12 @@ function SelectControl< ItemType = DefaultItemType >( {
},
} );
const onRemoveItem = ( item: ItemType ) => {
selectItem( null );
removeSelectedItem( item );
onRemove( item );
};
return (
<div
className={ classnames( 'woocommerce-experimental-select-control', {
@ -150,7 +175,7 @@ function SelectControl< ItemType = DefaultItemType >( {
getItemLabel={ getItemLabel }
getItemValue={ getItemValue }
getSelectedItemProps={ getSelectedItemProps }
onRemove={ onRemove }
onRemove={ onRemoveItem }
/>
) }
<ComboBox

View File

@ -106,6 +106,7 @@ export const Async: React.FC = () => {
const fetchItems = ( value: string | undefined ) => {
setIsFetching( true );
setFetchedItems( [] );
setTimeout( () => {
const results = sampleItems.sort( () => 0.5 - Math.random() );
setFetchedItems( results );
@ -117,6 +118,9 @@ export const Async: React.FC = () => {
<>
<SelectControl
label="Async"
getFilteredItems={ ( allItems ) => {
return allItems;
} }
items={ fetchedItems }
onInputChange={ fetchItems }
selected={ selectedItem }

View File

@ -10,6 +10,7 @@
"typeRoots": [
"./node_modules/@types"
],
"skipLibCheck": true
},
"include": [
"src/**/*"

View File

@ -10,6 +10,7 @@
"typeRoots": [
"./node_modules/@types"
],
"skipLibCheck": true
},
"include": [
"src/**/*"