[RFC]: Collapsed-by-default categories in the Controls args table #35737
eliasthompson
started this conversation in
RFC
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Add a
parameters.controls.categoriesparameter that lets users mark args-table categories as collapsed by default, in both the Controls panel and theArgTypes/Controlsdoc blocks. Because it's a plain-object parameter, Storybook's standard parameter inheritance provides layered configuration for free: a global default inpreview.ts, overridable per component or per story. The rendering component already supports this —SectionRowhas aninitialExpandedprop that is never wired to any public API — so this RFC is primarily about exposing existing behavior.Problem Statement
Design systems increasingly add shared cross-cutting props (layout, spacing, accessibility passthroughs) to every component. Grouping them with
table.categorykeeps the args table organized, but every category always renders fully expanded, so a component's own distinctive props get buried under dozens of rows of shared boilerplate on every single story. Users can collapse a category by clicking its header, but that state resets on every story navigation, making it useless as a curation tool.Maintainers currently have no way to say "this category is reference material — keep it available, but out of the way." The existing escape hatches all sacrifice documentation:
controls.excludeandtable.disableremove the props entirely, andcontrols.sortreorders but doesn't reduce noise.This was previously requested in #18487 (2022). It was closed as not planned in May 2026, with the closing comment inviting a fresh RFC — this is that RFC.
Non-goals
argTypesdeclaration order.controls.exclude/table.disablealready cover that.Implementation
Proposed API — an object map keyed by category label (the same strings used in
table.category):The object-map shape is deliberate:
combineParametersdeep-merges plain objects across the global → component → story levels, so a component can override one category without restating the rest of the global config. (An array likecollapsedCategories: string[]would be replaced wholesale by the more specific level — see Alternatives.) An object per category also leaves headroom for future per-category options without new top-level parameters.Wiring is small because the UI already supports it:
SectionRow(code/addons/docs/src/blocks/components/ArgsTable/SectionRow.tsx) already acceptsinitialExpanded?: boolean(defaulttrue); it is currently never passed by either call site.ArgsTable(.../ArgsTable/ArgsTable.tsx) renders aSectionRowper category and subcategory. It gains a prop carrying the categories config and passesinitialExpanded: !categories?.[label]?.collapsedat both call sites.ArgTypes/Controlsdoc blocks (which share thisArgsTablecomponent) readparameters.controls.categoriesand thread it through, alongside the existing handling ofcontrols.sort/controls.expanded.Prior Art
controls.sort,controls.expanded, andcontrols.excludeestablish the pattern of table-presentation options living underparameters.controlswith inheritance.Deliverables
parameters.controls.categoriesthreaded through the Controls panel and doc blocks intoArgsTable→SectionRow, plus TypeScript types.ArgsTablein collapsed/expanded/override states.This fits comfortably in a single small PR; listed as three deliverables only for review clarity.
Risks
table.categoryitself works, but worth stating.Unresolved Questions
categories: { Layout: { collapsed: true, subcategories: {...} } }) vs. a path key ('Layout/Spacing') vs. category-level only for v1?controls.categories(proposed) vs. something more explicit likecontrols.categoryDefaults?parameters.controls.categories, or do docs need an independentparameters.docs-level override?Alternatives considered / Abandoned Ideas
collapsedCategories: string[]— simplest shape, butcombineParametersreplaces arrays wholesale at more specific levels. A component wanting to expand one globally-collapsed category would have to restate every other global entry, which rots as the global list changes. The object map deep-merges and avoids this.table.initialExpanded— puts the setting on individual args, but a category spans many args, so conflicting values need arbitrary tie-breaking, and it's maximally verbose for the common "collapse this shared category everywhere" case.manager-head.htmlMutationObserver that auto-clicks section toggles (fragile, flashes, breaks silently on DOM changes) orpatch-packageagainst bundled dist files (breaks on every Storybook upgrade). Both exist in the wild precisely because there's no supported option.All reactions