Skip to content

DataForm: mark fields as required or optional automatically#74430

Merged
oandregal merged 16 commits intoWordPress:trunkfrom
czarflix:add/74417-optional-field-label
Feb 4, 2026
Merged

DataForm: mark fields as required or optional automatically#74430
oandregal merged 16 commits intoWordPress:trunkfrom
czarflix:add/74417-optional-field-label

Conversation

@czarflix
Copy link
Contributor

@czarflix czarflix commented Jan 8, 2026

What?

Closes #74417

Adds the markWhenOptional prop to the DataViews Field API, allowing fields to display "(Optional)" instead of "(Required)" labels.

Why?

When most fields in a form are required, it's more intuitive to highlight the optional fields rather than marking every required one. The underlying @wordpress/components validated controls already support markWhenOptional, but it wasn't exposed through the DataViews Field API.

How?

  • Added markWhenOptional?: boolean to DataFormControlProps in field-api.ts
  • Added markWhenOptional?: boolean to FieldLayoutProps in dataform.ts
  • Updated all control components to destructure and pass the prop to their underlying validated controls
  • Updated all layout components to forward the prop to child components
  • Follows the existing pattern used by hideLabelFromVision

Files modified: 25 files across types, controls, and layouts

Testing Instructions

  1. Create a DataForm with multiple fields
  2. Set isValid: { required: true } on most fields
  3. Add markWhenOptional: true to an optional field (one without required)
  4. Verify the optional field's label shows "(Optional)" suffix
  5. Verify required fields show no indicator (instead of "(Required)")

Testing Instructions for Keyboard

No keyboard-specific testing needed - this change passes an existing prop through the component hierarchy without modifying any interactive behavior.

Screenshots or screencast

N/A - No visual changes to document. The feature enables an existing capability in the underlying components.

@github-actions github-actions bot added the [Package] DataViews /packages/dataviews label Jan 8, 2026
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @czarflix! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@github-actions github-actions bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Jan 8, 2026
@czarflix czarflix marked this pull request as ready for review January 8, 2026 05:37
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

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: First-time Contributor, [Package] DataViews.

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

github-actions bot commented Jan 8, 2026

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: czarflix <czarflix@git.wordpress.org>
Co-authored-by: oandregal <oandregal@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: mcsf <mcsf@git.wordpress.org>
Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org>

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

@oandregal
Copy link
Member

@czarflix thanks for your contribution! A couple of notes:

If you join Make WordPress as a contributor, and then link your account to your GitHub account, you'll be marked as a contributor in the WordPress 7.0 release. You also get a profile like this https://profiles.wordpress.org/oandregal/

