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

Add block navigator movers #18014

Merged
merged 1 commit into from
May 12, 2020
Merged

Add block navigator movers #18014

merged 1 commit into from
May 12, 2020

Conversation

talldan
Copy link
Contributor

@talldan talldan commented Oct 18, 2019

Description

Closes #11408

Adds block navigator movers to the navigation block.

This PR refactors the Block Navigator to use follow a TreeGrid as described in https://w3c.github.io/aria-practices/examples/treegrid/treegrid-1.html?cell=force, as suggested by feedback on this PR. The navigator can be navigated using arrow keys.

Some descriptions have been added to the buttons for selecting blocks and the appender for screenreader users using aria-describedby.

This is quite a large PR, so there are a couple of PRs extracted from this:

How has this been tested?

  1. Add a navigation menu block (ensure the feature is enabled as an experiment first)
  2. Add some menu items to the navigation menu
  3. Click the block navigator button on the toolbar
  4. Try reordering the items using the movers

Screenshots

navigator-movers

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.

@talldan talldan added [Type] Enhancement A suggestion for improvement. [Feature] List View Menu item in the top toolbar to select blocks from a list of links. [Block] Navigation Affects the Navigation Block labels Oct 18, 2019
@talldan talldan self-assigned this Oct 18, 2019
@talldan talldan requested review from mtias and karmatosed October 18, 2019 04:24
@draganescu
Copy link
Contributor

So far this works great and the code is perfect.

@talldan talldan force-pushed the add/block-nav-movers branch from f1d13f3 to d751f8a Compare October 25, 2019 09:26
@talldan talldan added the Needs Accessibility Feedback Need input from accessibility label Oct 25, 2019
@talldan talldan marked this pull request as ready for review October 25, 2019 09:28
@talldan talldan added the Needs Design Feedback Needs general design feedback. label Oct 25, 2019
@talldan
Copy link
Contributor Author

talldan commented Oct 25, 2019

I think this one is open for reviews now.

I think it needs some a11y feedback and design feedback.

There are some issues I've spotted that I'll continue to look into:

  • When clicking the up mover button, focus is retained, but clicking the down mover button causes a focus loss
  • When selected item is focused the background turns white
  • Select block button uses the new display name, but screenreader text for mover buttons still refer to item by its block type
  • I think it would be good to read what's read by a screenreader for the select button. e.g. the select button should probably read 'Select [Block Type]' instead of just the block type.

@talldan talldan requested a review from shaunandrews October 25, 2019 09:46
Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

Can we benefit from all these Block Navigation improvements in the global block navigation popover as well?

@mtias
Copy link
Member

mtias commented Oct 25, 2019

Can we benefit from all these Block Navigation improvements in the global block navigation popover as well?

The movers is the only one I'd be comfortable enabling in the top level one, but we need some improvements first — selection should be clearer, ideally also support the motion effect we have for moving blocks in the canvas.

@mtias
Copy link
Member

mtias commented Oct 25, 2019

Allow moving blocks in and out of nesting (follow-up PR?)
Drag and drop (follow-up PR?)
Animate moving of blocks (follow-up PR?)

Follow up PR seems fine. We can look at enabling the movers in the top-level navigator once these are worked out.

Copy link
Contributor

@tellthemachines tellthemachines left a comment

Choose a reason for hiding this comment

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

I did a bit of testing on NVDA/Firefox and VoiceOver/Safari. Agree that screen reader output for mover buttons is not very informative right now, would be better to read out something like "move Sample page menu item".

I'm afraid the issue with focus being lost when clicking the down mover is even worse using NVDA/Firefox as focus moves to the document body, even with the modal still open (yikes!). On Firefox with no screen reader, focus can also be moved out of the modal but not every time. Here's an example screenshot of Firefox on Mac with focus moved behind the modal and the menu item still visually selected:
Screen Shot 2019-10-28 at 2 14 21 pm

Another issue I'm noticing with the Navigator modal is that clicking on any arrow key closes it. This was already happening before this PR so it's not related to these changes but, because the navigator list now has a role of tree, VoiceOver is announcing it as a table, which is expected to be navigable with arrow keys. (Using the VO keys + arrow keys still works, but just using plain arrows should also work in a table scenario.) Still, it might be easier to handle this in a separate PR.

@talldan
Copy link
Contributor Author

talldan commented Oct 28, 2019

Thanks for testing and reviewing @tellthemachines. There's definitely a bit subtlety to getting these movers to work in the right way.

It's interesting in your screenshot that focus has moved back to the mover outside the popover. Coincidence? I'll do some more debugging/testing to establish.

