From d697c5350320aff1e9497543315dba4b022f5140 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Tue, 20 Oct 2026 16:57:11 +0200 Subject: [PATCH] refactor(segmented-control): ship as a render-prop component - Add SegmentedControl and SegmentedControlItem in ui/segmented-control.tsx; the rendered element (Radio Group, nav and links, Toggle Group) provides the behavior - Render the sliding indicator inside SegmentedControl and share size via context like TabsList - Remove lib/segmented-control.ts and lib/segmented-control-indicator.tsx; @coss/segmented-control is now a registry:ui item and @coss/segmented-control-indicator is removed - Tabs imports the shared sizes, layout and indicator surface from the component - Migrate the radio group and navigation particles, docs, skill references, and add a changelog entry with an agent migration prompt Co-authored-by: Cursor --- apps/ui/content/docs/(root)/changelog.mdx | 86 +++++++ .../docs/components/segmented-control.mdx | 159 +++++++----- apps/ui/content/docs/components/tabs.mdx | 18 +- apps/ui/public/r/p-navigation-1.json | 5 +- apps/ui/public/r/p-navigation-2.json | 5 +- apps/ui/public/r/p-navigation-3.json | 5 +- apps/ui/public/r/p-radio-group-7.json | 5 +- apps/ui/public/r/p-radio-group-8.json | 5 +- apps/ui/public/r/p-radio-group-9.json | 5 +- apps/ui/public/r/registry.json | 58 ++--- .../public/r/segmented-control-indicator.json | 16 -- apps/ui/public/r/segmented-control.json | 10 +- apps/ui/public/r/tabs.json | 2 +- apps/ui/registry.json | 58 ++--- apps/ui/registry/__index__.tsx | 66 ++--- .../lib/segmented-control-indicator.tsx | 155 ------------ .../registry/default/lib/segmented-control.ts | 47 ---- .../default/particles/p-navigation-1.tsx | 42 ++-- .../default/particles/p-navigation-2.tsx | 45 ++-- .../default/particles/p-navigation-3.tsx | 45 ++-- .../default/particles/p-radio-group-7.tsx | 38 ++- .../default/particles/p-radio-group-8.tsx | 36 ++- .../default/particles/p-radio-group-9.tsx | 38 ++- .../registry/default/ui/segmented-control.tsx | 234 ++++++++++++++++++ apps/ui/registry/default/ui/tabs.tsx | 4 +- apps/ui/registry/registry-lib.ts | 22 -- apps/ui/registry/registry-particles.ts | 33 +-- apps/ui/registry/registry-ui.ts | 11 + apps/ui/skills/coss/SKILL.md | 3 +- .../coss/references/component-registry.md | 4 +- .../coss/references/primitives/radio-group.md | 2 +- .../primitives/segmented-control.md | 111 +++++++++ .../skills/coss/references/primitives/tabs.md | 6 +- .../references/primitives/toggle-group.md | 2 +- .../coss/references/segmented-control.md | 74 ------ .../ui/src/components/segmented-control.tsx | 234 ++++++++++++++++++ packages/ui/src/components/tabs.tsx | 2 +- .../src/lib/segmented-control-indicator.tsx | 155 ------------ packages/ui/src/lib/segmented-control.ts | 47 ---- 39 files changed, 991 insertions(+), 902 deletions(-) delete mode 100644 apps/ui/public/r/segmented-control-indicator.json delete mode 100644 apps/ui/registry/default/lib/segmented-control-indicator.tsx delete mode 100644 apps/ui/registry/default/lib/segmented-control.ts create mode 100644 apps/ui/registry/default/ui/segmented-control.tsx create mode 100644 apps/ui/skills/coss/references/primitives/segmented-control.md delete mode 100644 apps/ui/skills/coss/references/segmented-control.md create mode 100644 packages/ui/src/components/segmented-control.tsx delete mode 100644 packages/ui/src/lib/segmented-control-indicator.tsx delete mode 100644 packages/ui/src/lib/segmented-control.ts diff --git a/apps/ui/content/docs/(root)/changelog.mdx b/apps/ui/content/docs/(root)/changelog.mdx index 24d405e65..14cd575ba 100644 --- a/apps/ui/content/docs/(root)/changelog.mdx +++ b/apps/ui/content/docs/(root)/changelog.mdx @@ -3,6 +3,92 @@ title: Changelog description: Breaking changes, migration guides, and notable updates. --- +## October 20, 2026 + +### Segmented Control component + +**`@coss/segmented-control`** is now a component at **`components/ui/segmented-control.tsx`** instead of a styling library at **`lib/segmented-control.ts`**. It exports **`SegmentedControl`** and **`SegmentedControlItem`**. The element you pass to **`render`** still decides the behavior — a Radio Group, links, or a Toggle Group — so the semantics stay those of the primitive you choose. + +```tsx +} +> + }> + Monthly + + }> + Yearly + + +``` + +The sliding indicator is built in. **`SegmentedControl`** renders it after its children, so there is nothing to add or order by hand, and before hydration the active item paints its own static pill. **`size`** is set once on **`SegmentedControl`** and inherited by its items; an item can still override it. One item recipe now covers **`data-checked`**, **`aria-current="page"`**, and **`data-pressed`**, so there is no **`state`** option. + +These exports were removed: **`segmentedControlRootClassName`**, **`segmentedControlItemVariants`**, **`segmentedControlIndicatorClassName`**, and **`SegmentedControlIndicator`**. The **`@coss/segmented-control-indicator`** registry item no longer exists. **`SegmentedControlSize`**, **`segmentedControlItemSizeClassNames`**, **`segmentedControlItemLayoutClassName`**, and **`segmentedControlIndicatorSurfaceClassName`** are still exported, from the component file. Tabs imports them from there, and **`@coss/tabs`** declares the component as a registry dependency. + +**Migration:** + +Install the component, then update Tabs so it no longer imports from the library: + +```bash +npx shadcn@latest add @coss/segmented-control @coss/tabs +``` + +If you maintain a local Tabs, change its import instead of overwriting it: + +```diff +- } from "@/lib/segmented-control" ++ } from "@/components/ui/segmented-control" +``` + +Replace class-based compositions. Move the root class and the indicator into **`SegmentedControl`**, and each item recipe into **`SegmentedControlItem`**, keeping behavior props on the rendered element: + +```diff +- +- ++ } ++ > ++ }> + Monthly +- +- +- ++ ++ +``` + +Navigation follows the same shape, with the **`