-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Try better block labels #18132
Try better block labels #18132
Changes from all commits
14ca32d
58f90d0
97b2c8f
40ae5cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,9 +21,9 @@ import { | |
isReusableBlock, | ||
isUnmodifiedDefaultBlock, | ||
getUnregisteredTypeHandlerName, | ||
__experimentalGetAccessibleBlockLabel as getAccessibleBlockLabel, | ||
} from '@wordpress/blocks'; | ||
import { withFilters, Popover } from '@wordpress/components'; | ||
import { __, sprintf } from '@wordpress/i18n'; | ||
import { | ||
withDispatch, | ||
withSelect, | ||
|
@@ -50,6 +50,32 @@ import useMovingAnimation from './moving-animation'; | |
import { ChildToolbar, ChildToolbarSlot } from './block-child-toolbar'; | ||
import { Context } from './root-container'; | ||
|
||
/** | ||
* A debounced version of getAccessibleBlockLabel, avoids unnecessary updates to the aria-label attribute | ||
* when typing in some blocks, like the paragraph. | ||
* | ||
* @param {Object} blockType The block type object representing the block's definition. | ||
* @param {Object} attributes The block's attribute values. | ||
* @param {number} index The index of the block in the block list. | ||
* @param {string} moverDirection A string representing whether the movers are displayed vertically or horizontally. | ||
* @param {number} delay The debounce delay. | ||
*/ | ||
const useDebouncedAccessibleBlockLabel = ( blockType, attributes, index, moverDirection, delay ) => { | ||
const [ blockLabel, setBlockLabel ] = useState( '' ); | ||
|
||
useEffect( () => { | ||
const timeoutId = setTimeout( () => { | ||
setBlockLabel( getAccessibleBlockLabel( blockType, attributes, index + 1, moverDirection ) ); | ||
}, delay ); | ||
|
||
return () => { | ||
clearTimeout( timeoutId ); | ||
}; | ||
}, [ blockType, attributes, index, moverDirection, delay ] ); | ||
|
||
return blockLabel; | ||
}; | ||
|
||
function BlockListBlock( { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is one of the most central components of our codebase and changes here can have big performance impacts, so, a sanity check (running performance tests) would be good (with and without the PR. |
||
mode, | ||
isFocusMode, | ||
|
@@ -71,6 +97,7 @@ function BlockListBlock( { | |
isSelectionEnabled, | ||
className, | ||
name, | ||
index, | ||
isValid, | ||
isLast, | ||
attributes, | ||
|
@@ -115,6 +142,9 @@ function BlockListBlock( { | |
|
||
const [ isToolbarForced, setIsToolbarForced ] = useState( false ); | ||
|
||
const blockType = getBlockType( name ); | ||
const blockAriaLabel = useDebouncedAccessibleBlockLabel( blockType, attributes, index, moverDirection, 400 ); | ||
|
||
// Handing the focus of the block on creation and update | ||
|
||
/** | ||
|
@@ -255,13 +285,6 @@ function BlockListBlock( { | |
{ bindGlobal: true, eventName: 'keydown', isDisabled: ! canFocusHiddenToolbar } | ||
); | ||
|
||
// Rendering the output | ||
const blockType = getBlockType( name ); | ||
// translators: %s: Type of block (i.e. Text, Image etc) | ||
const blockLabel = sprintf( __( 'Block: %s' ), blockType.title ); | ||
// The block as rendered in the editor is composed of general block UI | ||
// (mover, toolbar, wrapper) and the display of the block content. | ||
|
||
const isUnregisteredBlock = name === getUnregisteredTypeHandlerName(); | ||
|
||
// If the block is selected and we're typing the block should not appear. | ||
|
@@ -382,7 +405,7 @@ function BlockListBlock( { | |
// Only allow shortcuts when a blocks is selected and not locked. | ||
onKeyDown={ isSelected && ! isLocked ? onKeyDown : undefined } | ||
tabIndex="0" | ||
aria-label={ blockLabel } | ||
aria-label={ blockAriaLabel } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might represent a bit of a performance issue for something like the paragraph block where the aria-label contains all the paragraph text. Typing in the block also updates the aria-label! An option might be to debounce the function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How do the mobile friends do it? An option might be to update the paragraph text, for example, once editing mode is exited. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a feeling it's not as much of an issue on the mobile side as there's no document object model. I've updated the code now so that the function is debounced, hopefully that's an ok solution. |
||
role="group" | ||
{ ...wrapperProps } | ||
style={ | ||
|
@@ -560,6 +583,7 @@ const applyWithSelect = withSelect( | |
hasFixedToolbar: hasFixedToolbar && isLargeViewport, | ||
isLast: index === blockOrder.length - 1, | ||
isNavigationMode: isNavigationMode(), | ||
index, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We removed this explicitely some time ago for performance reasons. Adding this prop rerenders the block everytime a precedent block is removed in the list, this can be harmful for long posts. Also, We should favor the inner useSelect instead of adding new props to this component. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this is being removed in #19597 |
||
isRTL, | ||
|
||
// Users of the editor.BlockListBlock filter used to be able to access the block prop | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,113 +8,113 @@ describe( 'block mover', () => { | |
positiveDirection = 1; | ||
|
||
describe( 'getBlockMoverDescription', () => { | ||
const type = 'TestType'; | ||
const label = 'Header: Some Header Text'; | ||
|
||
it( 'generates a title for the first item moving up', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
0, | ||
true, | ||
false, | ||
negativeDirection | ||
) ).toBe( | ||
`Block ${ type } is at the beginning of the content and can’t be moved up` | ||
`Block ${ label } is at the beginning of the content and can’t be moved up` | ||
); | ||
} ); | ||
|
||
it( 'generates a title for the last item moving down', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
3, | ||
false, | ||
true, | ||
positiveDirection | ||
) ).toBe( `Block ${ type } is at the end of the content and can’t be moved down` ); | ||
positiveDirection, | ||
) ).toBe( `Block ${ label } is at the end of the content and can’t be moved down` ); | ||
} ); | ||
|
||
it( 'generates a title for the second item moving up', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
1, | ||
false, | ||
false, | ||
negativeDirection | ||
) ).toBe( `Move ${ type } block from position 2 up to position 1` ); | ||
negativeDirection, | ||
) ).toBe( `Move ${ label } block from position 2 up to position 1` ); | ||
} ); | ||
|
||
it( 'generates a title for the second item moving down', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
1, | ||
false, | ||
false, | ||
positiveDirection | ||
) ).toBe( `Move ${ type } block from position 2 down to position 3` ); | ||
positiveDirection, | ||
) ).toBe( `Move ${ label } block from position 2 down to position 3` ); | ||
} ); | ||
|
||
it( 'generates a title for the only item in the list', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
0, | ||
true, | ||
true, | ||
positiveDirection | ||
) ).toBe( `Block ${ type } is the only block, and cannot be moved` ); | ||
positiveDirection, | ||
) ).toBe( `Block ${ label } is the only block, and cannot be moved` ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am wondering if it makes sense to also add tests for horizontal movers so they are properly labeled for columns moving left and right. Also, in light of the other discussion, it would make sense to update the movers text to speak of rows in these situations I think. But that should be dealt with in a follow-up after this lands. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} ); | ||
|
||
it( 'indicates that the block can be moved left when the orientation is horizontal and the direction is negative', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
1, | ||
false, | ||
false, | ||
negativeDirection, | ||
'horizontal' | ||
) ).toBe( `Move ${ type } block from position 2 left to position 1` ); | ||
) ).toBe( `Move ${ label } block from position 2 left to position 1` ); | ||
} ); | ||
|
||
it( 'indicates that the block can be moved right when the orientation is horizontal and the direction is positive', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
1, | ||
false, | ||
false, | ||
positiveDirection, | ||
'horizontal' | ||
) ).toBe( `Move ${ type } block from position 2 right to position 3` ); | ||
) ).toBe( `Move ${ label } block from position 2 right to position 3` ); | ||
} ); | ||
|
||
it( 'indicates that the block cannot be moved left when the orientation is horizontal and the block is the first block', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
0, | ||
true, | ||
false, | ||
negativeDirection, | ||
'horizontal' | ||
) ).toBe( | ||
`Block ${ type } is at the beginning of the content and can’t be moved left` | ||
`Block ${ label } is at the beginning of the content and can’t be moved left` | ||
); | ||
} ); | ||
|
||
it( 'indicates that the block cannot be moved right when the orientation is horizontal and the block is the last block', () => { | ||
expect( getBlockMoverDescription( | ||
1, | ||
type, | ||
label, | ||
3, | ||
false, | ||
true, | ||
positiveDirection, | ||
'horizontal' | ||
) ).toBe( `Block ${ type } is at the end of the content and can’t be moved right` ); | ||
) ).toBe( `Block ${ label } is at the end of the content and can’t be moved right` ); | ||
} ); | ||
} ); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a timeout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably because of https://github.com/WordPress/gutenberg/pull/18132/files#r359241034
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is being removed in #19597