Skip to content

Fix: empty Storybook args tables for slot parts [WIP]#206

Open
codingwolf-at wants to merge 87 commits into
mainfrom
fix/broken-stories
Open

Fix: empty Storybook args tables for slot parts [WIP]#206
codingwolf-at wants to merge 87 commits into
mainfrom
fix/broken-stories

Conversation

@codingwolf-at

@codingwolf-at codingwolf-at commented Jun 25, 2026

Copy link
Copy Markdown

Description

Several component autodocs pages in Storybook were rendering "Args table couldn't be auto-generated" in place of a props table for their atomic "slot" subcomponents (icon/label/body/footer/spinner wrappers).

Root cause — two things compounding:

  1. Our docgen filter in .storybook/main.ts intentionally strips props inherited from React/DOM types so the tables only show propel's own props. These slot parts wrap a bare <span>/<div>/etc. and have no propel-defined props — their entire API is children — so the filter left them with zero props → the empty state.
    react-docgen-typescript doesn't emit children at all unless a component explicitly declares it in its props type.
    Fix — two parts:

  2. Whitelisted children in the docgen propFilter (so the composition slot is documentable while still hiding the rest of the inherited DOM attributes).
    Added an explicit, TSDoc'd children to each affected slot's props type. This is type-only and additive — children was always accepted via the {...props} spread, so there is no runtime/behavioral change.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

NA

Test Scenarios

  • Docgen extraction — ran react-docgen-typescript directly on each edited file; every previously-empty part now reports ["children"] (or render/variant props where applicable).
  • Live docs — opened each component's Storybook docs page and confirmed zero "couldn't be auto-generated" tabs (Accordion, AlertDialog, Badge, Banner, Button, IconButton, AnchorButton, Checkbox, CircularProgress, ContextMenu, Dialog, Drawer).
  • vp check — formatting, lint, and type-check all pass (818 files, no errors).
  • Story tests — vp test run .stories passes for every touched component (no behavioral regressions, since the change is type-only).

References

  • Storybook docgen config: packages/propel/.storybook/main.ts (typescript.reactDocgenTypescriptOptions.propFilter)
  • react-docgen-typescript behavior: omits children unless explicitly declared; attributes inherited props to @types/react (which the filter drops)

The 243 Base-UI-derived parts already supported `render` (prop passthrough), but the
~57 parts we build ourselves (slots, labels, semantic containers) rendered a bare
`<tag {...props}/>` that silently dropped `render` — an observable inconsistency. Convert
them to Base UI's `useRender` directly (no wrapper) so every part has the same element
contract: `render` polymorphism, `className` merging, ref forwarding. Each part's props
now derive from `useRender.ComponentProps<Tag>`.

Also fixes the `mergeProps` argument order in the 3 pre-existing useRender exemplars
(breadcrumb-trigger, nav-item, pagination-per-page-trigger): per the Base UI docs the
order is `mergeProps(defaultProps, externalProps)` so consumer props win — they had it
reversed (defaults won, so a consumer couldn't override aria-*/type/etc.).

Excludes `ui/table/table.tsx` (a true multi-element composition — a `<table>` inside a
scroll frame), not a single styled element.

vp check + build (attw/publint) clean; full suite 435/435.
ui AvatarGroup is now a single styled <div> (the overlapping stack); the components
ready-made owns the AvatarGroupContext.Provider that shares magnitude with child Avatars.
Composition lives in components, ui stays single-element.
ui ToggleGroup is now a single BaseToggleGroup (select state + roving focus only); the
components ready-made owns the ToggleGroupContext.Provider that shares magnitude. ui story
wires the context explicitly.
ui Toolbar is a single BaseToolbar.Root (its density still styles the row); the components
ready-made owns the ToolbarDensityContext.Provider that shares density with the controls. ui
story wires the context explicitly.
ui Tabs is a single Tabs.Root and ui TabsList a single Tabs.List (no provider, no baked
indicator, no cx). The components ready-made owns the TabsVariantContext provider, composes
the horizontal scroll frame (new single-element ui TabsListScrollArea + reused ui ScrollArea
scrollbar/thumb), and renders the underline TabsIndicator. ui story wires the context.
…to components

ui Table is now a single render-capable <table>. New single-element ui parts TableScrollArea
(ScrollArea.Root) + TableScrollAreaViewport (ScrollArea.Viewport) carry the frame chrome; the
components ready-made composes them with the reused ui ScrollArea scrollbar/thumb/corner and
owns the TableVariantContext provider. ui story wires the variant context.
Also renamed tableRootVariants->tableScrollAreaVariants, tableViewportVariants->tableScrollAreaViewportVariants.
…concern)