@tellthemachines
Copy link
Contributor

It's interesting in your screenshot that focus has moved back to the mover outside the popover. Coincidence? I'll do some more debugging/testing to establish.

Initially it moves to the block inserter, then if you tab once it goes to the mover. I forgot to mention that bit, sorry.

@mtias
Copy link
Member

mtias commented May 7, 2020

Yes, let's test it for a release or two in the navigation block to squash all the bugs.

expect( renderer.toJSON() ).toMatchSnapshot();
} );

it( 'allows children to bue declared using a child render function as an alternative to `as`', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: "to be declared".

Copy link
Contributor

@tellthemachines tellthemachines left a comment

Choose a reason for hiding this comment

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

This is working much better on VoiceOver, and is working well on NVDA too, apart from one issue: when entering the treegrid, NVDA should go into focus mode automatically, but it's not happening. In browse mode, we are not able to use the arrow keys to navigate the treegrid, so users will have to manually switch to focus mode to be able to interact with it. This is a bit annoying because the wai-aria example correctly switches to focus mode, and the markup used seems to be identical in everything to this one 😞 . @diegohaz any ideas on this?

Approving, because we should get this in and iterate! It would be good to fix the above issue before we extend this functionality to the general block navigator though.

<TreeGrid>
<TreeGridRow level={ 1 } positionInSet={ 1 } setSize={ 2 }>
<TreeGridCell>
{ ( props ) => <Button onClick={ onSelect } { ...props }>Select</Button> }
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the element inside the cell have to be a button? I wouldn't expect that to be the typical case for this component. If we were to have just plain text, like in the wai-aria example, where would focus be transferred to? (This is something we can iterate on later though)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's a good point! I can think of a few ways to accomplish this, and it shouldn't be too difficult as TreeGridCell has all the information it needs.

<RovingTabIndexContainer>
{ /* Disable reason: A treegrid is implemented using a table element. */ }
{ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role */ }
<table { ...props } role="treegrid" onKeyDown={ onKeyDown }>
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be good to add in an aria-label here that can be passed a short description of what the treegrid is about.

) );

