Skip to content

feat: Nimbus 4.0 collection primitives + DataTable enhancements#1606

Draft
ByronDWall wants to merge 53 commits into
mainfrom
nimbus-4.0
Draft

feat: Nimbus 4.0 collection primitives + DataTable enhancements#1606
ByronDWall wants to merge 53 commits into
mainfrom
nimbus-4.0

Conversation

@ByronDWall

@ByronDWall ByronDWall commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Nimbus 4.0 feature branch — collection primitives, custom theming, SSR/RSC support, DataTable enhancements, public Popover, FilterMenu pattern, trailingElement slots, and ToggleButtonGroup variants.

Collection primitives

  • Tree — full component wrapping React Aria Tree with DnD, checkboxes, nested indent, and drag-handle support
  • ListBox — standalone ListBox with sections and items
  • GridList — standalone GridList with DnD reordering
  • Autocomplete — wrapping SearchInput + ListBox with async filtering
  • Virtualizer — standalone Virtualizer for large lists
  • ComboBox v4 + Select v4 composition stories demonstrating cross-primitive patterns
  • DraggableList deprecation path

Popover compound component

  • Promoted internal Popover to a public compound API: Popover.Root, Popover.Trigger, Popover.Content
  • Uses React Aria's DialogTrigger for open state management and positioning
  • Key behavior: popover stays open on internal interaction (unlike Menu)
  • Supports controlled/uncontrolled mode, asChild trigger, Escape/outside-click dismissal
  • Internal component renamed to PopoverBase; internal consumers (ComboBox, LocalizedField) updated

FilterMenu pattern

  • New pattern component built on Popover for structured filter forms
  • Compound API: FilterMenu.Root, FilterMenu.Trigger, FilterMenu.Content, FilterMenu.Section, FilterMenu.Option, FilterMenu.ClearAction
  • Collapsible sections via CollapsibleMotion with direction prop for horizontal/vertical layout
  • FilterMenu.Option with isSelected/data-selected state and hover styling
  • Full documentation: overview .mdx, implementation guide .dev.mdx with live examples, consumer .docs.spec.tsx tests

DataTable enhancements

  • Compound APIDataTable.Root, DataTable.Column, etc. for declarative table composition
  • allowsPinning (default true): set to false to hide the pin column
  • allowsExpandColumn (default true): set to false to hide the expand chevron column
  • renderDetails(row): full-width detail panel below a clicked row
  • Virtualized DataTable composition story
  • Sticky column scroll shadows: gradient shadows on inside edges of sticky columns when table overflows horizontally, driven by scroll listener + ResizeObserver with CSS ::after pseudo-elements

trailingElement slot for Combobox, Select, SearchInput

  • Added trailingElement prop and recipe slot to Combobox, Select, and SearchInput
  • Follows the established TextInput/DateInput/TimeInput pattern
  • Renders after built-in trailing controls (clear button, toggle/chevron) at the far trailing edge
  • Includes new slot components, type definitions with JSDoc, and Storybook stories with play-function assertions

ToggleButtonGroup visual variants

  • Added variant prop to ToggleButtonGroup with five visual styles:
    • outline (default) — current behavior preserved: outline border unselected, solid fill selected
    • ghost — no border/background, tinted fill on selection, gapped layout
    • solid — always filled, stronger shade on selection, joined layout
    • subtle — light tint unselected, stronger tint selected, gapped layout
    • segmented — iOS/Material-style segmented control with background track and elevated selected pill
  • Uses CSS custom properties for clean state separation
  • Storybook story with play-function assertions for all variants

Custom theming

  • Color palette generation from a single base color (light + dark modes)
  • createNimbusTheme() API with generated, manual, and preset palette configs
  • Contrast validation and accessible color scale generation
  • Theme generator moved into @commercetools/nimbus/theme-generator subpath
  • Storybook decorator support for per-story custom themes via nimbusTheme parameter
  • Consumer-facing theming guide with interactive examples

