Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve block inserter keyboard navigation #26938

Merged
merged 21 commits into from
Mar 12, 2021
Merged
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0df4171
Try new block inserter keyboard navigation
diegohaz Nov 12, 2020
4f906dd
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Nov 12, 2020
13d209d
Refactor code
diegohaz Nov 19, 2020
5c71072
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Nov 19, 2020
543ef7c
Pass aria-orientation to listbox
diegohaz Nov 19, 2020
ce34a54
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Dec 3, 2020
eca11f9
Update package.json
diegohaz Dec 3, 2020
fcd6573
Address review comments
diegohaz Dec 4, 2020
bcc8d85
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Dec 10, 2020
3155cee
Add announcement
diegohaz Jan 7, 2021
dc52e50
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Jan 7, 2021
eddebc4
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Jan 9, 2021
8518ec3
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Jan 16, 2021
40a0043
Import composite from @wordpress/components
diegohaz Jan 16, 2021
2f7889a
Fix import names
diegohaz Jan 16, 2021
1b1d02f
Merge branch 'master' into try/block-inserter-keyboard-navigation
diegohaz Jan 21, 2021
cb7b4d7
Fix keyboard navigation on search results
diegohaz Jan 21, 2021
454a69f
Fix e2e test
diegohaz Jan 21, 2021
c0d52d1
Announce instructions after block and group name
diegohaz Jan 21, 2021
5f3bc81
Merge branch 'trunk' into try/block-inserter-keyboard-navigation
diegohaz Mar 11, 2021
cfbf51b
Merge branch 'trunk' into try/block-inserter-keyboard-navigation
diegohaz Mar 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/block-editor/package.json
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@
"memize": "^1.1.0",
"react-autosize-textarea": "^7.1.0",
"react-spring": "^8.0.19",
"reakit": "1.1.0",
"reakit": "1.3.0",
"redux-multi": "^0.1.12",
"refx": "^3.0.0",
"rememo": "^3.0.0",
79 changes: 35 additions & 44 deletions packages/block-editor/src/components/block-types-list/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
/**
* External dependencies
*/
import { Composite, useCompositeState } from 'reakit';

/**
* WordPress dependencies
*/
import { getBlockMenuDefaultClassName } from '@wordpress/blocks';
import { useEffect } from '@wordpress/element';

/**
* Internal dependencies
*/
import InserterListItem from '../inserter-list-item';
import { InserterListboxGroup, InserterListboxRow } from '../inserter-listbox';

function chunk( array, size ) {
const chunks = [];
for ( let i = 0, j = array.length; i < j; i += size ) {
chunks.push( array.slice( i, i + size ) );
}
return chunks;
}