describe( 'TreeGridCell', () => {
it( 'requires TreeGrid to be declared as a parent component somewhere in the component heirarchy', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: "hierarchy".

@talldan talldan force-pushed the add/block-nav-movers branch from 93b7b9b to 606c0b7 Compare May 8, 2020 08:26
@diegohaz
Copy link
Member

diegohaz commented May 8, 2020

@tellthemachines

This is working much better on VoiceOver, and is working well on NVDA too, apart from one issue: when entering the treegrid, NVDA should go into focus mode automatically, but it's not happening. In browse mode, we are not able to use the arrow keys to navigate the treegrid, so users will have to manually switch to focus mode to be able to interact with it. This is a bit annoying because the wai-aria example correctly switches to focus mode, and the markup used seems to be identical in everything to this one 😞

It seems that it happens because the first active element when you tab into the treegrid is a button, not a role="gridcell" or role="row". I think this can be solved by always focusing the row when entering the treegrid, like in the WAI-ARIA example.

@diegohaz
Copy link
Member

diegohaz commented May 8, 2020

Hmm, after doing some more tests, it looks like NVDA messes up with focus/browse randomly when you focus on elements inside a tree grid that aren't rows or grid cells.

It happens even on the WAI-ARIA example. As soon as I focus the link, it switches to browse mode, and I'm no longer able to navigate through the tree grid using arrow keys.

The same happens on role="grid" elements. Seems like a bug on NVDA?

Read description above

@diegohaz
Copy link
Member

diegohaz commented May 8, 2020

Related issue on NVDA: nvaccess/nvda#8395

Looks like it’s expected behavior and NVDA users should use especial keys to navigate the grid, or enable focus mode manually.

@tellthemachines
Copy link
Contributor

Ooooh, great detective work @diegohaz ! I guess there's nothing else to do on our side then.

@talldan talldan force-pushed the add/block-nav-movers branch 2 times, most recently from 9e80c67 to ade2759 Compare May 11, 2020 09:05
</li>
);
}
export default function BlockNavigationBranch( props ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adamziel I ended up renaming BlockNavigationBranch to BlockNavigationLeaf and BlockNavigationList to BlockNavigationBranch, so this diff looks a bit confusing.

I think that's correct though, a branch should have multiple leaves, and the leaf should be the terminating points on a tree.

*
* @param {Object} props
*/
export default function BlockNavigationTree( {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adamziel I renamed BlockNavigationList to BlockNavigationTree to be consistent with the whole tree/branch/leaf thing.

*/
import { createContext, useContext } from '@wordpress/element';

export const BlockNavigationContext = createContext( {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adamziel I moved the context out into its own file and add a useBlockNavigationContext helper.

}

return (
<BlockNavigationBlockContentWrapper as="div">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adamziel This main file now contains a lot of the Wrapper and Slot/Fill logic. I ended up renaming a few things.

The main logic I changed is that the wrapper is now rendered around the slot, while in your PR the wrapper is rendered inside the fill:
https://github.com/WordPress/gutenberg/pull/22210/files#diff-2e071f8429cd2c500b830947ffde4239R226-R231

Pretty open to handling that differently, I think some aspects of this may need to be changed to handle adding the menu described in #22089.

Copy link
Contributor

@adamziel adamziel May 11, 2020

Choose a reason for hiding this comment

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

@talldan I went for the "wrapper inside of the fill" approach to make something like this possible:

<BlockNavigationBlockFill>
	<BlockNavigationBlockSelectButton
		ref={ ref }
		block={ block }
		onClick={ onClick }
		isSelected={ isSelected }
		position={ position }
		siblingCount={ siblingCount }
		level={ level }
		{ ...props }
	/>
	<EllipsisMenu {/* some props */} />
</BlockNavigationBlockFill>

With "wrapper outside of the fill" approach, these slots are only good for something like replacing the button entirely with RichText. You cannot the keep navigation item as a button and you cannot add any additional components.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, this is made difficult because this PR introduces the movers which are rendered after the fill, and then the designs in #22089 shown the dropdown menu after the movers.

I think most blocks will end up having the dropdown menu, so it probably makes sense to add that as an internal part of BlockNavigation, and then if we need to add custom items for particular blocks we can try a slot for the menu.

@talldan
Copy link
Contributor Author

talldan commented May 11, 2020

In case anyone is wondering, the above comments are in relation to resolving merge conflicts between this and the recently merged #21948

Fix doc examples

Make components experimental

Simplify creation of RovingTabIndex provider value

Add storybook snapshots

Add tests for RovingTabIndex, RovingTabIndexItem

Add tests for TreeGrid components

minor variable name change

Format JS

Import TreeGrid components from @wordpress/components

Update styling for block navigator

Try adding descender line styles

Add some further finesse to styling

Extract animated row to fix animation and use change detection that includes a full path so that all children animate

Patch up code after rebase

Use colSpan instead of colspan

Fix row animation when moving a row quickly multiple times

Remove descender lines from the accessibility tree

Use useCallback for callback

Use aria-hidden on purely presentational descender indicator in tree grid

Update example

Fix arrow key navigation when using Voiceover

Only handle arrow key navigation when no modifiers are pressed

Fix regressions in BlockMoverButton caused by rebase. Rename file to just button

Name buttons in a consistent way

Add screenreader description for focused block in navigator

Add aria-describedby for appender button

Fix selected block movers appearing with darker background

Remove writing flow hack

Fix typo

Allow aria-setsize and aria-posinset on role=row in axe e2e tests

Fix translator comment and use Add as the verb instead of Insert

Add aria-label for navigation structure tree grid

Fix typos

Try to fix tests

More typo fixes

Update snapshot to reflect renaming of test description

Update more e2e test classnames

Rename components to more closely reflect `master`
@talldan talldan force-pushed the add/block-nav-movers branch from ade2759 to 3de8bd1 Compare May 12, 2020 01:21
@talldan talldan merged commit cea2a4f into master May 12, 2020
@talldan talldan deleted the add/block-nav-movers branch May 12, 2020 02:05
@github-actions github-actions bot added this to the Gutenberg 8.2 milestone May 12, 2020
@gziolo gziolo added [Type] Feature New feature to highlight in changelogs. and removed [Type] Enhancement A suggestion for improvement. labels May 12, 2020
@paaljoachim
Copy link
Contributor

paaljoachim commented May 12, 2020

Awesome that movers are being added (have been added) to the block navigator!
Are there also plans for drag & drop? As it would be so nice to grab a hold of something and just drop it into the place where we need it.

@draganescu
Copy link
Contributor

There doesn't appear to be any issue for this specifically, @paaljoachim Maybe you can open one, specifically for the block navigator?

@paaljoachim
Copy link
Contributor

I went ahead and opened a new issue: #22297
(I added the Navigation and the Navigator, but can of course adjust to only focus on the Block Navigator.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block [Feature] List View Menu item in the top toolbar to select blocks from a list of links. [Type] Feature New feature to highlight in changelogs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reordering of blocks inside block navigation