SSR / RSC support

  • "use client" directives on all component entry points
  • SSR smoke test suite (ssr.ssr.spec.tsx)
  • CI check for missing directives (check-use-client.mjs)
  • Next.js SSR test app (apps/ssr-test)

Other

  • Badge: add missing sm size variant
  • Checkbox: drop reserved label spacing when label-less; align tree indent
  • Security: override ws to >=8.21.0 (CVE-2026-48779, CVE-2026-45736)

Test plan

  • All existing component stories still pass
  • Tree stories: expand/collapse, DnD reorder, checkbox selection, keyboard nav
  • ListBox / GridList / Autocomplete / Virtualizer stories render and interact correctly
  • DataTable: allowsPinning={false} hides pin column, allowsExpandColumn={false} hides expand column, renderDetails renders inline detail panel, sticky column shadows appear on horizontal scroll
  • Popover: opens on trigger click, stays open on internal interaction, closes on Escape/outside click, controlled mode works
  • FilterMenu: sections expand/collapse, options show selected state, ClearAction resets, inputs focusable inside popover, horizontal direction layout works
  • Combobox/Select/SearchInput: trailingElement renders after built-in controls, absent when not provided, sizes correctly per variant
  • ToggleButtonGroup: all five variants render correctly, selection toggles, segmented track and elevation work
  • Custom theming stories apply brand palettes correctly in light and dark modes
  • SSR test app renders without hydration errors
  • Lint and typecheck pass
  • Orca security scan passes (ws vulnerability resolved)

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nimbus-documentation Ready Ready Preview, Comment Jul 17, 2026 7:14am
nimbus-storybook Ready Ready Preview, Comment Jul 17, 2026 7:14am

Request Review

@changeset-bot

changeset-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a7fdff6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@commercetools/nimbus Minor
@commercetools/nimbus-tokens Minor
@commercetools/nimbus-icons Minor
@commercetools/nimbus-design-token-ts-plugin Minor
@commercetools/nimbus-mcp Minor
@commercetools/nimbus-docs-build Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ByronDWall

Copy link
Copy Markdown
Contributor Author

/deploy-canary

@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Report

Last updated: 2026-07-17 07:13:48 UTC

Package Format Current Baseline Delta Status
@commercetools/nimbus dist 20903.8 KB 19577.5 KB +6.8% ⚠️ approved
@commercetools/nimbus-icons dist 4787.6 KB 4787.6 KB +0.0% ✅ ok
@commercetools/nimbus-tokens dist 408.2 KB 408.2 KB +0.0% ✅ ok

Baseline source: comment-chain

@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

1 similar comment
@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary published

Version: 0.0.0-canary-nimbus-4-0-20260612212251
Commit: c5d531c

pnpm add @commercetools/nimbus@0.0.0-canary-nimbus-4-0-20260612212251
pnpm add @commercetools/nimbus-tokens@0.0.0-canary-nimbus-4-0-20260612212251
pnpm add @commercetools/nimbus-icons@0.0.0-canary-nimbus-4-0-20260612212251
pnpm add @commercetools/nimbus-theme-generator@0.0.0-canary-nimbus-4-0-20260612212251

ByronDWall and others added 10 commits July 16, 2026 10:05
…chitecture

OpenSpec proposal for introducing standalone ListBox, GridList, Autocomplete,
and Virtualizer primitives. Rewrites ComboBox and Select as thin compositional
layers on Autocomplete. Unifies D&D as opt-in dragAndDropHooks across all
collection components. Adds virtualization to every relevant component.
Deprecates DraggableList. Includes MC categories app remake as proof-of-concept.
Compound component for hierarchical data (file trees, nested navigation) with
Tree.Root / Tree.Item / Tree.ItemContent / Tree.Indicator. Provides keyboard
navigation, expand/collapse, single/multiple selection (auto checkboxes),
type-ahead, level-based indentation, sm/md sizes, and opt-in drag-and-drop via
dragAndDropHooks. Built on React Aria's accessible treegrid pattern; styled with
a nimbusTree slot recipe and design tokens.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… DnD

