feat(views): the list toolbar speaks one vocabulary — userActions (#2890) - #2948
Merged
Conversation
…2890) The seven bare `show*` toolbar flags fold into the spec's `userActions` and the renderer reads nothing else; `showDescription` folds into `appearance.showDescription` at the same boundary. The last three — `group` / `hideFields` / `rowColor` — are NEW keys, and they close a capability hole rather than renaming one. The spec documents `userActions` as "which interactive actions are available to users in the view toolbar — each boolean toggles the corresponding toolbar element on/off", and already carries `rowHeight` (objectui's `showDensity` under its spec name). Grouping, column visibility and row coloring are the same kind of toggle: the spec models all three as configuration (`grouping`, `hiddenFields`, `rowColor`) but has no "may the user change it" switch for any of them. That gap was visible in the product. With no `userActions` key to read, the two list surfaces hardcoded OPPOSITE policies — InterfaceListPage pinned all three off, ObjectDataPage pinned two on — and an interface-page author could not turn grouping back on for end users at all. Both now express policy as `userActions` defaults, which an author can override. Until the keys land upstream, @object-ui/types carries them as a documented `.extend()` on `UserActionsConfigSchema`, the shape `ListColumnSchema` already uses while waiting on objectstack#3761. The spec schema is not `.strict()`, so before this an author writing `userActions: { group: false }` had it silently stripped — valid on parse, no effect at render. Defaults unchanged and deliberately asymmetric: search/sort/filter/rowHeight/ group on unless turned off, hideFields/rowColor off unless turned on. Unifying them would grow two buttons on every existing view — its own product decision, not something to smuggle into a vocabulary migration. Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#2890 scope A step 3. The seven bare
show*toolbar flags fold into the spec'suserActions, and the renderer reads nothing else.showDescriptionfolds intoappearance.showDescriptionat the same boundary.showSearch/showSort/showFilters/showDensityuserActions.search/.sort/.filter/.rowHeightshowGroup/showHideFields/showColoruserActions.group/.hideFields/.rowColorshowDescriptionappearance.showDescriptionThe last three are new keys — and they close a capability hole
The spec's
UserActionsConfigSchemadocuments itself as:…and already carries
rowHeight— which is objectui'sshowDensityunder its spec name. Grouping, column visibility and row coloring are the same kind of toggle. The spec models all three as configuration (grouping,hiddenFields,rowColor) but has no "may the user change it" switch for any of them, so an author cannot express a complete toolbar policy.That gap is visible in the product today. With no
userActionskey to read, the two list surfaces hardcoded opposite policies:InterfaceListPage(the ADR-0047 author-curated interface page) pinnedshowHideFields/showGroup/showColoroff — an interface-page author could not turn grouping back on for end users at all;ObjectDataPagepinnedshowGroup/showHideFieldson.Two surfaces, two opposite constants, neither author-controllable. Both now express their policy as
userActionsdefaults, which an author can override. Interface mode stays closed by default — that is a default now, not an unreachable constant.Why the keys live here for the moment
Until they land in
@objectstack/spec,@object-ui/typescarries them as a documented.extend()onUserActionsConfigSchema— the same shapeListColumnSchemaalready uses while waiting on objectstack#3761 — and it collapses into a plain re-export once they do. A spec PR addinggroup/hideFields/rowColorfollows separately; this PR does not depend on it and does not block on the17.0.0-rcrelease window.Worth noting for the AI-authoring path:
UserActionsConfigSchemais not.strict(), so before this an author (or a generative one, reading that docblock and the Airtable reference) writinguserActions: { group: false }had it silently stripped — valid on parse, no effect at render. That is the failure mode this removes.Defaults are unchanged
Deliberately asymmetric, matching what these flags have always done:
search/sort/filter/rowHeight/groupare on unless turned off;hideFields/rowColorare off unless turned on. Making them uniform would grow two buttons on every existing view, so it is left as its own product decision rather than smuggled into a vocabulary migration. The fold applies no defaults — an absent flag stays absent, so the per-flag merge stays honest.Also
Drops a dead relay in app-shell's
ObjectViewthat forwardedshowDescriptiononto the node, althoughListViewhas only ever readappearance.showDescription.Verification
normalize-list-view.test.ts+6: full-flag fold, merge-into-existing-userActions, per-flag canonical precedence, no-defaults-applied, non-boolean passthrough,showDescription→appearance.ListView.test.tsx+4 consumer regressions on the three new toggles, incl. legacy-flag-still-works and canonical-wins-over-legacy.plugin-view/ObjectView.test.tsx: the two tests asserting the oldshow*payload now assertuserActions.core,types,plugin-list,plugin-view,app-shellpass;turbo run type-check32/32; ESLint 0 errors.🤖 Generated with Claude Code