Skip to content

Align breadcrumb to architecture goals#203

Open
lifeiscontent wants to merge 3 commits into
mainfrom
align/breadcrumb
Open

Align breadcrumb to architecture goals#203
lifeiscontent wants to merge 3 commits into
mainfrom
align/breadcrumb

Conversation

@lifeiscontent

Copy link
Copy Markdown
Collaborator

Closes #121.

What the spec says

From the designer's comment on #121:

Always the same (baked in): horizontal layout, separators and gap between items, last-item non-interactive + visually distinct (text-primary), inline-flex alignment, font style, focus ring on interactive items.

Depends / adjustable (caller-controlled): number of items, labels, separator style (slash vs chevron — passed as children on BreadcrumbSeparator), navigation targets, truncation strategy, whether icons appear alongside labels.

Architecture changes

ui/breadcrumb/variants.ts

  • Added crumbItemVariants (was a bare string literal in BreadcrumbItem).
  • Added crumbListVariants (was a bare string literal inside Breadcrumb's <ol>).
  • Added crumbSeparatorVariants — includes --node-size:0.875rem, [&>svg]:size-(--node-size), and rtl:[&>svg]:-scale-x-100 so the separator sizes and RTL-mirrors any icon child without baking a className on it.
  • Merged crumbVariants({ interactive: false }) so BreadcrumbPage's text-primary lives in the cva, not in a cx() call in the component file.
  • Replaced the two-cva cx(crumbVariants(...), crumbTriggerVariants(...)) composition in BreadcrumbTrigger with a single self-contained crumbTriggerVariants that includes all the base pill styles plus open-state shifts. Also sets [--node-size:0.875rem] for icon children.
  • Removed every cx import from component files; components now call a single xVariants(...).

components/breadcrumb/variants.ts (new file)

  • crumbDropdownItemVariants — moves the inline className string out of BreadcrumbDropdownItem.
  • crumbDropdownPopupVariants — moves the className off Menu.Popup in BreadcrumbDropdown.
  • crumbMenuTriggerIconSlotVariants — named slot variant for the leading icon in BreadcrumbMenuTrigger (16 px via --node-size:1rem, [&>svg] sizing), replacing the anonymous <span className="flex size-4 ..."> wrapper.
  • crumbMenuTriggerIndicatorVariants — trailing chevron classes, moved out of JSX into cva.

components/breadcrumb/breadcrumb-dropdown.tsx

  • Wraps the <Ellipsis /> in <NodeSlot> so the icon is sized by --node-size (inherited from the trigger's cva) rather than a hardcoded className="size-3.5".

components/breadcrumb/breadcrumb.stories.tsx

  • Removes className="size-4" from icon passed to BreadcrumbMenuTrigger — the slot variant now handles sizing, so no className is needed on the icon element.

Notes

Needs design approval from @bhaveshraja before merge, per the team's review process.

@github-actions

Copy link
Copy Markdown

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

Move all className composition into cva in variants.ts (ui and components tiers),
remove every cx() call from component files, add new variants for BreadcrumbItem /
BreadcrumbSeparator / the ordered list, merge the two separate trigger cva calls
into one, move BreadcrumbPage's text-primary into the interactive:false variant,
move BreadcrumbDropdownItem's className into a cva, and replace the icon <span>
wrapper in BreadcrumbMenuTrigger with a named slot variant. Separator now sizes its
default chevron via --node-size / [&>svg] instead of a hardcoded className on the
child, and RTL mirroring is baked into the separator variant. Closes #121.
Split the multi-element ui parts into single-element parts and lift all
styling out of the components tier:

- Breadcrumb now renders only <nav>; the <ol> is a new BreadcrumbList part.
- New BreadcrumbTriggerIcon (leading icon slot) and BreadcrumbTriggerIndicator
  (trailing chevron) ui parts, each a single element with cva in variants.ts,
  replacing the inline icon/chevron baked into BreadcrumbMenuTrigger.
- BreadcrumbMenuTrigger now composes the ui trigger + icon + indicator parts
  with no styling.
- BreadcrumbDropdown reuses MenuContent and BreadcrumbDropdownItem reuses
  MenuLinkItem, so the components tier no longer owns popup/item chrome.
- Deleted components/breadcrumb/variants.ts; the components tier holds no cva,
  cx, or className literals.
- Stories compose the new parts and register them in subcomponents.
All seven variant functions in packages/propel/src/ui/breadcrumb/variants.ts
were prefixed `crumb*` instead of `breadcrumb*`. Renamed each to match its
consuming part exactly per rule 3a. The shared crumbVariants (used by both
BreadcrumbLink and BreadcrumbPage with different `interactive` values) is split
into breadcrumbLinkVariants and breadcrumbPageVariants; the interactive variant
is inlined as fixed Tailwind classes so each part has its own cva.
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.

Breadcrumb: what should always look the same, and what should be adjustable?

1 participant