This is a step in the good direction, we need to do an extra step: the downstream consumers need a way to pass this setting to the Edit control. This is a form-level configuration (either fields are highlighted as required or optional, it doesn't make sense mixing both). So this is what I'm thinking:

  • Add a form.labelMode that can take showRequired, showOptional, or auto (the default when no value is passed). When auto, we calculate the number of required fields: if more fields are required, the label mode is showRequired, otherwise we use showOptional – this logic can live in DataForm.
  • Update the validation story (storybook, code) by adding a "labelMode" control to highlight this behavior.
@czarflix
Copy link
Contributor Author

czarflix commented Jan 8, 2026

@oandregal Thanks for the feedback and the contributor tip — I’ll get that set up.

Your form-level approach makes more sense. Here’s how I’m planning to implement it:

form.labelMode

  • 'showRequired' — marks required fields (current default behavior)
  • 'showOptional' — marks optional fields
  • 'auto' — determines labeling based on field counts

Default behavior

One tweak on the default: I’m thinking of defaulting to 'showRequired' rather than 'auto' to preserve backward compatibility. Existing forms would retain their current appearance, and users who want the smart behavior can explicitly opt into 'auto'.

Does that seem reasonable, or would you prefer 'auto' as the default?

Implementation approach

  • Calculate the effective label mode in DataForm (so nested form config doesn’t need to care about it)
  • Use the per-field markWhenOptional plumbing from this PR as the internal mechanism
  • Add a labelMode control to the Validation story

I’ll push the updated code shortly.

@czarflix
Copy link
Contributor Author

czarflix commented Jan 9, 2026

I've updated the PR with the form-level approach.

Changes

  • Added form.labelMode with the following options:

    • 'showRequired'
    • 'showOptional'
    • 'auto'
  • Behavior for 'auto':

    • If requiredCount >= optionalCount'showOptional'
    • Else → 'showRequired'
  • Default value is 'showRequired' for backward compatibility.

  • Added labelMode control to the Validation story.

  • The per-field markWhenOptional plumbing from the initial PR is now reused as the internal mechanism.

@oandregal oandregal added [Type] Enhancement A suggestion for improvement. [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond labels Jan 9, 2026
@czarflix czarflix force-pushed the add/74417-optional-field-label branch from c353d5b to 1a7fdee Compare January 9, 2026 22:25
@czarflix
Copy link
Contributor Author

czarflix commented Jan 9, 2026

CI Lint Failures - Pre-existing Issues

The CI lint failures are not caused by this PR:

  1. File Location: All lint errors are in test/e2e/, test/native/, test/performance/. This PR only modifies packages/dataviews/.

  2. Verified in Trunk: These exact issues exist in trunk at the same line numbers:

    • undo.spec.js lines 27, 354 (waitForTimeout)
    • blocks-raw-handling.native.js lines 267-576 (.skip())
  3. No ESLint Changes: This PR does not modify .eslintrc.js.

Could a maintainer confirm if these pre-existing lint issues should block this PR, or be addressed separately?

@czarflix
Copy link
Contributor Author

czarflix commented Jan 15, 2026

@oandregal @gigitux @ntsekouras
All CI checks are now passing

Fixed the lint issues from the previous run. Ready for review when you have time!

() => ( {
layout: DEFAULT_LAYOUT,
fields: !! field.children ? field.children : [],
labelMode: 'showRequired',
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit confused why in all cases here we pass showRequired mode, whereas below we pass markWhenOptional which was computed based on the label mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a bug. All 6 nested layout files were hardcoding labelMode: 'showRequired', which broke the parent's computed value.

Fixed by:

  1. Removed labelMode from all nested form objects
  2. Added markWhenOptional to DataFormContext
  3. All layouts now read from context, ensuring proper inheritance

The context approach means nested forms at any depth correctly inherit the auto-computed value.

@ntsekouras
Copy link
Contributor

ntsekouras commented Jan 22, 2026

Thanks for the PR!

I might be missing context, but here are my thoughts after checking the changes and reading the comments above.

I'm not sure we should have any configurable prop for this and I believe we should be opinionated with the one referred to as auto (determines labeling based on field counts).

This way we don't have to add any new API since the showRequired/markAsOptional can be derived directly from DataFormLayout that has access to the fields through context.

UX wise I believe it's better to have this auto behavior as it will reduce visual noise and cognitive load. Said that, I think we should have the auto but if a form ends up with markAsOptional (fewer optional fields), we should probably add a small note above or below the form, with a message like All fields are required unless marked optional. What do you think? --cc @jasmussen @jameskoster @gigitux @oandregal

@jameskoster
Copy link
Contributor

jameskoster commented Jan 26, 2026

I can't comment on the code but I can confirm that the pattern we'd like to enable is one where the minimal number of fields are marked. IE if 2 of 10 fields are required only the required ones should be marked, and vice versa. When all the fields in the form are required or optional that should be stated in the DataForm description.

I'm planning a PR to document this.

- Remove configurable form.labelMode prop
- Add markWhenOptional to DataFormContext (auto-computed)
- Fix nested forms to inherit labeling via Context
- Mark minority of fields (required OR optional) to reduce noise

Addresses feedback from @ntsekouras and @jameskoster:
- Auto-only behavior, no configurable prop
- Nested forms now correctly inherit labeling
@czarflix
Copy link
Contributor Author


Thanks @jameskoster and @ntsekouras for the feedback!

I've refactored to the auto-only approach as suggested:

Changes in this update

Removed configurable form.labelMode prop

  • No more 'showRequired' / 'showOptional' / 'auto' options
  • Behavior is now always automatic

Auto-compute logic

Forms now automatically mark the minority of fields:

  • If more required → mark optional fields
  • If more optional → mark required fields
  • Equal split → mark optional (tie-breaker)

Fixed the nested forms bug @ntsekouras spotted

The hardcoded labelMode: 'showRequired' in nested layouts was causing the issue you identified.

Solution: Moved markWhenOptional to React Context, so all nested layouts inherit from the parent DataForm. No more hardcoding!

Files changed

  • 15 files, +30 -73 lines

Architecture

DataForm (auto-computes markWhenOptional)
    ↓ via Context
DataFormLayout → Regular/Card/Panel/Details/Row
    ↓ inherited
FieldLayout → Controls

All tests passing (212/212), lint clean. Ready for re-review!


@mcsf
Copy link
Contributor

mcsf commented Jan 28, 2026

@czarflix, you have so far taken time and attention from at least 3 lead contributors, while communicating exclusively via LLM-generated responses. If you cannot defend the work nor explain it as a person when asked, and are unable to follow up, then let's stop wasting more time and close this pull request.

I've labeled this PR accordingly and we'll allow a grace period while we wait for your feedback.

@czarflix
Copy link
Contributor Author

@czarflix, you have so far taken time and attention from at least 3 lead contributors, while communicating exclusively via LLM-generated responses. If you cannot defend the work nor explain it as a person when asked, and are unable to follow up, then let's stop wasting more time and close this pull request.

I've labeled this PR accordingly and we'll allow a grace period while we wait for your feedback.

Hey @mcsf, sorry for the confusion! English isn't my first language so I've been using AI rewriters to help clean up my grammar and formatting before posting , didn't mean to come across as impersonal.

I also have a full-time job and things got hectic this past week, which is why I've been slow to respond.

I'll go through all the feedback today and respond properly. Thanks for your patience

@czarflix
Copy link
Contributor Author

@czarflix I am not sure if I understand that proposal, can you rephrase it? The current controls to switch on/off required validation should remain because that allows us to test the different validation scenarios (in isolation, together with others, etc.).

I apologize for the delay, it was unavoidable due to work pressure.

Here is what I meant,
The required toggle applies to all all fields at once. So whether it's on or off, all fields are the same and nothing gets labeled.

What I recommended was keeping the existing required toggle, but adding a second control called fieldDistribution with options:

'All Same' (current behavior)
'Mostly Required' (e.g., 15 required, 3 optional)
'Mostly Optional' (e.g., 3 required, 15 optional)
This way you can still test validation with required on/off, AND see the minority-marking feature working too.

@czarflix
Copy link
Contributor Author

@oandregal I also noticed that the panel layouts (dropdown/modal) weren't passing markWhenOptional through the children render prop , will fix that.

For the Storybook enhancement, let me know if the fieldDistribution approach works and I'll implement it and push the changes together.

@mcsf
Copy link
Contributor

mcsf commented Jan 29, 2026

@czarflix, you have so far taken time and attention from at least 3 lead contributors, while communicating exclusively via LLM-generated responses. If you cannot defend the work nor explain it as a person when asked, and are unable to follow up, then let's stop wasting more time and close this pull request.
I've labeled this PR accordingly and we'll allow a grace period while we wait for your feedback.

Hey @mcsf, sorry for the confusion! English isn't my first language so I've been using AI rewriters to help clean up my grammar and formatting before posting , didn't mean to come across as impersonal.

I also have a full-time job and things got hectic this past week, which is why I've been slow to respond.

I'll go through all the feedback today and respond properly. Thanks for your patience

Thank you for your honesty, and for your graceful response to my impatience. Indeed, English isn't the mother tongue of most of us, and I recognise the inherent friction. I can only say this: your short reply here felt more concrete, readable and conducive to debate than anything that came before it. :) I'll also add that, when choosing to use an LLM for translation, one should make the LLM faithfully translate one's words, and never let it take over (substance, form, filler).

@czarflix
Copy link
Contributor Author

@czarflix, you have so far taken time and attention from at least 3 lead contributors, while communicating exclusively via LLM-generated responses. If you cannot defend the work nor explain it as a person when asked, and are unable to follow up, then let's stop wasting more time and close this pull request.
I've labeled this PR accordingly and we'll allow a grace period while we wait for your feedback.

Hey @mcsf, sorry for the confusion! English isn't my first language so I've been using AI rewriters to help clean up my grammar and formatting before posting , didn't mean to come across as impersonal.
I also have a full-time job and things got hectic this past week, which is why I've been slow to respond.
I'll go through all the feedback today and respond properly. Thanks for your patience

Thank you for your honesty, and for your graceful response to my impatience. Indeed, English isn't the mother tongue of most of us, and I recognise the inherent friction. I can only say this: your short reply here felt more concrete, readable and conducive to debate than anything that came before it. :) I'll also add that, when choosing to use an LLM for translation, one should make the LLM faithfully translate one's words, and never let it take over (substance, form, filler).

I will keep this in mind. Thank you for understanding.

@ntsekouras
Copy link
Contributor

I don't think using an asterisk is ideal because despite being a relatively common pattern it's meaning would probably still need to be explained somewhere. For that reason it might be better to display a simple "All fields are required." statement above the fields.

Can we make a decision to move forward with this PR, as it's quite close to landing?

I think the 'auto' algorithm works well, but we need to figure out what to do when all fields are required:

  1. show a message above all fields ( that could possibly be the same place where a form description might be implemented and the message should be appended to the description if provided)
  2. just show the required label for all fields.

We could just go with option 2, which is already the case in trunk right now. @oandregal @jameskoster

@jameskoster
Copy link
Contributor

Option 2 could work as an interim 👍

@oandregal
Copy link
Member

Can we make a decision to move forward with this PR, as it's quite close to landing?

I thought we had one: it's the consumer responsibility to display the message. A potential follow-up to this may be adding a description to layouts that don't support description.

IMO, this PR only needs to update the validation story mentioned here.

@ntsekouras
Copy link
Contributor

ntsekouras commented Feb 3, 2026

IMO, this PR only needs to update the validation story mentioned #74430 (comment).

And these two: 1, 2

);

// Auto-compute: mark the minority of fields
// When counts are equal, mark optional fields (arbitrary but consistent)
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 in the case of equal fields we should show the required label.

czarflix and others added 3 commits February 3, 2026 23:48
… story

- Move markWhenOptional computation from DataForm to DataFormLayout
- Remove markWhenOptional from context (per @ntsekouras)
- Change tie-breaker: equal counts now show required labels (>)
- Fix panel/dropdown and panel/modal to pass markWhenOptional
- Wire up validation story with fieldDistribution control
- Add unit tests for auto-compute logic
- Fixed prettier formatting issues from GitHub merge
- Added missing 'required' dependency to useMemo (for combobox field)
- Added CHANGELOG entry for markWhenOptional feature
@czarflix
Copy link
Contributor Author

czarflix commented Feb 3, 2026

Pushed the changes. Moved markWhenOptional computation to DataFormLayout, fixed the tie-breaker to use >, and wired up all the validation story fields with the fieldDistribution control.

@ntsekouras @oandregal Ready for re-review when you get a chance.

@oandregal
Copy link
Member

@czarflix congrats on your 1st contribution.

I've pushed some changes directly to the PR to speed things up:

  • Remove duplicate entry in changelog in a section already released: f0ed449, 5aa6ddb
  • Remove unnecessary tests (wasn't testing anything) and nickname: 03b5aaa
  • Reverted changes to story. I was not convinced this was a good way to highlight this changes, it's better to address in a follow-up: a5fcf88
  • Removed leftover changes from a refactor: d4958d2
@oandregal oandregal enabled auto-merge (squash) February 4, 2026 09:12
@oandregal oandregal changed the title DataViews: Add markWhenOptional prop to Field API Feb 4, 2026
@oandregal oandregal merged commit 93baec3 into WordPress:trunk Feb 4, 2026
40 checks passed
@github-actions github-actions bot added this to the Gutenberg 22.6 milestone Feb 4, 2026
MaggieCabrera pushed a commit that referenced this pull request Feb 10, 2026
Co-authored-by: czarflix <czarflix@git.wordpress.org>
Co-authored-by: oandregal <oandregal@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: mcsf <mcsf@git.wordpress.org>
Co-authored-by: Mayank-Tripathi32 <mayanktripathi32@git.wordpress.org>
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 First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository Needs Author's Reply [Package] DataViews /packages/dataviews [Type] Enhancement A suggestion for improvement.

5 participants