Skip to content

feat(FE-2977): table primitives, Sheet, ToggleGroup, and the ring utilities - #92

Merged
dominicpedro merged 38 commits into
mainfrom
feature/FE-2977-table
Aug 19, 2026
Merged

feat(FE-2977): table primitives, Sheet, ToggleGroup, and the ring utilities#92
dominicpedro merged 38 commits into
mainfrom
feature/FE-2977-table

Conversation

@dominicpedro

Copy link
Copy Markdown
Contributor

Companion to the monorepo's FE-2977 (the flow-factory playground): https://git.upmind.io/upmind/upmind-monorepo/-/merge_requests/516

What's here

Table primitives The shadcn table set — Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableEmpty — installed against radix-vue, not smuggling a reka migration in.
Sheet The side panel the playground's Debug/Code/Scenario host renders into.
ToggleGroup The Table/Cards view switch, and the filter facets.
useInvalidRing / useHighlightRing The invalid-field treatment lifted to a utility so a consumer applies the ring rather than re-deriving a second error-outline technique. Composables that APPLY a treatment — never raw exported class strings.

Each component ships its own *.config.ts (CVA) and colocated tests, matching the library's existing shape.

Why it's a separate PR

packages/ui is a submodule of the monorepo. The pointer bump rides in MR !516; this is the two-MR flow that was agreed at plan review.

dominicpedro and others added 30 commits August 5, 2026 10:08
Wraps radix-vue's Stepper primitive family (Root/Item/Trigger/
Indicator/Title/Description/Separator) following the house
convention (<Component>.vue + .ce.vue + config.ts + types.ts +
index.ts), and adds a steps-array-driven Stepper composite.
Barrelled from src/index.ts.
Wraps radix-vue's Stepper primitive family (Root/Item/Trigger/
Indicator/Title/Description/Separator) following the house
convention (<Component>.vue + .ce.vue + config.ts + types.ts +
index.ts), and adds a steps-array-driven Stepper composite.
Barrelled from src/index.ts.
Wraps radix-vue's ContextMenu primitive family, mirroring the
existing dropdown-menu composite (design tokens, Portal + `to`
target, items-array-driven ContextMenu.ce.vue). Backs the
action-slot `context-menu` placement (wired in labs-nuxt
separately). Barrelled from src/index.ts.
Wraps radix-vue's ContextMenu primitive family, mirroring the
existing dropdown-menu composite (design tokens, Portal + `to`
target, items-array-driven ContextMenu.ce.vue). Backs the
action-slot `context-menu` placement (wired in labs-nuxt
separately). Barrelled from src/index.ts.
…u [FE-2977]

Task 18 (AC4): prove both new primitives mount and resolve from the
package barrel (src/index.ts), not just their local module. Imports
are deferred behind a canvas-getContext stub (icon-animated/lottie-web
probes canvas support at barrel-import time; unrelated to this pair)
so the real barrel loads under vitest+jsdom.

context-menu: barrel resolution + a real right-click open/reveal
round-trip on the raw radix-vue primitives — green.

stepper: barrel resolution passes, but mounting the data-driven
Stepper convenience component with real `steps` data is red —
`StepperTitle`/`StepperDescription` throw "Injection
Symbol(StepperItemContext) not found" (not nested under StepperItem),
and StepperSeparator warns "missing template or render function".
Genuine capability gaps, not test artifacts.
…u [FE-2977]

Task 18 (AC4): prove both new primitives mount and resolve from the
package barrel (src/index.ts), not just their local module. Imports
are deferred behind a canvas-getContext stub (icon-animated/lottie-web
probes canvas support at barrel-import time; unrelated to this pair)
so the real barrel loads under vitest+jsdom.

context-menu: barrel resolution + a real right-click open/reveal
round-trip on the raw radix-vue primitives — green.

stepper: barrel resolution passes, but mounting the data-driven
Stepper convenience component with real `steps` data is red —
`StepperTitle`/`StepperDescription` throw "Injection
Symbol(StepperItemContext) not found" (not nested under StepperItem),
and StepperSeparator warns "missing template or render function".
Genuine capability gaps, not test artifacts.
radix-vue's StepperSeparator injects StepperItemContext to derive its
data-state; as a sibling of StepperItem it has no providing ancestor
and throws on mount for any multi-step render.
radix-vue's StepperSeparator injects StepperItemContext to derive its
data-state; as a sibling of StepperItem it has no providing ancestor
and throws on mount for any multi-step render.
…g [FE-2977]

Replace the wrapper.exists()-only assertion on ContextMenu with real
behaviour proofs (per-item handler on select, hidden-item exclusion,
items-prop rendering) and add the stepper analog (per-item disabled
forwarding) so the wrapper's data-driven mapping is actually verified,
not just its mount.
…g [FE-2977]

