Views: honor all developer-defined view config overrides - #80832
Conversation
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
This PR fixes @wordpress/views view-resolution so server-provided view config overrides are fully honored (especially view_list overrides) while still allowing user preferences to win once a user explicitly changes an overridden setting.
Changes:
- Resolve URL-managed
search/pageas URL param → active override → default view (and exclude them from persistence comparisons). - Apply
type/perPage/fieldsoverrides as “default-bound” (only while the current view still matchesdefaultView), and refine filter override behavior so unlocked filters are user-editable while locked filters remain enforced and never persisted. - Add unit tests covering
useViewURL fallback behavior, overridden layout defaults, and the new override/stripping semantics.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/views/src/use-view.ts | Fixes search/page fallback + persistence comparison; resolves layout defaults using effective type from active overrides. |
| packages/views/src/load-view.ts | Mirrors useView resolution for route loaders, including effective type for layout defaults. |
| packages/views/src/filter-utils.ts | Implements default-bound overrides (type/perPage/fields) and refined locked vs unlocked filter override/strip behavior. |
| packages/views/src/types.ts | Extends ActiveViewOverrides typing to include default-bound and URL-managed keys. |
| packages/views/src/test/use-view.tsx | Adds useView tests for URL/override/default resolution and overridden layout defaults. |
| packages/views/src/test/filter-utils.ts | Adds coverage for new default-bound override and filter lock/unlock semantics. |
| packages/views/package.json | Adds @testing-library/react as a dev dependency for the new hook tests. |
| packages/views/CHANGELOG.md | Documents the behavior fixes under Unreleased bug fixes. |
| package-lock.json | Updates lockfile for the new workspace dev dependency entry. |
|
Size Change: +11 B (0%) Total Size: 7.78 MB 📦 View Changed
|
|
For anyone reviewing: at this point, focus the reviews on "does this work?", "what are the side effects", "is it future proof?" rather than on variable naming, etc. I'm still testing scenarios and verifying the persistance mechanism. |
8079a6a to
9a0008b
Compare
|
Flaky tests detected in 1444e8c. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/30547485693
|
|
I've ran into this scenario #80840 but it also happens in |
9a0008b to
5ca308e
Compare
|
Update: #80832 (comment) The changes to support What changes here is The fallback:
They still work after user changes:
Screen.Recording.2026-07-29.at.13.12.30.mov
Screen.Recording.2026-07-29.at.12.16.58.mov |
7d75aeb to
0793d11
Compare
a80e17f to
c86d925
Compare
|
Prepared backport with PHP changes at WordPress/wordpress-develop#12766 |
|
One of the aspects that is challenging here is how the user preferences have been modeled to work with anything else:
So, there may be situations like this:
But:
I think a simpler model to reason (and compute) would be: store only the user changes, not a whole view. And the hierarchy is core < plugin < user changes. This is, user changes take precedence over anything else, but only for the things they actually changed. That's how However, this is a change with how preferences work and would require users to reset their views. Additionally, the |
mergeOverrides completes a partial sort override from the default view's sort, but stripOverrides compared the view's sort against the raw override, so the completed sort was never stripped. It got persisted on any unrelated change and left useView reporting isModified forever. Compare against the merged shape instead, symmetric with mergeOverrides. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
layout is nested (layout.styles.<field>.<prop>), but merging was shallow and stripping deleted whole top-level keys. An override for one field's styles replaced the styles object, wiping every other field's width and alignment, and stripping then dropped the whole key so the user's own styles were never persisted. Recurse into nested objects on both sides, treating arrays and scalars as leaves. groupBy uses the same helpers; its values are scalars, so its behaviour is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolve the view out of a stack of layers, later ones overriding earlier ones: the default view, the default layouts for the effective type, the active view overrides, the user's preference, and the URL query params. Every layer merges leaf by leaf, so `layout`, `groupBy` and `sort` no longer wipe the siblings the layers below provide, while arrays stay leaves and are replaced wholesale. Persist only the leaves the user's view differs from what the layers below resolve to. A property the user never touched keeps resolving out of those layers, so a later change to any of them shows through; one they did pick sticks, even when it happens to be the value a lower layer already carries. `page` and `search` are sourced from the URL alone and reported back through `onChangeQueryParams` instead of being persisted. Replaces filter-utils' merge/strip pair with resolve-view. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A layout switch reports the new type together with that type's defaultLayouts entry merged in. Diffing against the base resolved at the previous type persisted the differences between the two entries as user modifications, which lingered as phantoms after switching back — the view looked default but stayed marked as modified. See #80832 (comment) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
I think it's fine that preferences stored by the old model keep working as they do today. That keeps their current setup stable. |
ntsekouras
left a comment
There was a problem hiding this comment.
I think that's ready to land. Thanks for all the iterations!
a049c80 to
3cbf504
Compare
|
I just cherry-picked this PR to the wp/7.1 branch to get it included in the next release: ad20d8f |
| * WordPress dependencies | ||
| */ | ||
| import { createRegistry, RegistryProvider } from '@wordpress/data'; | ||
| // @ts-ignore - Preferences package is not typed |
There was a problem hiding this comment.
This is not correct. The preferences store is fully typed. Apart from that, we should use // @ts-expect-error to ensure this suppression is flagged when things change.
Also, I just now noticed that the package uses React without declaring react or react-dom as a dependency.
This updates the pinned commit hash of the Gutenberg repository from `fd715a6833679d098d9fee84b642f8f1bc27341b` to `f05e40e91c54f29c449b1f33d0db89f5166812d9`. A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@fd715a6...f05e40e - Writing flow: forward delete an empty paragraph without breaking apart the next block (WordPress/gutenberg#80813) - Upload Media: Fail the item when the /finalize request fails (WordPress/gutenberg#80725) - Fix template `modified` and `date` return value for file templates (WordPress/gutenberg#80733) - Boot: Adjust specificity of the image reset styles so components can size their own images (WordPress/gutenberg#80845) - Quote: Ensure paragraph placeholder appears after deleting nested blocks (WordPress/gutenberg#77151) - Block editor: make the Group action wrap blocks with a group transform (WordPress/gutenberg#80891) - Copy: preserve the block when its entire text is selected (WordPress/gutenberg#80994) - Add opt-out for block style state controls (WordPress/gutenberg#80956) (WordPress/gutenberg#81004) - Tabs: Support Home and End keys for keyboard navigation (WordPress/gutenberg#80912) - Rename blockStatesEnabled setting to blockStatesEditingEnabled (WordPress/gutenberg#81058) - [WP 7.1] Background: Fix the legacy gradient UI where a gradient cannot be selected (WordPress/gutenberg#81059) - Views: honor developer-defined view config overrides (WordPress/gutenberg#80832) - Playlist: Add track icon (WordPress/gutenberg#81078) - Remove the CODEOWNERS file from wp/7.1. (WordPress/gutenberg#81104) - Notes: Email users mentioned in a note (WordPress/gutenberg#79606) - Backport 81068 80744 80642 (WordPress/gutenberg#81135) - Site Editor: Add E2E coverage for view config extensibility (WordPress/gutenberg#80577) - change from WordPress/gutenberg#81068 (WordPress/gutenberg#81140) - Link Control: Restore the preview title underline (WordPress/gutenberg#81083) - Button: Suppress UA focus ring when focused and pressed (WordPress/gutenberg#81113) - View config: add reference docs (WordPress/gutenberg#81149) - Editor: Fix document tools button focus ring (WordPress/gutenberg#81115) - Interface: Increase footer breadcrumb height to prevent focus ring clipping (WordPress/gutenberg#81156) - Post editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81112) - Pass Playlist controls to track blocks (WordPress/gutenberg#81158) - Theme: Omit color properties when neither provided nor inherited (WordPress/gutenberg#80600) (WordPress/gutenberg#81172) - Media: Improve the HEIC upload error and keep any upload errors up until dismissed (WordPress/gutenberg#81130) - Video: Hide settings for the GIF variation (WordPress/gutenberg#81142) - Video: clarify the Video variation description (WordPress/gutenberg#81181) - Button: turn on the width setting by default in theme.json (WordPress/gutenberg#81196) - Edit Widgets: Fix header toolbar button focus ring (WordPress/gutenberg#81176) - Build: Wrap script bundles in an IIFE to contain 'use strict' (WordPress/gutenberg#79792) - Customizer widgets: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81174) - Fix: Tabs block: Start with empty tab labels with placeholders (WordPress/gutenberg#81197) - PanelColorSettings: Restore the missing space below the panel header (WordPress/gutenberg#81155) - Visual revisions: add shareable urls (WordPress/gutenberg#81205) - Notes: fix the mention notification email composition (WordPress/gutenberg#81187) - Fix ESLint warnings for 'navigateRegionsProps' spread (WordPress/gutenberg#81208) - Widgets editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81173) - Remove the editableRoot opt-in from the paragraph block (WordPress/gutenberg#81184) - Media Attached to: Fix issue with the popover unexpectedly flipping, tweak wording (WordPress/gutenberg#81206) - Ensure device preview is always accurate when window is zoomed in (WordPress/gutenberg#81215) Props wildworks. See #65529. git-svn-id: https://develop.svn.wordpress.org/trunk@63026 602fd350-edb4-49c9-b593-d223f7449a82
This updates the pinned commit hash of the Gutenberg repository from `fd715a6833679d098d9fee84b642f8f1bc27341b` to `f05e40e91c54f29c449b1f33d0db89f5166812d9`. A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@fd715a6...f05e40e - Writing flow: forward delete an empty paragraph without breaking apart the next block (WordPress/gutenberg#80813) - Upload Media: Fail the item when the /finalize request fails (WordPress/gutenberg#80725) - Fix template `modified` and `date` return value for file templates (WordPress/gutenberg#80733) - Boot: Adjust specificity of the image reset styles so components can size their own images (WordPress/gutenberg#80845) - Quote: Ensure paragraph placeholder appears after deleting nested blocks (WordPress/gutenberg#77151) - Block editor: make the Group action wrap blocks with a group transform (WordPress/gutenberg#80891) - Copy: preserve the block when its entire text is selected (WordPress/gutenberg#80994) - Add opt-out for block style state controls (WordPress/gutenberg#80956) (WordPress/gutenberg#81004) - Tabs: Support Home and End keys for keyboard navigation (WordPress/gutenberg#80912) - Rename blockStatesEnabled setting to blockStatesEditingEnabled (WordPress/gutenberg#81058) - [WP 7.1] Background: Fix the legacy gradient UI where a gradient cannot be selected (WordPress/gutenberg#81059) - Views: honor developer-defined view config overrides (WordPress/gutenberg#80832) - Playlist: Add track icon (WordPress/gutenberg#81078) - Remove the CODEOWNERS file from wp/7.1. (WordPress/gutenberg#81104) - Notes: Email users mentioned in a note (WordPress/gutenberg#79606) - Backport 81068 80744 80642 (WordPress/gutenberg#81135) - Site Editor: Add E2E coverage for view config extensibility (WordPress/gutenberg#80577) - change from WordPress/gutenberg#81068 (WordPress/gutenberg#81140) - Link Control: Restore the preview title underline (WordPress/gutenberg#81083) - Button: Suppress UA focus ring when focused and pressed (WordPress/gutenberg#81113) - View config: add reference docs (WordPress/gutenberg#81149) - Editor: Fix document tools button focus ring (WordPress/gutenberg#81115) - Interface: Increase footer breadcrumb height to prevent focus ring clipping (WordPress/gutenberg#81156) - Post editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81112) - Pass Playlist controls to track blocks (WordPress/gutenberg#81158) - Theme: Omit color properties when neither provided nor inherited (WordPress/gutenberg#80600) (WordPress/gutenberg#81172) - Media: Improve the HEIC upload error and keep any upload errors up until dismissed (WordPress/gutenberg#81130) - Video: Hide settings for the GIF variation (WordPress/gutenberg#81142) - Video: clarify the Video variation description (WordPress/gutenberg#81181) - Button: turn on the width setting by default in theme.json (WordPress/gutenberg#81196) - Edit Widgets: Fix header toolbar button focus ring (WordPress/gutenberg#81176) - Build: Wrap script bundles in an IIFE to contain 'use strict' (WordPress/gutenberg#79792) - Customizer widgets: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81174) - Fix: Tabs block: Start with empty tab labels with placeholders (WordPress/gutenberg#81197) - PanelColorSettings: Restore the missing space below the panel header (WordPress/gutenberg#81155) - Visual revisions: add shareable urls (WordPress/gutenberg#81205) - Notes: fix the mention notification email composition (WordPress/gutenberg#81187) - Fix ESLint warnings for 'navigateRegionsProps' spread (WordPress/gutenberg#81208) - Widgets editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81173) - Remove the editableRoot opt-in from the paragraph block (WordPress/gutenberg#81184) - Media Attached to: Fix issue with the popover unexpectedly flipping, tweak wording (WordPress/gutenberg#81206) - Ensure device preview is always accurate when window is zoomed in (WordPress/gutenberg#81215) Props wildworks. See #65529. Built from https://develop.svn.wordpress.org/trunk@63026 git-svn-id: http://core.svn.wordpress.org/trunk@62245 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This updates the pinned commit hash of the Gutenberg repository from `fd715a6833679d098d9fee84b642f8f1bc27341b` to `f05e40e91c54f29c449b1f33d0db89f5166812d9`. A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@fd715a6...f05e40e - Writing flow: forward delete an empty paragraph without breaking apart the next block (WordPress/gutenberg#80813) - Upload Media: Fail the item when the /finalize request fails (WordPress/gutenberg#80725) - Fix template `modified` and `date` return value for file templates (WordPress/gutenberg#80733) - Boot: Adjust specificity of the image reset styles so components can size their own images (WordPress/gutenberg#80845) - Quote: Ensure paragraph placeholder appears after deleting nested blocks (WordPress/gutenberg#77151) - Block editor: make the Group action wrap blocks with a group transform (WordPress/gutenberg#80891) - Copy: preserve the block when its entire text is selected (WordPress/gutenberg#80994) - Add opt-out for block style state controls (WordPress/gutenberg#80956) (WordPress/gutenberg#81004) - Tabs: Support Home and End keys for keyboard navigation (WordPress/gutenberg#80912) - Rename blockStatesEnabled setting to blockStatesEditingEnabled (WordPress/gutenberg#81058) - [WP 7.1] Background: Fix the legacy gradient UI where a gradient cannot be selected (WordPress/gutenberg#81059) - Views: honor developer-defined view config overrides (WordPress/gutenberg#80832) - Playlist: Add track icon (WordPress/gutenberg#81078) - Remove the CODEOWNERS file from wp/7.1. (WordPress/gutenberg#81104) - Notes: Email users mentioned in a note (WordPress/gutenberg#79606) - Backport 81068 80744 80642 (WordPress/gutenberg#81135) - Site Editor: Add E2E coverage for view config extensibility (WordPress/gutenberg#80577) - change from WordPress/gutenberg#81068 (WordPress/gutenberg#81140) - Link Control: Restore the preview title underline (WordPress/gutenberg#81083) - Button: Suppress UA focus ring when focused and pressed (WordPress/gutenberg#81113) - View config: add reference docs (WordPress/gutenberg#81149) - Editor: Fix document tools button focus ring (WordPress/gutenberg#81115) - Interface: Increase footer breadcrumb height to prevent focus ring clipping (WordPress/gutenberg#81156) - Post editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81112) - Pass Playlist controls to track blocks (WordPress/gutenberg#81158) - Theme: Omit color properties when neither provided nor inherited (WordPress/gutenberg#80600) (WordPress/gutenberg#81172) - Media: Improve the HEIC upload error and keep any upload errors up until dismissed (WordPress/gutenberg#81130) - Video: Hide settings for the GIF variation (WordPress/gutenberg#81142) - Video: clarify the Video variation description (WordPress/gutenberg#81181) - Button: turn on the width setting by default in theme.json (WordPress/gutenberg#81196) - Edit Widgets: Fix header toolbar button focus ring (WordPress/gutenberg#81176) - Build: Wrap script bundles in an IIFE to contain 'use strict' (WordPress/gutenberg#79792) - Customizer widgets: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81174) - Fix: Tabs block: Start with empty tab labels with placeholders (WordPress/gutenberg#81197) - PanelColorSettings: Restore the missing space below the panel header (WordPress/gutenberg#81155) - Visual revisions: add shareable urls (WordPress/gutenberg#81205) - Notes: fix the mention notification email composition (WordPress/gutenberg#81187) - Fix ESLint warnings for 'navigateRegionsProps' spread (WordPress/gutenberg#81208) - Widgets editor: Add ThemeProvider for admin color schemes (WordPress/gutenberg#81173) - Remove the editableRoot opt-in from the paragraph block (WordPress/gutenberg#81184) - Media Attached to: Fix issue with the popover unexpectedly flipping, tweak wording (WordPress/gutenberg#81206) - Ensure device preview is always accurate when window is zoomed in (WordPress/gutenberg#81215) Props wildworks. See #65529. git-svn-id: https://develop.svn.wordpress.org/trunk@63026 602fd350-edb4-49c9-b593-d223f7449a82
Fixes #80778.
Backport at WordPress/wordpress-develop#12766
What?
Fix
useViewhook so that the server-side view config filters are respected:searchandpageURL params: ignored for now (see conversation). They cannot be set via PHP.view_listoverrides fortype,perPage,fieldsare now applied, users can modify unlocked filters provided by a viewWhy?
Closes #80778.
How?
@wordpress/viewsonly merged a fixed set of override keys, sotype,perPage, andfieldsfromview_listwere silently ignored (e.g. the bundled "Trash" view rendered as a list despite being configured as a table).In
mergeActiveViewOverrides/stripActiveViewOverrides,type,perPage, andfieldsnow follow the same pattern assort: the override applies while the view still matches the default view, so an explicit user change wins and is persisted. Locked filters keep replacing same-field filters and are never persisted, while unlocked filters act as defaults that a user-modified filter beats.Testing Instructions
Add the two filter callbacks from the issue description (#80778) to any PHP file, then open Pages in the Site Editor: the "My view" tab should load with the grid layout, page size, and fields from the config, and its status filter should be user-editable; the bundled "Trash" view should render as a table.
Use of AI Tools
This PR (investigation, code, tests, and description) was authored with Claude Code using the Claude Fable 5 model, directed and reviewed by a human contributor.
Follow-ups