- Base story is now actionable (onAction) so leaf rows show hover/press
  feedback; add a [data-pressed] state to the recipe (React Aria only enables
  row hover/press when the tree is selectable or actionable).
- Rebalance itemContent spacing: larger leading inset, tighter gap between the
  checkbox and chevron.
- Style the drag-and-drop drop indicator with Nimbus tokens (was browser
  default) and align it with the row content/level.
- Sizes story now renders the full feature set (selection checkboxes + drag
  handles) so every element is verified per size; use a styled IconButton drag
  handle. Document keyboard / leftward-drag path for moving items to the root.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Scope the chevron visibility/rotation rules to the tree's own indicator slot
  class instead of [data-slot="indicator"], which also matched the selection
  Checkbox's internal indicator. This was rotating the checkmark on expanded
  selected rows and hiding the checkbox on leaf rows.
- Set the indent step to the leading control column + gap so a child's checkbox
  aligns directly under its parent's chevron.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e indent

- Checkbox: remove the root's fixed min-width so a label-less checkbox sizes to
  its indicator instead of reserving 8px of trailing space for an absent label.
  Labeled checkboxes are unchanged; the 24px hit area is preserved by the
  indicator's `_after` pseudo. This also makes the Tree's drag icon read as
  centered between the checkbox and chevron.
- Tree: reduce the indent step to match the now-tight (16px) selection checkbox
  so a child's checkbox still aligns exactly under its parent's chevron.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Optically center an optional drag handle (`<Button slot="drag">`) between the
  checkbox and chevron via a per-size `--tree-drag-offset` (sm: spacing.100 /
  4px, md: spacing.150 / 6px), applied as a visual-only translateX so it does
  not reflow the row or disturb the checkbox-to-chevron alignment.
- Add a "ReorderWithoutSelection" story: drag-and-drop with selectionMode="none"
  (no checkboxes) — the navigation-menu-builder / content-outline use case where
  arranging hierarchy is the only interaction.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The root no longer forces `overflow: auto`, which created a scroll container
that clipped the drop-target and focus outlines at the rows' edges. Consumers
that want a scrollable tree can set `maxHeight` + `overflow="auto"` on
`Tree.Root` themselves.

FEC-985

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, and docs

- Add Rollup plugin to prepend "use client" to all entry-point chunks
- Add getServerSnapshot to useSyncExternalStore in ToastOutlet
- Add SSR smoke test suite (85 tests) covering all components and patterns
- Add vitest SSR project config (environment: node, no JSDOM)
- Add post-build check:use-client verification script
- Add Next.js App Router test app (apps/ssr-test) for end-to-end validation
- Add SSR documentation page under Getting Started
- Update testing strategy and component guidelines to require SSR tests
…I check

Fix incorrect component API usage across SSR tests (ModalPage.Body →
Content, DataTable compound → simple, Avatar/Alert/Pagination/MoneyInput/
ScopedSearchInput/SplitButton/FormDialog/ConfirmationDialog prop errors).
Add SSR smoke tests for RichTextInput and MoneyInputField. Add 6 missing
components to the Next.js SSR test app. Wire check:use-client into CI.
Update test category count to 4 in docs.
Promote the internal Popover component to a public compound API with
Popover.Root, Popover.Trigger, and Popover.Content. Uses React Aria's
DialogTrigger for open state management and positioning, and wraps the
existing internal PopoverBase + Dialog for focus management.

The internal component is renamed to PopoverBase to avoid name collision
with the compound namespace. Internal consumers (ComboBox, LocalizedField)
are updated to use PopoverBase.
A compound component for structured filter forms that looks like a Menu
but contains interactive inputs. Built on the new Popover compound
component.

Components: FilterMenu.Root, FilterMenu.Trigger, FilterMenu.Content,
FilterMenu.Section (collapsible via CollapsibleMotion), FilterMenu.Option
(selectable row with selected state), FilterMenu.ClearAction (critical
color clear button).

