Skip to content

DataForm: Stop card and details validation from hijacking focus - #80685

Merged
jorgefilipecosta merged 9 commits into
WordPress:trunkfrom
jorgefilipecosta:fix/dataform-card-validation-focus
Jul 28, 2026
Merged

DataForm: Stop card and details validation from hijacking focus#80685
jorgefilipecosta merged 9 commits into
WordPress:trunkfrom
jorgefilipecosta:fix/dataform-card-validation-focus

Conversation

@jorgefilipecosta

@jorgefilipecosta jorgefilipecosta commented Jul 24, 2026

Copy link
Copy Markdown
Member

Fixes #76832

On the card layout, validation runs on every blur inside the card, and reportValidity() moves focus to the first invalid field. So tabbing from one field to the next sends focus back to an unrelated field, breaking the natural tab sequence.

Following the discussion on the issue, this PR shows the errors of all the fields of a card when the card loses focus, instead of on each blur inside it. The errors are shown by dispatching a synthetic invalid event, so focus is never moved. Validated controls only replicate the native focus behavior for trusted events, so submitting a form still focuses the first error. The details layout gets the same treatment, and both announce how many fields need attention, given the errors now appear without moving focus.

The panel layout shares the same hook, so reopening a touched panel also shows its errors without moving focus.

Videos

Both videos run the same steps on the left and on the right. The title bar, the caption and the red ring around the focused field were added for the recording only.

DataForm Validation story, card layout — focus the Text field and press TAB without editing anything. Before, focus jumps to Password, the first field with errors. After, it goes to the Textarea, as expected.

DataForm Validation story, before and after

Download the MP4

Settings > Content Types > Add post type — click the Singular label and press TAB. Before, focus jumps back to Plural label and the whole card turns red. After, focus moves on to Post type key, and only the field that was left shows its error.

Content Types Add post type, before and after

Download the MP4

Testing Instructions

Go to http://localhost:50240/?path=/story/dataviews-dataform--validation and set the layout to card-collapsible.
Focus the Text field, press TAB, and verify focus moves to the Textarea instead of to the first field with errors.
Click outside the card and verify every invalid field shows its error and focus stays where you put it.
Collapse the card and verify the badge appears, expand it and verify the errors are still shown.

Then, with the Content Types experiment enabled, go to Settings > Content Types and click "Add post type".
Click the Singular label, press TAB, and verify focus moves to Post type key instead of back to Plural label.
Click outside the card and verify the fields you left show their errors without pulling focus back.

AI usage disclosure: fix and description drafted with AI assistance and reviewed by me.

@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

2 similar comments
@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: oandregal <oandregal@git.wordpress.org>
Co-authored-by: Shekhar0109 <shekh0109@git.wordpress.org>
Co-authored-by: NeosinneR <neosinner@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@jorgefilipecosta jorgefilipecosta added [Type] Bug An existing feature does not function as intended [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond labels Jul 24, 2026
@github-actions github-actions Bot added [Package] Components /packages/components [Package] DataViews /packages/dataviews labels Jul 24, 2026
@ciampo

ciampo commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

@mirka should be the best person here to give feedback (I'm currently unable to dedicate much time to Gutenberg work)

@jorgefilipecosta
jorgefilipecosta force-pushed the fix/dataform-card-validation-focus branch from 45c7c98 to 144b657 Compare July 27, 2026 17:53

@mirka mirka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I went ahead and added a story to document the pattern, if that's ok 🙏

* need to report on a recurring event such as losing focus. It returns
* how many inputs it revealed an error for.
*/
export default function useReportValidity(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe this should be renamed to something like useRevealValidity since it's no longer tied to reportValidity.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 to the rename.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The rename makes sense, the hook was renamed to useRevealValidity 👍

Comment thread packages/components/CHANGELOG.md Outdated

### Bug Fixes

- Validated form controls: Only move focus to the invalid control for trusted `invalid` events (form submission, `reportValidity()`). Consumers can now dispatch a synthetic `invalid` event to reveal a control's error message without disturbing the user's place in the form ([#80685](https://github.com/WordPress/gutenberg/pull/80685)).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel like this is an enhancement?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You are right, it was moved to the enhancements section 👍

// the badge, so it stays silent.
const reportedCount = reportValidity();
const message = getValidationMessage( validity );
if ( reportedCount > 0 && message ) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we gate the speak with isOpen?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, the gate was added 👍

jorgefilipecosta and others added 9 commits July 28, 2026 22:49
Validating on every blur inside a card marked the whole card touched and
called reportValidity(), which focuses the first invalid input. Tabbing
between two fields therefore jumped focus back to an unrelated field.

Errors for every field in a card are now revealed once focus leaves the
card, matching what validated controls do on their own first blur, and
they are revealed by dispatching a synthetic `invalid` event so no focus
move happens. ControlWithError only replicates the native focus behavior
for trusted events, so form submission still focuses the first error.

The details layout gets the same treatment, and both announce the number
of fields needing attention, since the errors now appear silently.
Tabbing away from a collapsed card that was edited earlier revealed
nothing, yet still announced the error count — which its header already
exposes as a description, so screen readers said it twice.
The details layout has no unit tests, so its half of the fix was
uncovered. jsdom doesn't reproduce the focus steal for `details` the way
it does for cards, so this asserts the reveal rather than claiming to
guard focus — the card tests cover the shared mechanism.
@jorgefilipecosta
jorgefilipecosta force-pushed the fix/dataform-card-validation-focus branch from 0aa5124 to 6f2876b Compare July 28, 2026 21:50
@jorgefilipecosta

Copy link
Copy Markdown
Member Author

I went ahead and added a story to document the pattern, if that's ok 🙏

That's a great enhancement, thank you!

@jorgefilipecosta

Copy link
Copy Markdown
Member Author

Thank you a lot @mirka, @ntsekouras for the reviews.

@jorgefilipecosta
jorgefilipecosta merged commit 2b91675 into WordPress:trunk Jul 28, 2026
62 of 67 checks passed
@jorgefilipecosta
jorgefilipecosta deleted the fix/dataform-card-validation-focus branch July 28, 2026 22:45
@github-actions github-actions Bot added this to the Gutenberg 23.7 milestone Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond [Package] Components /packages/components [Package] DataViews /packages/dataviews [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DataForm: Validation on blur hijacks focus from the natural tab sequence in card layout

4 participants