Replace the wrapper.exists()-only assertion on ContextMenu with real
behaviour proofs (per-item handler on select, hidden-item exclusion,
items-prop rendering) and add the stepper analog (per-item disabled
forwarding) so the wrapper's data-driven mapping is actually verified,
not just its mount.
Both are verified radix-vue installs resolving from the package
barrel; the README's component index was missing them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both are verified radix-vue installs resolving from the package
barrel; the README's component index was missing them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Operator direction (overrides sibling convention): Vue defineModel not
useVModel; the repo Icon component (check/chevron-right/circle) not
lucide-vue-next.
Operator direction (overrides sibling convention): Vue defineModel not
useVModel; the repo Icon component (check/chevron-right/circle) not
lucide-vue-next.
The shadcn-vue@radix installer refreshed the stepper and context-menu
primitives with current radix-vue markup but reset them to vanilla
shadcn color classes and dropped our composite/barrel exports. Layer
Upmind design tokens onto the new primitives without touching their
shipped structure, and restore the .ce.vue composite + StepperRoot/
ContextMenuRoot re-exports the install clobbered.
The shadcn-vue@radix installer refreshed the stepper and context-menu
primitives with current radix-vue markup but reset them to vanilla
shadcn color classes and dropped our composite/barrel exports. Layer
Upmind design tokens onto the new primitives without touching their
shipped structure, and restore the .ce.vue composite + StepperRoot/
ContextMenuRoot re-exports the install clobbered.
…orientations)

Composite renders content as a trigger sibling and the separator absolutely
positioned per shadcn's stepper example; config carries shadcn's layout with
Upmind tokens layered on. Fixes the vertical connector (now between nodes).
…orientations)

Composite renders content as a trigger sibling and the separator absolutely
positioned per shadcn's stepper example; config carries shadcn's layout with
Upmind tokens layered on. Fixes the vertical connector (now between nodes).
Rebuild the connector as two flex-1 half-lines either side of the pill so
it auto-centres and meets its neighbour with no magic-number offsets, in
both orientations. Move all styling into stepper.config.ts (resolved via
useStyles) and reduce the radix primitives to pure pass-throughs. Unify
pill-to-content spacing on a single flex gap; keep completed/active/
inactive/disabled state classes on the pill and connector.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebuild the connector as two flex-1 half-lines either side of the pill so
it auto-centres and meets its neighbour with no magic-number offsets, in
both orientations. Move all styling into stepper.config.ts (resolved via
useStyles) and reduce the radix primitives to pure pass-throughs. Unify
pill-to-content spacing on a single flex gap; keep completed/active/
inactive/disabled state classes on the pill and connector.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two are the same component with a different trigger, so the visual
primitives (Content, Item, Label, Sub*, Checkbox/Radio) are mirrored from
dropdown-menu — same surface, persistent ring, radius, spacing and item
chrome — while each keeps its own cursor-positioned radix ContextMenu*
component and right-click trigger. context-menu.config gains dropdown's
width-variant system (default md); the .ce stays config-only. Dropped the
dropdown-only sideOffset default (context has no trigger to offset from).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two are the same component with a different trigger, so the visual
primitives (Content, Item, Label, Sub*, Checkbox/Radio) are mirrored from
dropdown-menu — same surface, persistent ring, radius, spacing and item
chrome — while each keeps its own cursor-positioned radix ContextMenu*
component and right-click trigger. context-menu.config gains dropdown's
width-variant system (default md); the .ce stays config-only. Dropped the
dropdown-only sideOffset default (context has no trigger to offset from).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pnpm dlx shadcn-vue@0.11.4 add table — the last radix-vue line (E-1;
radix-vue@1.9.17, no reka migration). Verbatim install; only colour/font
classes swapped to Upmind tokens (text-muted-foreground→text-muted,
text-foreground→text-display, bg-muted→bg-accent-neutral/20, bare
border-*→border-control-default) and the CLI's unresolved `src/utils`
import corrected to the sibling-relative `../../utils`. @tanstack/vue-table
stays OUT of packages/ui. Barrel exports ./ui/table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pnpm dlx shadcn-vue@0.11.4 add table — the last radix-vue line (E-1;
radix-vue@1.9.17, no reka migration). Verbatim install; only colour/font
classes swapped to Upmind tokens (text-muted-foreground→text-muted,
text-foreground→text-display, bg-muted→bg-accent-neutral/20, bare
border-*→border-control-default) and the CLI's unresolved `src/utils`
import corrected to the sibling-relative `../../utils`. @tanstack/vue-table
stays OUT of packages/ui. Barrel exports ./ui/table.

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

- Introduced Sheet component with its subcomponents (SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger) and configuration.
- Added ToggleGroup component with ToggleGroupItem and associated styles.
- Implemented tests for ButtonGroup and ToggleGroup to ensure correct functionality.
- Updated existing components to support new styles and configurations.
- Enhanced form components to allow for additional class bindings and improved accessibility features.
… tests

- Introduced Sheet component with its subcomponents (SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger) and configuration.
- Added ToggleGroup component with ToggleGroupItem and associated styles.
- Implemented tests for ButtonGroup and ToggleGroup to ensure correct functionality.
- Updated existing components to support new styles and configurations.
- Enhanced form components to allow for additional class bindings and improved accessibility features.
@dominicpedro
dominicpedro merged commit 32544b2 into main Aug 19, 2026
@dominicpedro
dominicpedro deleted the feature/FE-2977-table branch August 19, 2026 08:44
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.

1 participant