function BlockTypesList( {
items = [],
@@ -21,49 +24,37 @@ function BlockTypesList( {
children,
label,
} ) {
const composite = useCompositeState();
const orderId = items.reduce( ( acc, item ) => acc + '--' + item.id, '' );

// This ensures the composite state refreshes when the list order changes.
useEffect( () => {
composite.unstable_sort();
}, [ composite.unstable_sort, orderId ] );

return (
/*
* Disable reason: The `list` ARIA role is redundant but
* Safari+VoiceOver won't announce the list otherwise.
*/
/* eslint-disable jsx-a11y/no-redundant-roles */
<Composite
{ ...composite }
role="listbox"
<InserterListboxGroup
className="block-editor-block-types-list"
aria-label={ label }
>
{ items.map( ( item ) => {
return (
<InserterListItem
key={ item.id }
className={ getBlockMenuDefaultClassName( item.id ) }
icon={ item.icon }
onClick={ () => {
onSelect( item );
onHover( null );
} }
onFocus={ () => onHover( item ) }
onMouseEnter={ () => onHover( item ) }
onMouseLeave={ () => onHover( null ) }
onBlur={ () => onHover( null ) }
isDisabled={ item.isDisabled }
title={ item.title }
composite={ composite }
/>
);
} ) }
{ chunk( items, 3 ).map( ( row, i ) => (
<InserterListboxRow key={ i } role="presentation">
{ row.map( ( item, j ) => (
<InserterListItem
key={ item.id }
className={ getBlockMenuDefaultClassName(
item.id
) }
icon={ item.icon }
onClick={ () => {
onSelect( item );
onHover( null );
} }
onFocus={ () => onHover( item ) }
onMouseEnter={ () => onHover( item ) }
onMouseLeave={ () => onHover( null ) }
onBlur={ () => onHover( null ) }
isDisabled={ item.isDisabled }
title={ item.title }
isFirst={ i + j === 0 }
/>
) ) }
</InserterListboxRow>
) ) }
{ children }
</Composite>
/* eslint-enable jsx-a11y/no-redundant-roles */
</InserterListboxGroup>
);
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.block-editor-block-types-list {
list-style: none;
.block-editor-block-types-list > * {
padding: 4px;
margin-left: -4px;
margin-right: -4px;
Original file line number Diff line number Diff line change
@@ -2,25 +2,20 @@
* External dependencies
*/
import classnames from 'classnames';
import { CompositeItem } from 'reakit';

/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';

/**
* Internal dependencies
*/
import BlockIcon from '../block-icon';
import { InserterListboxItem } from '../inserter-listbox';

function InserterListItem( {
icon,
onClick,
isDisabled,
title,
className,
composite,
isFirst,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InserterListItem isn't exposed as part of the public API so it's fine to change 👍🏻

...props
} ) {
const itemIconStyle = icon
@@ -31,11 +26,11 @@ function InserterListItem( {
: {};

return (
<div className="block-editor-block-types-list__list-item">
<CompositeItem
role="option"
as={ Button }
{ ...composite }
<div
className="block-editor-block-types-list__list-item"
role="presentation"
>
<InserterListboxItem
className={ classnames(
'block-editor-block-types-list__item',
className
@@ -45,6 +40,7 @@ function InserterListItem( {
onClick();
} }
disabled={ isDisabled }
isFirst={ isFirst }
{ ...props }
>
<span
@@ -56,7 +52,7 @@ function InserterListItem( {
<span className="block-editor-block-types-list__item-title">
{ title }
</span>
</CompositeItem>
</InserterListboxItem>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* WordPress dependencies
*/
import { createContext } from '@wordpress/element';

const InserterListboxContext = createContext();

export default InserterListboxContext;
17 changes: 17 additions & 0 deletions packages/block-editor/src/components/inserter-listbox/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

function InserterListboxGroup( props, ref ) {
return (
<div
role="listbox"
aria-orientation="horizontal"
{ ...props }
ref={ ref }
/>
);
}

export default forwardRef( InserterListboxGroup );
32 changes: 32 additions & 0 deletions packages/block-editor/src/components/inserter-listbox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* External dependencies
*/
import { useCompositeState } from 'reakit/Composite';

/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import InserterListboxContext from './context';

export { default as InserterListboxGroup } from './group';
export { default as InserterListboxRow } from './row';
export { default as InserterListboxItem } from './item';

function InserterListbox( props, ref ) {
const compositeState = useCompositeState( {
shift: true,
wrap: 'horizontal',
} );
return (
<InserterListboxContext.Provider value={ compositeState }>
<div { ...props } ref={ ref } />
</InserterListboxContext.Provider>
);
}

export default forwardRef( InserterListbox );
45 changes: 45 additions & 0 deletions packages/block-editor/src/components/inserter-listbox/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* External dependencies
*/
import { CompositeItem } from 'reakit/Composite';

/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import { forwardRef, useContext } from '@wordpress/element';

/**
* Internal dependencies
*/
import InserterListboxContext from './context';

function InserterListboxItem(
{ isFirst, as: Component, children, ...props },
ref
) {
const state = useContext( InserterListboxContext );
return (
<CompositeItem state={ state } role="option" ref={ ref } { ...props }>
{ ( htmlProps ) => {
const propsWithTabIndex = {
...htmlProps,
tabIndex: isFirst ? 0 : htmlProps.tabIndex,
};
if ( Component ) {
return (
<Component { ...propsWithTabIndex }>
{ children }
</Component>
);
}
if ( typeof children === 'function' ) {
return children( propsWithTabIndex );
}
return <Button { ...propsWithTabIndex }>{ children }</Button>;
} }
</CompositeItem>
);
}

export default forwardRef( InserterListboxItem );
27 changes: 27 additions & 0 deletions packages/block-editor/src/components/inserter-listbox/row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* WordPress dependencies
*/
import { forwardRef, useContext } from '@wordpress/element';
/**
* External dependencies
*/
import { CompositeGroup } from 'reakit/Composite';

/**
* Internal dependencies
*/
import InserterListboxContext from './context';

function InserterListboxRow( props, ref ) {
const state = useContext( InserterListboxContext );
return (
<CompositeGroup
state={ state }
role="presentation"
ref={ ref }
{ ...props }
/>
);
}

export default forwardRef( InserterListboxRow );
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ import BlockTypesList from '../block-types-list';
import ChildBlocks from './child-blocks';
import InserterPanel from './panel';
import useBlockTypesState from './hooks/use-block-types-state';
import InserterListbox from '../inserter-listbox';

const getBlockNamespace = ( item ) => item.name.split( '/' )[ 0 ];

@@ -93,7 +94,7 @@ export function BlockTypesTab( {
useEffect( () => () => onHover( null ), [] );

return (
<div>
<InserterListbox>
{ hasChildItems && (
<ChildBlocks rootClientId={ rootClientId }>
<BlockTypesList
@@ -179,7 +180,7 @@ export function BlockTypesTab( {
</InserterPanel>
);
} ) }
</div>
</InserterListbox>
);
}

2 changes: 1 addition & 1 deletion packages/block-library/package.json
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@
"memize": "^1.1.0",
"moment": "^2.22.1",
"react-easy-crop": "^3.0.0",
"reakit": "1.1.0",
"reakit": "1.3.0",
"tinycolor2": "^1.4.1"
},
"publishConfig": {
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
"react-resize-aware": "^3.0.1",
"react-spring": "^8.0.20",
"react-use-gesture": "^7.0.15",
"reakit": "^1.1.0",
"reakit": "^1.3.0",
"rememo": "^3.0.0",
"tinycolor2": "^1.4.1",
"uuid": "^8.3.0"
2 changes: 1 addition & 1 deletion packages/edit-widgets/package.json
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@
"@wordpress/url": "file:../url",
"classnames": "^2.2.5",
"lodash": "^4.17.19",
"reakit": "^1.1.0",
"reakit": "^1.3.0",
"rememo": "^3.0.0",
"uuid": "^8.3.0"
},