ui Avatar is now prop-only (magnitude defaults md, no useContext). AvatarGroupContext lives in
components/avatar; the components Avatar reads it and passes the effective magnitude down, so the
ui primitive doesn't reach into a shared context.
…ncern)

ui Tab/TabsList are now prop-driven (variant required, no useContext); the TabsVariant type stays
in ui (it's a styling type). TabsVariantContext lives in components/tabs; components Tab/TabsList
read it and omit variant from their API + pass it to the ui part. ui story passes variant props.
ui Table is a single <table>; ui TableCell/TableHead are prop-driven (variant required, no
useTableVariant). The context+hook live in components/table; the components cell/head parts
(TableCell, TableHead, TableActionCell, TableEditableCell) read the context and pass variant to
their ui part, omitting it from their own API. TableVariant/TablePinned types stay in ui.
ui Toggle is now prop-driven (magnitude required, no useContext). ToggleGroupContext lives in
components/toggle; a new components Toggle reads it (magnitude override -> group -> md) and passes
it down, so consumers omit magnitude inside a ToggleGroup. ui toggle-group story sizes each Toggle.
ui ToolbarButton/ToolbarToggle/ToolbarMenuTriggerButton are now prop-driven (density required, no
useContext). The context lives in components/toolbar; new components ToolbarButton/ToolbarToggle/
ToolbarMenuTriggerButton read it (density override -> toolbar density) and omit density from their
API. ToolbarDensity/ToolbarElevation types stay in ui; comment pattern uses the components toolbar.
A ui element must not default a variant prop. ui Avatar's magnitude is now required; the
components Avatar keeps it optional and resolves the effective value (group context, else md).
…ntion)

buttonVariants -> ButtonVariantProps + per-key types (ButtonVariant/Tone/Magnitude/Emphasis/
Stretch) now live in variants.ts; button.tsx imports them for ButtonOwnProps and re-exports them.
Reference for the codebase-wide convention.
…defaulted)

internal/variant-props.ts: StrictVariantProps<cva, DefaultedKeys> makes every variant axis required
(non-null) unless it has a configured default, so an axis with no fallback can't be omitted (no
impossible states). Button uses it: variant/tone/magnitude required; emphasis/stretch optional via
a real defaultVariants ({emphasis:solid, stretch:auto}). ButtonProps = Omit<Base> & ButtonVariantProps
(no hand-built ButtonOwnProps).
Codifies the base/ui/components/internal tiers and the hard rules: single-element ui parts; cva only
in ui named after the part (no Root, no generic names); className/style exposed only at base (Base
UI convention), hidden at ui/components; no cross-component Props/cva/type coupling (share via
internal); StrictVariantProps for variant-prop types (optional iff defaulted; no defaultVariants
today so all required); context + defaults are components concerns.
ui IconButtonRoot -> IconButton; iconButtonRootVariants -> iconButtonVariants as a self-contained
cva (owns its variant/tone/magnitude chrome + geometry; no buttonVariants/ButtonProps import). Types
derive from its own cva via StrictVariantProps. components IconButton aliases the ui part as
IconButtonElement (no Root idiom). Removes the cross-component coupling the protocol forbids.
… fix call sites

ButtonProps = Omit<BaseButton.Props> & ButtonVariantProps (StrictVariantProps; no defaultVariants
today so variant/tone/magnitude/emphasis/stretch are all required). Supplies emphasis/stretch at the
~15 Button call sites (interim solid/auto; sensible defaults to be settled later).
…e it

internal/control-chrome.ts holds the chrome shared by Button (non-link) and IconButton — behavior
base + neutral/danger palette per Type. internal/compose-variants.ts adds composeVariants(shared,
local) = cx(shared(props), local(props)), typed as the intersection of both cvas' props (so a local
cva narrows axes out — IconButton has no link/emphasis/stretch). buttonVariants/iconButtonVariants
are now composeVariants(controlChrome, <local>). No cross-component coupling, no duplicated chrome.
Verified style-stable: the class set for every variant combo is byte-identical to before.
…rol)