Exported from patterns/overlays barrel and available via the nimbus barrel.
When the table overflows horizontally, gradient shadows appear on the
inside edges of sticky columns to indicate scrollable content behind
them. A scroll listener + ResizeObserver on the root element sets
data-scroll-left/data-scroll-right attributes, and CSS ::after
pseudo-elements render the 8px gradient shadows conditionally.

Applies to left-sticky columns (selection, drag, expand) and
right-sticky columns (pin-row).
Supports "row" or "column" (default) layout for section content,
allowing filter inputs to be arranged horizontally (e.g. min/max
price range) or vertically (e.g. status options).

Row direction also enables flex-wrap for graceful overflow handling.
- filter-menu.mdx: Overview page with when-to-use guidance and related
  component links
- filter-menu.dev.mdx: Implementation guide with live examples covering
  basic usage, collapsible sections, horizontal layout, mixed filter
  types, controlled mode, and full API reference table
- filter-menu.docs.spec.tsx: Consumer implementation tests for basic
  rendering, option selection, clear action, and escape dismissal
Add a trailingElement prop and recipe slot to Combobox, Select, and
SearchInput, following the pattern established in TextInput/DateInput.
The trailing element renders after built-in controls (clear, toggle)
at the far trailing edge of the input.
Add outline (default), ghost, solid, subtle, and segmented variants
to ToggleButtonGroup. Previously the visual style was hardcoded to
outline/solid toggle. Each variant defines unselected and selected
states using CSS custom properties.
@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary published

Version: 0.0.0-canary-nimbus-4-0-20260717052632
Commit: 21e5ea8

pnpm add @commercetools/nimbus@0.0.0-canary-nimbus-4-0-20260717052632
pnpm add @commercetools/nimbus-tokens@0.0.0-canary-nimbus-4-0-20260717052632
pnpm add @commercetools/nimbus-icons@0.0.0-canary-nimbus-4-0-20260717052632
pnpm add @commercetools/nimbus-theme-generator@0.0.0-canary-nimbus-4-0-20260717052632

Update tsup build target from node20 to node24. Add openspec change
proposals for trailing-element-slot and toggle-button-group-variants.
…bundle tests

Importing from the local source file caused a dual react-aria-components
instance when tests ran against the built dist, preventing DialogTrigger
context from reaching the Button child.
@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary published

Version: 0.0.0-canary-nimbus-4-0-20260717062323
Commit: 11ddf17

pnpm add @commercetools/nimbus@0.0.0-canary-nimbus-4-0-20260717062323
pnpm add @commercetools/nimbus-tokens@0.0.0-canary-nimbus-4-0-20260717062323
pnpm add @commercetools/nimbus-icons@0.0.0-canary-nimbus-4-0-20260717062323
pnpm add @commercetools/nimbus-theme-generator@0.0.0-canary-nimbus-4-0-20260717062323

@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary published

Version: 0.0.0-canary-nimbus-4-0-20260717065321
Commit: 11ddf17

pnpm add @commercetools/nimbus@0.0.0-canary-nimbus-4-0-20260717065321
pnpm add @commercetools/nimbus-tokens@0.0.0-canary-nimbus-4-0-20260717065321
pnpm add @commercetools/nimbus-icons@0.0.0-canary-nimbus-4-0-20260717065321
pnpm add @commercetools/nimbus-theme-generator@0.0.0-canary-nimbus-4-0-20260717065321

@ByronDWall

Copy link
Copy Markdown
Contributor Author

[/deploy-canary]

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary published

Version: 0.0.0-canary-nimbus-4-0-20260717073521
Commit: a7fdff6

pnpm add @commercetools/nimbus@0.0.0-canary-nimbus-4-0-20260717073521
pnpm add @commercetools/nimbus-tokens@0.0.0-canary-nimbus-4-0-20260717073521
pnpm add @commercetools/nimbus-icons@0.0.0-canary-nimbus-4-0-20260717073521
pnpm add @commercetools/nimbus-theme-generator@0.0.0-canary-nimbus-4-0-20260717073521

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bundle-size-approved This label is to be added when the bundle-size check fails but the change is expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants