-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Table block: Fix focus loss after Create Table button is selected #40399
Conversation
Size Change: +92 B (0%) Total Size: 1.23 MB
ℹ️ View Unchanged
|
…w contentEditable elements for focus first.
const { tagName } = element; | ||
const checkForInputTextarea = isInputOrTextArea( element ); | ||
let checkContentEditable = false; |
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.
I added this because some blocks such as the table block have contentEditable instead of a real form element.
@@ -269,7 +269,6 @@ describe( 'Table', () => { | |||
// Create the table. | |||
await clickButton( createButtonLabel ); | |||
|
|||
await page.keyboard.press( 'Tab' ); |
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.
This issue is fixed. 👍
@@ -280,4 +279,18 @@ describe( 'Table', () => { | |||
|
|||
expect( await getEditedPostContent() ).toMatchSnapshot(); | |||
} ); | |||
|
|||
it( 'should not have focus loss after creation', async () => { |
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.
Added this test to ensure it doesn't break in the future.
@@ -678,27 +678,11 @@ describe( 'Writing Flow', () => { | |||
await page.keyboard.press( 'Tab' ); | |||
// Create the table. | |||
await page.keyboard.press( 'Space' ); | |||
// Return focus after focus loss. This should be fixed. |
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.
This was fixed.
// Navigate to the second cell. | ||
await page.keyboard.press( 'ArrowRight' ); | ||
await page.keyboard.type( '2' ); | ||
// Confirm correct setup. | ||
expect( await getEditedPostContent() ).toMatchSnapshot(); | ||
// The content should only have one tab stop. |
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.
This is not the case. Each Tab key press will land in a cell so removed this. Let me know if I should do anything differently.
@@ -105,6 +105,9 @@ function TableEdit( { | |||
const colorProps = useColorProps( attributes ); | |||
const borderProps = useBorderProps( attributes ); | |||
|
|||
const tableRef = useRef(); | |||
const [ hasTableCreated, setHasTableCreated ] = useState( false ); |
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.
I am using the state to detect when table creation happens and then it fires the effect later. From my understanding, effects cannot listen for function execution but they can listen for states. If the state is set to true on creation, the effect will execute which will place focus in the table cell. After, it will set the state to false so it won't fire anymore. I set the ref as a property on the block so I had good targeting on my querySelector since that should be avoided.
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.
This looks good, another good problem to solve.
I had a question about the code I'm unfamiliar with and also a code quality suggestion.
export default function isFormElement( element ) { | ||
export default function isFormElement( | ||
element, | ||
includeContentEditable = false |
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.
I wonder if instead of adding an extra parameter, another option would be adding an isContentEditable
function to the dom package and using that instead.
I'm never a huge fan of boolean parameters, as the calling code is very unclear. For example isFormElement( element, true )
, I have to look up what the true
means.
An alternative is to add an options object, so it becomes isFormElement( element, { includeContentEditable: true } );
, which is more verbose, but means readers don't have to look up documentation.
But I also think isFormElement( element ) || isContentEditable( element )
is very readable and the separate function might be more useful in a wider range of situations.
PS: I think this function is unusual anyway. It doesn't return true
for a <form>
element, which contradicts the name 😆
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.
Removed this for now.
@@ -115,7 +115,7 @@ export default function useTabNav() { | |||
// these are not rendered in the content and perhaps in the | |||
// future they can be rendered in an iframe or shadow DOM. | |||
if ( | |||
( isFormElement( event.target ) || | |||
( isFormElement( event.target, true ) || | |||
event.target.getAttribute( 'data-block' ) === | |||
getSelectedBlockClientId() ) && | |||
isFormElement( focus.tabbable[ direction ]( event.target ) ) |
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.
Should this call to isFormElement
also check for contenteditables?
It looks like it says 'if the current element is a form element, content editable or a block boundary, and the next element is a form element, don't do anything'. But I'm not sure what doing nothing achieves.
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.
No, it should not. Adding true here will find another block on next Tab key press vs. jumping to the sidebar.
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.
@talldan I could not make this work again when I restarted my dev environment so I removed the changes. I'll try again in another PR. This whole writing flow feature still needs some work for screen reader users.
…able-block-accessibility
… in to another PR.
Updated the PR description to reflect latest changes. |
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.
This solves the problem for me, and the code is easily understandable. Nice work!
What?
The PR fixes focus on table creation.
Why?
When focus loss occurs after table creation, users may be confused.
How?
After the table creation function executes, focus is placed in the table.
Testing Instructions
Screenshots or screencast