Per the protocol: per-key types + <Name>VariantProps via StrictVariantProps live in variants.ts;
Props = Omit<Base.Props> & <Name>VariantProps. avatar-fallback's tone is now required (no JS
default), matching the no-defaults rule — all callers already pass it.
…dialog-popup)

Normalizes the variant-prop typing: banner-body/banner-icon move from raw VariantProps (all
optional) to StrictVariantProps (required, callers already pass variant+tone); dialog-popup moves
from Required<Pick<VariantProps,...>> to StrictVariantProps. Per-key types + <Name>VariantProps in
variants.ts; Props = Omit<Base.Props> & <Name>VariantProps.
…oup)

Required<VariantProps>/local raw aliases -> exported StrictVariantProps in variants.ts; Props =
Omit<Base.Props> & <Name>VariantProps.
…cator, circle, circle-indicator)

Each progress cva is single-axis, so raw VariantProps / Required<Pick<...>> all normalize to
StrictVariantProps. Per-component <Name>VariantProps in variants.ts; Props = Omit<Base> & it.
…radio/link/submenu-trigger)

The four item variants share contextMenuItemVariants -> one ContextMenuItemVariantProps; submenu
trigger uses ContextMenuSubmenuTriggerVariantProps. Drops the duplicated per-component tone aliases.
…r + fallback)

menu-popup surface, workspace-avatar magnitude -> StrictVariantProps. workspace-avatar-fallback tone
is now required (no default; all callers already pass it). MenuItem.emphasis and NavItem.level held
back pending the defaults decision (their make-required cascade is large).
lifeiscontent and others added 3 commits June 25, 2026 13:42
…ue ui<->components 1:1

components/{linear,circular}-progress had no ui counterpart, violating the contract (components is the
public API; ui/base are the unwrapped escape hatch — so every ready-made needs matching building
blocks). Split the shared ui/progress parts library into ui/linear-progress (LinearProgress + Track/
Indicator/Value/Label) and ui/circular-progress (CircularProgress + Svg/Track/Indicator), renaming the
parts; dropped ui/progress + components/progress. Rewrote the two ready-mades to compose their own ui
home (and fixed CircularProgress to derive magnitude/tone from the circular types, not the linear ones).
Now 54 ui <-> 54 components, fully bijective.
- Updated AccordionPanelContent, AccordionTriggerIcon, AccordionTriggerIndicator, and AccordionTriggerTitle to include an optional `children` prop for better content flexibility.
- Adjusted prop filtering in Storybook configuration to ensure `children` is documented correctly, allowing for proper rendering in the args table.

This change improves the usability of the Accordion components by allowing users to pass custom content directly, enhancing the overall component architecture.
@codingwolf-at codingwolf-at changed the base branch from main to feat/render-capable-base June 25, 2026 07:57
@github-actions

Copy link
Copy Markdown

📚 Storybook preview: https://pr-206-propel-storybook.vamsi-906.workers.dev

- Updated AlertDialogActionsProps, AlertDialogHeaderProps, and AlertDialogIntroProps to include an optional `children` prop for improved content flexibility.
- Modified the corresponding TypeScript definitions to allow for custom content within these components.

This change enhances the usability of the AlertDialog components by enabling users to pass custom children elements, improving overall component architecture.
- Added an optional `children` prop to the BadgeDismissProps type, allowing for customizable content within the BadgeDismiss component.
- Updated TypeScript definitions to reflect this new prop, improving flexibility for users.

This change enhances the BadgeDismiss component by enabling the inclusion of custom elements, aligning with recent updates to other components for better content management.
- Added an optional `children` prop to the BannerDescriptionProps and BannerDismissProps types, allowing for customizable content within the BannerDescription and BannerDismiss components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates to other components, enhancing the overall content management capabilities of the Banner components.
- Introduced `Menu` and `MenuItem` components to the Breadcrumb stories, enhancing the MenuTrigger story with a menu-style crumb.
- Implemented an inert anchor function to prevent default navigation behavior, improving the testing experience.
- Updated the MenuTrigger story to utilize `BreadcrumbMenuTrigger` and `MenuContent`, allowing for a more interactive breadcrumb navigation experience.

