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 screen reader instructions for navigating child blocks on block selection #39558

Open
wants to merge 6 commits into
base: trunk
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
isPartOfSelection,
adjustScrolling,
enableAnimation,
blockListSettings,
hasChildBlocks,
} = useSelect(
( select ) => {
const {
Expand All @@ -84,6 +86,8 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
isBlockMultiSelected,
isAncestorMultiSelected,
isFirstMultiSelectedBlock,
getBlockListSettings,
getBlockOrder,
} = select( blockEditorStore );
const isSelected = isBlockSelected( clientId );
const isPartOfMultiSelection =
Expand All @@ -104,13 +108,30 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
enableAnimation:
! isTyping() &&
getGlobalBlockCount() <= BLOCK_ANIMATION_THRESHOLD,
blockListSettings: getBlockListSettings( clientId ),
hasChildBlocks: getBlockOrder( clientId ).length > 0,
};
},
[ clientId ]
);

// translators: %s: Type of block (i.e. Text, Image etc)
const blockLabel = sprintf( __( 'Block: %s' ), blockTitle );
const blockDescription = hasChildBlocks
? sprintf(
// translators: 1: Block title to lowercase for better sentence structure.
__(
'Press Escape followed by Left and Right Arrows to explore child blocks of the %s block.'
),
blockTitle.toLowerCase()
)
: sprintf(
// translators: 1: Block title to lowercase for better sentence structure.
__(
'Press Tab followed by Enter to add a child block of the %s block.'
),
blockTitle.toLowerCase()
);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's also worth checking if the block list is locked before adding this description, as that would make it impossible to add blocks.

I think the locked status is stored in the block list settings. There's a getTemplateLock selector which can return values like 'insert', 'all', or false. Generally a truthy value means insertion isn't possible.

Probably another description explaining the lock might be useful in this situation, as some users might be used to adding children to blocks like group and columns, and it'll be unexpected when they can't.

@Mamaduka is currently working on the locking functionality and might be interested in this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like this feature isn't fully implemented yet but I did add a check for it.

const htmlSuffix = mode === 'html' && ! __unstableIsHtml ? '-visual' : '';
const mergedRefs = useMergeRefs( [
props.ref,
Expand Down Expand Up @@ -148,6 +169,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
tabIndex: 0,
role: 'document',
'aria-label': blockLabel,
'aria-description': blockListSettings ? blockDescription : undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like blockListSettings is being used to determine whether the block supports child blocks here.

I wonder if it's worth adding a hasInnerBlockList selector function to the block editor store. It could be used here to make this code a bit more readable. It would also make future refactoring of code easier if the way existence of a block list is determined changes.

From memory, I think @youknowriad has also run into this before, and there might be some pitfalls I'm unaware of.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's a difference between: my block is a container block and my block has a non empty list of inner blocks. I guess we might need both. For the latter !! getBlock( clientId )?.innerBlocks?.length might be sufficient.

'data-block': clientId,
'data-type': name,
'data-title': blockTitle,
Expand Down