This change aligns with recent enhancements across components, improving usability and flexibility in the Breadcrumb component's presentation.
- Added an optional `children` prop to the AnchorButtonSpinnerProps, ButtonSpinnerProps, and IconButtonSpinnerProps types, allowing for customizable spinner glyphs within the respective components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the spinner components.
- Added an optional `children` prop to the CheckboxInlineStartNodeProps type, allowing for customizable content within the component.
- Updated TypeScript definitions to reflect this new prop, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the CheckboxInlineStartNode component.
- Added an optional `children` prop to the CircularProgressSvgProps and CircularProgressTrackProps types, allowing for customizable content within the CircularProgress components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the CircularProgress components.
- Added an optional `children` prop to the ContextMenuItemIconProps, ContextMenuItemIndicatorProps, ContextMenuItemLabelProps, ContextMenuItemShortcutProps, and ContextMenuSubmenuTriggerIndicatorProps types, allowing for customizable content within these components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the context menu components.
- Added an optional `children` prop to DialogActionsProps, DialogBodyProps, DialogHeaderProps, DialogHeadingProps, DrawerFooterProps, DrawerHeaderProps, and DrawerHeaderContentProps types, allowing for customizable content within these components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the dialog and drawer components.
@codingwolf-at codingwolf-at changed the title Fix/broken stories [WIP Code & Desc] Fix: empty Storybook args tables for slot parts [WIP] Jun 25, 2026
- Added an optional `children` prop to the IconButtonIconProps type, allowing for customizable content within the IconButtonIcon component.
- Updated TypeScript definitions to reflect this new prop, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the IconButtonIcon component.
- Added an optional `children` prop to various menu-related component types, including MenuItemContentProps, MenuItemControlProps, MenuItemDescriptionProps, MenuItemSecondaryTextProps, MenuItemSelectedIndicatorProps, MenuItemSubmenuIndicatorProps, MenuItemTitleRowProps, MenuItemTitleProps, MenuItemTrailingProps, MenuLabelMetaProps, and MenuLabelTitleProps.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the menu components.
- Added an optional `children` prop to MenubarTriggerIconProps and MenubarTriggerLabelProps types, allowing for customizable content within the menubar components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the menubar components.
- Added an optional `children` prop to NavigationMenuContentListProps, NavigationMenuLinkDescriptionProps, NavigationMenuLinkTitleProps, and NavigationMenuTriggerLabelProps types, allowing for customizable content within these components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the navigation menu components.
- Added an optional `children` prop to NavItemHeaderActionProps, NavItemHeaderIndicatorProps, NavItemHeaderLabelProps, and NavItemTrailingProps types, allowing for customizable content within these components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the nav item components.
- Added an optional `children` prop to PaginationArrowButtonProps, PaginationEllipsisProps, PaginationPerPageIndicatorProps, PaginationPerPageLabelProps, PaginationRangeCurrentProps, and PaginationSpinnerProps types, allowing for customizable content within these pagination components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the pagination components.
- Added an optional `children` prop to PopoverActionsProps type, allowing for customizable content within the popover actions component.
- Updated TypeScript definitions to reflect this new prop, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the popover components.
- Added an optional `children` prop to PreviewCardBodyProps, PreviewCardDescriptionProps, and PreviewCardTitleProps types, allowing for customizable content within the preview card components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the preview card components.
- Added an optional `children` prop to TableCellContentProps, TableCellLayoutProps, TableCellSlotProps, TableCellTriggerIndicatorProps, TableCellTriggerLabelProps, TableHeadSortIndicatorProps, TableHeadSortTriggerProps, and TableHeadTitleProps types, allowing for customizable content within these table components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the table components.
- Added an optional `children` prop to ToastActionButtonProps, ToastActionGroupProps, ToastProviderProps, and ToastTextGroupProps types, allowing for customizable content within these toast components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the toast components.
- Added an optional `children` prop to ToolbarItemIconProps, ToolbarMenuTriggerIndicatorProps, and ToolbarMenuTriggerLabelProps types, allowing for customizable content within these toolbar components.
- Updated TypeScript definitions to reflect these new props, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the toolbar components.
- Added an optional `children` prop to TooltipShortcutProps type, allowing for customizable content within the tooltip component.
- Updated TypeScript definitions to reflect this new prop, improving flexibility for users.

This change aligns with recent updates across components, enhancing the overall content management capabilities of the tooltip components.
Base automatically changed from feat/render-capable-base to main June 26, 2026 11:54
@lifeiscontent lifeiscontent changed the base branch from main to fix/table-fieldlabel-variantprops June 26, 2026 12:30
@lifeiscontent lifeiscontent changed the base branch from fix/table-fieldlabel-variantprops to main June 26, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants