From 3bfda5d3f0df00d62bb650858175fa7f9304c4d8 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 19:52:07 +0200 Subject: [PATCH 01/17] feat(ui): add segmented control patterns --- apps/ui/content/docs/components/meta.json | 1 + .../content/docs/components/radio-group.mdx | 2 + .../docs/components/segmented-control.mdx | 131 ++++++++++ apps/ui/content/docs/components/tabs.mdx | 21 +- .../content/docs/components/toggle-group.mdx | 2 + apps/ui/public/r/p-navigation-1.json | 20 ++ apps/ui/public/r/p-navigation-2.json | 20 ++ apps/ui/public/r/p-navigation-3.json | 20 ++ apps/ui/public/r/p-radio-group-7.json | 21 ++ apps/ui/public/r/p-radio-group-8.json | 21 ++ apps/ui/public/r/p-radio-group-9.json | 21 ++ apps/ui/public/r/p-tabs-14.json | 19 ++ apps/ui/public/r/p-tabs-15.json | 19 ++ apps/ui/public/r/p-toggle-group-10.json | 23 ++ apps/ui/public/r/p-toggle-group-11.json | 23 ++ apps/ui/public/r/p-toggle-group-12.json | 23 ++ apps/ui/public/r/registry.json | 224 ++++++++++++++++++ apps/ui/public/r/segmented-control.json | 15 ++ apps/ui/public/r/tabs.json | 5 +- apps/ui/registry.json | 224 ++++++++++++++++++ apps/ui/registry/__index__.tsx | 218 ++++++++++++++++- .../registry/default/lib/segmented-control.ts | 35 +++ .../default/particles/p-navigation-1.tsx | 24 ++ .../default/particles/p-navigation-2.tsx | 27 +++ .../default/particles/p-navigation-3.tsx | 27 +++ .../default/particles/p-radio-group-7.tsx | 33 +++ .../default/particles/p-radio-group-8.tsx | 32 +++ .../default/particles/p-radio-group-9.tsx | 33 +++ .../registry/default/particles/p-tabs-14.tsx | 28 +++ .../registry/default/particles/p-tabs-15.tsx | 28 +++ .../default/particles/p-toggle-group-10.tsx | 34 +++ .../default/particles/p-toggle-group-11.tsx | 30 +++ .../default/particles/p-toggle-group-12.tsx | 34 +++ apps/ui/registry/default/ui/tabs.tsx | 39 ++- apps/ui/registry/registry-categories.ts | 1 + apps/ui/registry/registry-lib.ts | 11 + apps/ui/registry/registry-particles.ts | 94 ++++++++ apps/ui/registry/registry-ui.ts | 1 + packages/ui/src/components/tabs.tsx | 39 ++- packages/ui/src/lib/segmented-control.ts | 35 +++ 40 files changed, 1640 insertions(+), 18 deletions(-) create mode 100644 apps/ui/content/docs/components/segmented-control.mdx create mode 100644 apps/ui/public/r/p-navigation-1.json create mode 100644 apps/ui/public/r/p-navigation-2.json create mode 100644 apps/ui/public/r/p-navigation-3.json create mode 100644 apps/ui/public/r/p-radio-group-7.json create mode 100644 apps/ui/public/r/p-radio-group-8.json create mode 100644 apps/ui/public/r/p-radio-group-9.json create mode 100644 apps/ui/public/r/p-tabs-14.json create mode 100644 apps/ui/public/r/p-tabs-15.json create mode 100644 apps/ui/public/r/p-toggle-group-10.json create mode 100644 apps/ui/public/r/p-toggle-group-11.json create mode 100644 apps/ui/public/r/p-toggle-group-12.json create mode 100644 apps/ui/public/r/segmented-control.json create mode 100644 apps/ui/registry/default/lib/segmented-control.ts create mode 100644 apps/ui/registry/default/particles/p-navigation-1.tsx create mode 100644 apps/ui/registry/default/particles/p-navigation-2.tsx create mode 100644 apps/ui/registry/default/particles/p-navigation-3.tsx create mode 100644 apps/ui/registry/default/particles/p-radio-group-7.tsx create mode 100644 apps/ui/registry/default/particles/p-radio-group-8.tsx create mode 100644 apps/ui/registry/default/particles/p-radio-group-9.tsx create mode 100644 apps/ui/registry/default/particles/p-tabs-14.tsx create mode 100644 apps/ui/registry/default/particles/p-tabs-15.tsx create mode 100644 apps/ui/registry/default/particles/p-toggle-group-10.tsx create mode 100644 apps/ui/registry/default/particles/p-toggle-group-11.tsx create mode 100644 apps/ui/registry/default/particles/p-toggle-group-12.tsx create mode 100644 packages/ui/src/lib/segmented-control.ts diff --git a/apps/ui/content/docs/components/meta.json b/apps/ui/content/docs/components/meta.json index 92f91f4f3..63fd3eae6 100644 --- a/apps/ui/content/docs/components/meta.json +++ b/apps/ui/content/docs/components/meta.json @@ -40,6 +40,7 @@ "radio-group", "scroll-area", "select", + "segmented-control", "separator", "sheet", "skeleton", diff --git a/apps/ui/content/docs/components/radio-group.mdx b/apps/ui/content/docs/components/radio-group.mdx index 5765ed8d9..2954521d6 100644 --- a/apps/ui/content/docs/components/radio-group.mdx +++ b/apps/ui/content/docs/components/radio-group.mdx @@ -81,6 +81,8 @@ Individual radio button. Styled wrapper for `Radio.Root` from Base UI with built For accessible labelling and validation, prefer using the `Field` component to wrap radio buttons. See the related example: [Radio Group field](/ui/docs/components/field#radio-group-field). +For tabs-style mutually exclusive choices, see the [Segmented Control](/ui/docs/components/segmented-control) pattern. + ### Disabled diff --git a/apps/ui/content/docs/components/segmented-control.mdx b/apps/ui/content/docs/components/segmented-control.mdx new file mode 100644 index 000000000..cb9eb29fb --- /dev/null +++ b/apps/ui/content/docs/components/segmented-control.mdx @@ -0,0 +1,131 @@ +--- +title: Segmented Control +description: A visual pattern for presenting related choices, navigation destinations, filters, or content views. +--- + + + +## About + +A segmented control is a visual pattern, not a standalone behavior. COSS uses the same presentation across several components while preserving the semantics, keyboard interactions, and state model of each underlying primitive. + +## Choose the right primitive + +| Intent | Use | Why | +| ------ | --- | --- | +| Choose one value in a form | [Radio Group](/ui/docs/components/radio-group) | Represents a mutually exclusive value and participates in form state. | +| Navigate to another URL or route | Navigation links | Preserves link behavior, browser history, and `aria-current`. | +| Apply an exclusive filter or mode | [Toggle Group](/ui/docs/components/toggle-group) | Represents the pressed state of an action that may be cleared. | +| Switch between related panels | [Tabs](/ui/docs/components/tabs) | Connects each tab to an associated content panel. | + +Choose the primitive from the interaction first, then apply the segmented-control styling. Visual similarity alone is not a reason to use Tabs or Toggle Group. + +## Installation + +Segmented controls are provided as particles. Install the implementation and size that match your interaction: + +| Implementation | Small | Default | Large | +| -------------- | ----- | ------- | ----- | +| Radio Group | `@coss/p-radio-group-7` | `@coss/p-radio-group-8` | `@coss/p-radio-group-9` | +| Navigation | `@coss/p-navigation-2` | `@coss/p-navigation-1` | `@coss/p-navigation-3` | +| Toggle Group | `@coss/p-toggle-group-10` | `@coss/p-toggle-group-11` | `@coss/p-toggle-group-12` | + +For example, install the default Radio Group version with: + +```bash +npx shadcn@latest add @coss/p-radio-group-8 +``` + +The CLI installs the shared `segmented-control` styling library and the required primitive automatically. + +## Shared styling + +For a custom composition, install the styling library directly: + +```bash +npx shadcn@latest add @coss/segmented-control +``` + +The library exports a root class and an item recipe: + +```tsx +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/lib/segmented-control" +``` + +```tsx +const itemClassName = segmentedControlItemVariants({ + size: "default", + state: "checked", +}) +``` + +| Option | Values | Description | +| ------ | ------ | ----------- | +| `size` | `"sm" \| "default" \| "lg"` | Controls item height and horizontal padding. | +| `state` | `"checked" \| "current" \| "pressed"` | Selects the state attribute used by the underlying element. | + +Use `checked` with Radio Group, `current` with navigation links, and `pressed` with Toggle Group. Tabs retain their own animated indicator and do not use the shared state recipe. + +Each size uses the horizontal padding of the corresponding Button size. The outer segmented surface is slightly taller than that Button to optically balance its inset selected item when the controls appear next to each other. + + + +## Radio options + +Use Radio Group when the selected segment represents a mutually exclusive value, especially in forms. + +### Small Radio Group + + + +### Default Radio Group + + + +### Large Radio Group + + + +## Navigation + +Use links when each segment points to a different destination. Apply `aria-current="page"` to the active link. + +### Small Navigation + + + +### Default Navigation + + + +### Large Navigation + + + +## Filters and modes + +Use a single-selection Toggle Group when segments apply a filter, view, or reversible mode. Use Radio Group instead when one value must always remain selected. + +### Small Toggle Group + + + +### Default Toggle Group + + + +### Large Toggle Group + + + +## Related content + +Use Tabs when each segment controls an associated content panel. Tabs share the visual language of segmented controls but keep their animated indicator, orientation support, and panel semantics. + + diff --git a/apps/ui/content/docs/components/tabs.mdx b/apps/ui/content/docs/components/tabs.mdx index 60e7699f3..1d8916a66 100644 --- a/apps/ui/content/docs/components/tabs.mdx +++ b/apps/ui/content/docs/components/tabs.mdx @@ -65,14 +65,15 @@ import { Tabs, TabsList, TabsPanel, TabsTab } from "@/components/ui/tabs" Root component. Styled wrapper for `Tabs.Root` from Base UI. -| Prop | Type | Default | Description | -| --------- | ---------------------------- | ----------- | ------------------------------------------------ | -| `variant` | `"default" \| "underline"` | `"default"` | Controls the tabs styling | - ### TabsList Container for tab triggers. Styled wrapper for `Tabs.List` from Base UI. +| Prop | Type | Default | Description | +| --------- | -------------------------- | ----------- | ----------------------------------- | +| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Controls the size of all tab items. | +| `variant` | `"default" \| "underline"` | `"default"` | Controls the tabs styling. | + ### TabsTab Individual tab trigger. Styled wrapper for `Tabs.Tab` from Base UI. @@ -87,6 +88,18 @@ Visual indicator for the active tab. Styled wrapper for `Tabs.Indicator` from Ba ## Examples +For guidance on choosing between Tabs, Radio Group, Toggle Group, and navigation links, see the [Segmented Control](/ui/docs/components/segmented-control) pattern. + +Tabs use the same optical sizing as segmented controls. The default surface is slightly taller than a Button of the same size so its inset active indicator remains visually balanced alongside adjacent controls. + +### Small + + + +### Large + + + ### Underline Variant diff --git a/apps/ui/content/docs/components/toggle-group.mdx b/apps/ui/content/docs/components/toggle-group.mdx index fd22c6c27..f42fe9219 100644 --- a/apps/ui/content/docs/components/toggle-group.mdx +++ b/apps/ui/content/docs/components/toggle-group.mdx @@ -78,6 +78,8 @@ Visual separator between toggle buttons. ## Examples +For tabs-style filters and modes, see the [Segmented Control](/ui/docs/components/segmented-control) pattern. + ### Small Toggles diff --git a/apps/ui/public/r/p-navigation-1.json b/apps/ui/public/r/p-navigation-1.json new file mode 100644 index 000000000..41533cd03 --- /dev/null +++ b/apps/ui/public/r/p-navigation-1.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-navigation-1", + "description": "Tabs-style segmented navigation", + "registryDependencies": [ + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-navigation-1.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"current\" });\n\nexport default function Particle() {\n return (\n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "navigation", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-navigation-2.json b/apps/ui/public/r/p-navigation-2.json new file mode 100644 index 000000000..b34bd5de7 --- /dev/null +++ b/apps/ui/public/r/p-navigation-2.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-navigation-2", + "description": "Small tabs-style segmented navigation", + "registryDependencies": [ + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-navigation-2.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"current\",\n});\n\nexport default function Particle() {\n return (\n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "navigation", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-navigation-3.json b/apps/ui/public/r/p-navigation-3.json new file mode 100644 index 000000000..0399fac89 --- /dev/null +++ b/apps/ui/public/r/p-navigation-3.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-navigation-3", + "description": "Large tabs-style segmented navigation", + "registryDependencies": [ + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-navigation-3.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"current\",\n});\n\nexport default function Particle() {\n return (\n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "navigation", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-radio-group-7.json b/apps/ui/public/r/p-radio-group-7.json new file mode 100644 index 000000000..a31343391 --- /dev/null +++ b/apps/ui/public/r/p-radio-group-7.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-radio-group-7", + "description": "Small tabs-style segmented control", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-radio-group-7.tsx", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"sm\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "radio group", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-radio-group-8.json b/apps/ui/public/r/p-radio-group-8.json new file mode 100644 index 000000000..ed81a4fab --- /dev/null +++ b/apps/ui/public/r/p-radio-group-8.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-radio-group-8", + "description": "Tabs-style segmented control", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-radio-group-8.tsx", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "radio group", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-radio-group-9.json b/apps/ui/public/r/p-radio-group-9.json new file mode 100644 index 000000000..7e77665ff --- /dev/null +++ b/apps/ui/public/r/p-radio-group-9.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-radio-group-9", + "description": "Large tabs-style segmented control", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "files": [ + { + "path": "registry/default/particles/p-radio-group-9.tsx", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"lg\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "radio group", + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-tabs-14.json b/apps/ui/public/r/p-tabs-14.json new file mode 100644 index 000000000..029a9b195 --- /dev/null +++ b/apps/ui/public/r/p-tabs-14.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-tabs-14", + "description": "Small tabs", + "registryDependencies": [ + "@coss/tabs" + ], + "files": [ + { + "path": "registry/default/particles/p-tabs-14.tsx", + "content": "import { Tabs, TabsList, TabsPanel, TabsTab } from \"@/registry/default/ui/tabs\";\n\nexport default function Particle() {\n return (\n \n \n Tab 1\n Tab 2\n Tab 3\n \n \n

\n Tab 1 content\n

\n
\n \n

\n Tab 2 content\n

\n
\n \n

\n Tab 3 content\n

\n
\n
\n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-tabs-15.json b/apps/ui/public/r/p-tabs-15.json new file mode 100644 index 000000000..39c7cca21 --- /dev/null +++ b/apps/ui/public/r/p-tabs-15.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-tabs-15", + "description": "Large tabs", + "registryDependencies": [ + "@coss/tabs" + ], + "files": [ + { + "path": "registry/default/particles/p-tabs-15.tsx", + "content": "import { Tabs, TabsList, TabsPanel, TabsTab } from \"@/registry/default/ui/tabs\";\n\nexport default function Particle() {\n return (\n \n \n Tab 1\n Tab 2\n Tab 3\n \n \n

\n Tab 1 content\n

\n
\n \n

\n Tab 2 content\n

\n
\n \n

\n Tab 3 content\n

\n
\n
\n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "tabs" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json new file mode 100644 index 000000000..8002cd60e --- /dev/null +++ b/apps/ui/public/r/p-toggle-group-10.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-toggle-group-10", + "description": "Small tabs-style filter toggles", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "files": [ + { + "path": "registry/default/particles/p-toggle-group-10.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json new file mode 100644 index 000000000..3a3b79dd8 --- /dev/null +++ b/apps/ui/public/r/p-toggle-group-11.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-toggle-group-11", + "description": "Tabs-style filter toggles", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "files": [ + { + "path": "registry/default/particles/p-toggle-group-11.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json new file mode 100644 index 000000000..deedcf1b4 --- /dev/null +++ b/apps/ui/public/r/p-toggle-group-12.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "p-toggle-group-12", + "description": "Large tabs-style filter toggles", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "files": [ + { + "path": "registry/default/particles/p-toggle-group-12.tsx", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "type": "registry:block" + } + ], + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "type": "registry:block" +} \ No newline at end of file diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index a9ccab9d9..1e4d6ab11 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -810,6 +810,9 @@ } ], "name": "tabs", + "registryDependencies": [ + "@coss/segmented-control" + ], "type": "registry:ui" }, { @@ -8347,6 +8350,60 @@ ], "type": "registry:block" }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-1.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-1", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Small tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-2.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-2", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Large tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-3.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-3", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, { "categories": [ "pagination" @@ -8710,6 +8767,63 @@ ], "type": "registry:block" }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Small tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-7.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-7", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-8.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-8", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Large tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-9.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-9", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, { "categories": [ "scroll area" @@ -10594,6 +10708,40 @@ ], "type": "registry:block" }, + { + "categories": [ + "tabs" + ], + "description": "Small tabs", + "files": [ + { + "path": "registry/default/particles/p-tabs-14.tsx", + "type": "registry:block" + } + ], + "name": "p-tabs-14", + "registryDependencies": [ + "@coss/tabs" + ], + "type": "registry:block" + }, + { + "categories": [ + "tabs" + ], + "description": "Large tabs", + "files": [ + { + "path": "registry/default/particles/p-tabs-15.tsx", + "type": "registry:block" + } + ], + "name": "p-tabs-15", + "registryDependencies": [ + "@coss/tabs" + ], + "type": "registry:block" + }, { "categories": [ "textarea" @@ -11329,6 +11477,69 @@ ], "type": "registry:block" }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Small tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-10.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-10", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-11.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-11", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Large tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-12.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-12", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, { "categories": [ "toggle" @@ -11813,6 +12024,19 @@ "dependency": "geist" } }, + { + "dependencies": [ + "class-variance-authority" + ], + "files": [ + { + "path": "registry/default/lib/segmented-control.ts", + "type": "registry:lib" + } + ], + "name": "segmented-control", + "type": "registry:lib" + }, { "dependencies": [ "clsx", diff --git a/apps/ui/public/r/segmented-control.json b/apps/ui/public/r/segmented-control.json new file mode 100644 index 000000000..51f426c03 --- /dev/null +++ b/apps/ui/public/r/segmented-control.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "segmented-control", + "dependencies": [ + "class-variance-authority" + ], + "files": [ + { + "path": "registry/default/lib/segmented-control.ts", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "type": "registry:lib" + } + ], + "type": "registry:lib" +} \ No newline at end of file diff --git a/apps/ui/public/r/tabs.json b/apps/ui/public/r/tabs.json index 0760cba83..2628dffdf 100644 --- a/apps/ui/public/r/tabs.json +++ b/apps/ui/public/r/tabs.json @@ -4,10 +4,13 @@ "dependencies": [ "@base-ui/react" ], + "registryDependencies": [ + "@coss/segmented-control" + ], "files": [ { "path": "registry/default/ui/tabs.tsx", - "content": "\"use client\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport type React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\nexport type TabsVariant = \"default\" | \"underline\";\n\nexport function Tabs({\n className,\n ...props\n}: TabsPrimitive.Root.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function TabsList({\n variant = \"default\",\n className,\n children,\n ...props\n}: TabsPrimitive.List.Props & {\n variant?: TabsVariant;\n}): React.ReactElement {\n return (\n \n {children}\n \n \n );\n}\n\nexport function TabsTab({\n className,\n ...props\n}: TabsPrimitive.Tab.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function TabsPanel({\n className,\n ...props\n}: TabsPrimitive.Panel.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport { TabsPrimitive, TabsTab as TabsTrigger, TabsPanel as TabsContent };\n", + "content": "\"use client\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport * as React from \"react\";\nimport {\n type SegmentedControlSize,\n segmentedControlItemSizeClassNames,\n} from \"@/registry/default/lib/segmented-control\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\ntype TabsVariant = \"default\" | \"underline\";\ntype TabsSize = SegmentedControlSize;\n\nconst TabsListContext: React.Context =\n React.createContext(\"default\");\n\nexport function Tabs({\n className,\n ...props\n}: TabsPrimitive.Root.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function TabsList({\n variant = \"default\",\n size = \"default\",\n className,\n children,\n ...props\n}: TabsPrimitive.List.Props & {\n size?: TabsSize;\n variant?: TabsVariant;\n}): React.ReactElement {\n return (\n \n \n {children}\n \n \n \n );\n}\n\nexport function TabsTab({\n className,\n size,\n ...props\n}: TabsPrimitive.Tab.Props & {\n size?: TabsSize;\n}): React.ReactElement {\n const contextSize: TabsSize = React.useContext(TabsListContext);\n const resolvedSize: TabsSize = size ?? contextSize;\n\n return (\n \n );\n}\n\nexport function TabsPanel({\n className,\n ...props\n}: TabsPrimitive.Panel.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport {\n TabsPrimitive,\n TabsTab as TabsTrigger,\n TabsPanel as TabsContent,\n type TabsSize,\n type TabsVariant,\n};\n", "type": "registry:ui" } ], diff --git a/apps/ui/registry.json b/apps/ui/registry.json index a9ccab9d9..1e4d6ab11 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -810,6 +810,9 @@ } ], "name": "tabs", + "registryDependencies": [ + "@coss/segmented-control" + ], "type": "registry:ui" }, { @@ -8347,6 +8350,60 @@ ], "type": "registry:block" }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-1.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-1", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Small tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-2.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-2", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "navigation", + "tabs" + ], + "description": "Large tabs-style segmented navigation", + "files": [ + { + "path": "registry/default/particles/p-navigation-3.tsx", + "type": "registry:block" + } + ], + "name": "p-navigation-3", + "registryDependencies": [ + "@coss/segmented-control" + ], + "type": "registry:block" + }, { "categories": [ "pagination" @@ -8710,6 +8767,63 @@ ], "type": "registry:block" }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Small tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-7.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-7", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-8.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-8", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, + { + "categories": [ + "radio group", + "tabs" + ], + "description": "Large tabs-style segmented control", + "files": [ + { + "path": "registry/default/particles/p-radio-group-9.tsx", + "type": "registry:block" + } + ], + "name": "p-radio-group-9", + "registryDependencies": [ + "@coss/radio-group", + "@coss/segmented-control" + ], + "type": "registry:block" + }, { "categories": [ "scroll area" @@ -10594,6 +10708,40 @@ ], "type": "registry:block" }, + { + "categories": [ + "tabs" + ], + "description": "Small tabs", + "files": [ + { + "path": "registry/default/particles/p-tabs-14.tsx", + "type": "registry:block" + } + ], + "name": "p-tabs-14", + "registryDependencies": [ + "@coss/tabs" + ], + "type": "registry:block" + }, + { + "categories": [ + "tabs" + ], + "description": "Large tabs", + "files": [ + { + "path": "registry/default/particles/p-tabs-15.tsx", + "type": "registry:block" + } + ], + "name": "p-tabs-15", + "registryDependencies": [ + "@coss/tabs" + ], + "type": "registry:block" + }, { "categories": [ "textarea" @@ -11329,6 +11477,69 @@ ], "type": "registry:block" }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Small tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-10.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-10", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-11.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-11", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, + { + "categories": [ + "toggle", + "toggle group", + "tabs", + "filter" + ], + "description": "Large tabs-style filter toggles", + "files": [ + { + "path": "registry/default/particles/p-toggle-group-12.tsx", + "type": "registry:block" + } + ], + "name": "p-toggle-group-12", + "registryDependencies": [ + "@coss/segmented-control", + "@coss/toggle-group" + ], + "type": "registry:block" + }, { "categories": [ "toggle" @@ -11813,6 +12024,19 @@ "dependency": "geist" } }, + { + "dependencies": [ + "class-variance-authority" + ], + "files": [ + { + "path": "registry/default/lib/segmented-control.ts", + "type": "registry:lib" + } + ], + "name": "segmented-control", + "type": "registry:lib" + }, { "dependencies": [ "clsx", diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index 9c4d68d6c..348faffbe 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -857,7 +857,7 @@ export const Index: Record = { name: "tabs", description: "", type: "registry:ui", - registryDependencies: undefined, + registryDependencies: ["@coss/segmented-control"], files: [{ path: "registry/default/ui/tabs.tsx", type: "registry:ui", @@ -7189,6 +7189,60 @@ export const Index: Record = { categories: ["number field","input"], meta: {"className":"**:data-[slot=preview]:w-full **:data-[slot=preview]:max-w-64"}, }, + "p-navigation-1": { + name: "p-navigation-1", + description: "Tabs-style segmented navigation", + type: "registry:block", + registryDependencies: ["@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-navigation-1.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-navigation-1.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["navigation","tabs"], + meta: undefined, + }, + "p-navigation-2": { + name: "p-navigation-2", + description: "Small tabs-style segmented navigation", + type: "registry:block", + registryDependencies: ["@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-navigation-2.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-navigation-2.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["navigation","tabs"], + meta: undefined, + }, + "p-navigation-3": { + name: "p-navigation-3", + description: "Large tabs-style segmented navigation", + type: "registry:block", + registryDependencies: ["@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-navigation-3.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-navigation-3.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["navigation","tabs"], + meta: undefined, + }, "p-pagination-1": { name: "p-pagination-1", description: "Pagination example", @@ -7495,6 +7549,60 @@ export const Index: Record = { categories: ["radio group","form"], meta: {"className":"**:data-[slot=preview]:w-full **:data-[slot=preview]:max-w-[320px]"}, }, + "p-radio-group-7": { + name: "p-radio-group-7", + description: "Small tabs-style segmented control", + type: "registry:block", + registryDependencies: ["@coss/radio-group","@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-radio-group-7.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-radio-group-7.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["radio group","tabs"], + meta: undefined, + }, + "p-radio-group-8": { + name: "p-radio-group-8", + description: "Tabs-style segmented control", + type: "registry:block", + registryDependencies: ["@coss/radio-group","@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-radio-group-8.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-radio-group-8.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["radio group","tabs"], + meta: undefined, + }, + "p-radio-group-9": { + name: "p-radio-group-9", + description: "Large tabs-style segmented control", + type: "registry:block", + registryDependencies: ["@coss/radio-group","@coss/segmented-control"], + files: [{ + path: "registry/default/particles/p-radio-group-9.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-radio-group-9.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["radio group","tabs"], + meta: undefined, + }, "p-scroll-area-1": { name: "p-scroll-area-1", description: "Basic scroll area", @@ -9079,6 +9187,42 @@ export const Index: Record = { categories: ["tabs","tooltip"], meta: undefined, }, + "p-tabs-14": { + name: "p-tabs-14", + description: "Small tabs", + type: "registry:block", + registryDependencies: ["@coss/tabs"], + files: [{ + path: "registry/default/particles/p-tabs-14.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-tabs-14.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["tabs"], + meta: undefined, + }, + "p-tabs-15": { + name: "p-tabs-15", + description: "Large tabs", + type: "registry:block", + registryDependencies: ["@coss/tabs"], + files: [{ + path: "registry/default/particles/p-tabs-15.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-tabs-15.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["tabs"], + meta: undefined, + }, "p-textarea-1": { name: "p-textarea-1", description: "Basic textarea", @@ -9745,6 +9889,60 @@ export const Index: Record = { categories: ["toggle","toggle group"], meta: undefined, }, + "p-toggle-group-10": { + name: "p-toggle-group-10", + description: "Small tabs-style filter toggles", + type: "registry:block", + registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], + files: [{ + path: "registry/default/particles/p-toggle-group-10.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-toggle-group-10.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["toggle","toggle group","tabs","filter"], + meta: undefined, + }, + "p-toggle-group-11": { + name: "p-toggle-group-11", + description: "Tabs-style filter toggles", + type: "registry:block", + registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], + files: [{ + path: "registry/default/particles/p-toggle-group-11.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-toggle-group-11.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["toggle","toggle group","tabs","filter"], + meta: undefined, + }, + "p-toggle-group-12": { + name: "p-toggle-group-12", + description: "Large tabs-style filter toggles", + type: "registry:block", + registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], + files: [{ + path: "registry/default/particles/p-toggle-group-12.tsx", + type: "registry:block", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/particles/p-toggle-group-12.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: ["toggle","toggle group","tabs","filter"], + meta: undefined, + }, "p-toggle-1": { name: "p-toggle-1", description: "Basic toggle", @@ -9989,6 +10187,24 @@ export const Index: Record = { categories: undefined, meta: undefined, }, + "segmented-control": { + name: "segmented-control", + description: "", + type: "registry:lib", + registryDependencies: undefined, + files: [{ + path: "registry/default/lib/segmented-control.ts", + type: "registry:lib", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/default/lib/segmented-control.ts") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "utils": { name: "utils", description: "", diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts new file mode 100644 index 000000000..b473912e6 --- /dev/null +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -0,0 +1,35 @@ +import { cva } from "class-variance-authority"; + +export type SegmentedControlSize = "default" | "lg" | "sm"; + +export const segmentedControlItemSizeClassNames: Record< + SegmentedControlSize, + string +> = { + default: "h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5", + lg: "h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5", + sm: "h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5", +}; + +export const segmentedControlRootClassName = + "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; + +export const segmentedControlItemVariants = cva( + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + { + defaultVariants: { + size: "default", + }, + variants: { + size: segmentedControlItemSizeClassNames, + state: { + checked: + "data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input", + current: + "aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input", + pressed: + "data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input", + }, + }, + }, +); diff --git a/apps/ui/registry/default/particles/p-navigation-1.tsx b/apps/ui/registry/default/particles/p-navigation-1.tsx new file mode 100644 index 000000000..c5c23baa8 --- /dev/null +++ b/apps/ui/registry/default/particles/p-navigation-1.tsx @@ -0,0 +1,24 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; + +const itemClassName = segmentedControlItemVariants({ state: "current" }); + +export default function Particle() { + return ( + + ); +} diff --git a/apps/ui/registry/default/particles/p-navigation-2.tsx b/apps/ui/registry/default/particles/p-navigation-2.tsx new file mode 100644 index 000000000..ccce03d86 --- /dev/null +++ b/apps/ui/registry/default/particles/p-navigation-2.tsx @@ -0,0 +1,27 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; + +const itemClassName = segmentedControlItemVariants({ + size: "sm", + state: "current", +}); + +export default function Particle() { + return ( + + ); +} diff --git a/apps/ui/registry/default/particles/p-navigation-3.tsx b/apps/ui/registry/default/particles/p-navigation-3.tsx new file mode 100644 index 000000000..53dd2ce37 --- /dev/null +++ b/apps/ui/registry/default/particles/p-navigation-3.tsx @@ -0,0 +1,27 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; + +const itemClassName = segmentedControlItemVariants({ + size: "lg", + state: "current", +}); + +export default function Particle() { + return ( + + ); +} diff --git a/apps/ui/registry/default/particles/p-radio-group-7.tsx b/apps/ui/registry/default/particles/p-radio-group-7.tsx new file mode 100644 index 000000000..1e31a259c --- /dev/null +++ b/apps/ui/registry/default/particles/p-radio-group-7.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + RadioGroupPrimitive, + RadioPrimitive, +} from "@/registry/default/ui/radio-group"; + +const itemClassName = segmentedControlItemVariants({ + className: "grow", + size: "sm", + state: "checked", +}); + +export default function Particle() { + return ( + + + Monthly + + + Yearly + + + ); +} diff --git a/apps/ui/registry/default/particles/p-radio-group-8.tsx b/apps/ui/registry/default/particles/p-radio-group-8.tsx new file mode 100644 index 000000000..40683b050 --- /dev/null +++ b/apps/ui/registry/default/particles/p-radio-group-8.tsx @@ -0,0 +1,32 @@ +"use client"; + +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + RadioGroupPrimitive, + RadioPrimitive, +} from "@/registry/default/ui/radio-group"; + +const itemClassName = segmentedControlItemVariants({ + className: "grow", + state: "checked", +}); + +export default function Particle() { + return ( + + + Monthly + + + Yearly + + + ); +} diff --git a/apps/ui/registry/default/particles/p-radio-group-9.tsx b/apps/ui/registry/default/particles/p-radio-group-9.tsx new file mode 100644 index 000000000..8c8ddab39 --- /dev/null +++ b/apps/ui/registry/default/particles/p-radio-group-9.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + RadioGroupPrimitive, + RadioPrimitive, +} from "@/registry/default/ui/radio-group"; + +const itemClassName = segmentedControlItemVariants({ + className: "grow", + size: "lg", + state: "checked", +}); + +export default function Particle() { + return ( + + + Monthly + + + Yearly + + + ); +} diff --git a/apps/ui/registry/default/particles/p-tabs-14.tsx b/apps/ui/registry/default/particles/p-tabs-14.tsx new file mode 100644 index 000000000..16895371e --- /dev/null +++ b/apps/ui/registry/default/particles/p-tabs-14.tsx @@ -0,0 +1,28 @@ +import { Tabs, TabsList, TabsPanel, TabsTab } from "@/registry/default/ui/tabs"; + +export default function Particle() { + return ( + + + Tab 1 + Tab 2 + Tab 3 + + +

+ Tab 1 content +

+
+ +

+ Tab 2 content +

+
+ +

+ Tab 3 content +

+
+
+ ); +} diff --git a/apps/ui/registry/default/particles/p-tabs-15.tsx b/apps/ui/registry/default/particles/p-tabs-15.tsx new file mode 100644 index 000000000..092228198 --- /dev/null +++ b/apps/ui/registry/default/particles/p-tabs-15.tsx @@ -0,0 +1,28 @@ +import { Tabs, TabsList, TabsPanel, TabsTab } from "@/registry/default/ui/tabs"; + +export default function Particle() { + return ( + + + Tab 1 + Tab 2 + Tab 3 + + +

+ Tab 1 content +

+
+ +

+ Tab 2 content +

+
+ +

+ Tab 3 content +

+
+
+ ); +} diff --git a/apps/ui/registry/default/particles/p-toggle-group-10.tsx b/apps/ui/registry/default/particles/p-toggle-group-10.tsx new file mode 100644 index 000000000..263a5a3fb --- /dev/null +++ b/apps/ui/registry/default/particles/p-toggle-group-10.tsx @@ -0,0 +1,34 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + ToggleGroup, + ToggleGroupItem, +} from "@/registry/default/ui/toggle-group"; + +const itemClassName = segmentedControlItemVariants({ + size: "sm", + state: "pressed", +}); + +export default function Particle() { + return ( + + + Open + + + Assigned + + + Urgent + + + ); +} diff --git a/apps/ui/registry/default/particles/p-toggle-group-11.tsx b/apps/ui/registry/default/particles/p-toggle-group-11.tsx new file mode 100644 index 000000000..eb0bd13d2 --- /dev/null +++ b/apps/ui/registry/default/particles/p-toggle-group-11.tsx @@ -0,0 +1,30 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + ToggleGroup, + ToggleGroupItem, +} from "@/registry/default/ui/toggle-group"; + +const itemClassName = segmentedControlItemVariants({ state: "pressed" }); + +export default function Particle() { + return ( + + + Open + + + Assigned + + + Urgent + + + ); +} diff --git a/apps/ui/registry/default/particles/p-toggle-group-12.tsx b/apps/ui/registry/default/particles/p-toggle-group-12.tsx new file mode 100644 index 000000000..5cf497c09 --- /dev/null +++ b/apps/ui/registry/default/particles/p-toggle-group-12.tsx @@ -0,0 +1,34 @@ +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/registry/default/lib/segmented-control"; +import { + ToggleGroup, + ToggleGroupItem, +} from "@/registry/default/ui/toggle-group"; + +const itemClassName = segmentedControlItemVariants({ + size: "lg", + state: "pressed", +}); + +export default function Particle() { + return ( + + + Open + + + Assigned + + + Urgent + + + ); +} diff --git a/apps/ui/registry/default/ui/tabs.tsx b/apps/ui/registry/default/ui/tabs.tsx index 7a4b82ee7..17b83777e 100644 --- a/apps/ui/registry/default/ui/tabs.tsx +++ b/apps/ui/registry/default/ui/tabs.tsx @@ -1,10 +1,18 @@ "use client"; import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"; -import type React from "react"; +import * as React from "react"; +import { + type SegmentedControlSize, + segmentedControlItemSizeClassNames, +} from "@/registry/default/lib/segmented-control"; import { cn } from "@/registry/default/lib/utils"; -export type TabsVariant = "default" | "underline"; +type TabsVariant = "default" | "underline"; +type TabsSize = SegmentedControlSize; + +const TabsListContext: React.Context = + React.createContext("default"); export function Tabs({ className, @@ -24,10 +32,12 @@ export function Tabs({ export function TabsList({ variant = "default", + size = "default", className, children, ...props }: TabsPrimitive.List.Props & { + size?: TabsSize; variant?: TabsVariant; }): React.ReactElement { return ( @@ -40,10 +50,13 @@ export function TabsList({ : "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1 *:data-[slot=tabs-tab]:hover:bg-accent", className, )} + data-size={size} data-slot="tabs-list" {...props} > - {children} + + {children} + @@ -86,4 +107,10 @@ export function TabsPanel({ ); } -export { TabsPrimitive, TabsTab as TabsTrigger, TabsPanel as TabsContent }; +export { + TabsPrimitive, + TabsTab as TabsTrigger, + TabsPanel as TabsContent, + type TabsSize, + type TabsVariant, +}; diff --git a/apps/ui/registry/registry-categories.ts b/apps/ui/registry/registry-categories.ts index 3891865fd..3ca76c6dc 100644 --- a/apps/ui/registry/registry-categories.ts +++ b/apps/ui/registry/registry-categories.ts @@ -40,6 +40,7 @@ export const registryCategories = [ "label", "menu", "meter", + "navigation", "number field", "otp field", "pagination", diff --git a/apps/ui/registry/registry-lib.ts b/apps/ui/registry/registry-lib.ts index 9d4db687b..7cedb75f6 100644 --- a/apps/ui/registry/registry-lib.ts +++ b/apps/ui/registry/registry-lib.ts @@ -1,6 +1,17 @@ import type { Registry } from "shadcn/schema"; export const lib: Registry["items"] = [ + { + dependencies: ["class-variance-authority"], + files: [ + { + path: "lib/segmented-control.ts", + type: "registry:lib", + }, + ], + name: "segmented-control", + type: "registry:lib", + }, { dependencies: ["clsx", "tailwind-merge"], files: [ diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index 00d65451c..c7a7d300b 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -3954,6 +3954,30 @@ export const particles: ParticleItem[] = [ registryDependencies: ["@coss/number-field"], type: "registry:block", }, + { + categories: categories("navigation", "tabs"), + description: "Tabs-style segmented navigation", + files: [{ path: "particles/p-navigation-1.tsx", type: "registry:block" }], + name: "p-navigation-1", + registryDependencies: ["@coss/segmented-control"], + type: "registry:block", + }, + { + categories: categories("navigation", "tabs"), + description: "Small tabs-style segmented navigation", + files: [{ path: "particles/p-navigation-2.tsx", type: "registry:block" }], + name: "p-navigation-2", + registryDependencies: ["@coss/segmented-control"], + type: "registry:block", + }, + { + categories: categories("navigation", "tabs"), + description: "Large tabs-style segmented navigation", + files: [{ path: "particles/p-navigation-3.tsx", type: "registry:block" }], + name: "p-navigation-3", + registryDependencies: ["@coss/segmented-control"], + type: "registry:block", + }, { categories: categories("pagination"), description: "Pagination example", @@ -4147,6 +4171,30 @@ export const particles: ParticleItem[] = [ ], type: "registry:block", }, + { + categories: categories("radio group", "tabs"), + description: "Small tabs-style segmented control", + files: [{ path: "particles/p-radio-group-7.tsx", type: "registry:block" }], + name: "p-radio-group-7", + registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], + type: "registry:block", + }, + { + categories: categories("radio group", "tabs"), + description: "Tabs-style segmented control", + files: [{ path: "particles/p-radio-group-8.tsx", type: "registry:block" }], + name: "p-radio-group-8", + registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], + type: "registry:block", + }, + { + categories: categories("radio group", "tabs"), + description: "Large tabs-style segmented control", + files: [{ path: "particles/p-radio-group-9.tsx", type: "registry:block" }], + name: "p-radio-group-9", + registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], + type: "registry:block", + }, { categories: categories("scroll area"), description: "Basic scroll area", @@ -5231,6 +5279,22 @@ export const particles: ParticleItem[] = [ registryDependencies: ["@coss/tabs", "@coss/tooltip"], type: "registry:block", }, + { + categories: categories("tabs"), + description: "Small tabs", + files: [{ path: "particles/p-tabs-14.tsx", type: "registry:block" }], + name: "p-tabs-14", + registryDependencies: ["@coss/tabs"], + type: "registry:block", + }, + { + categories: categories("tabs"), + description: "Large tabs", + files: [{ path: "particles/p-tabs-15.tsx", type: "registry:block" }], + name: "p-tabs-15", + registryDependencies: ["@coss/tabs"], + type: "registry:block", + }, { categories: categories("textarea"), description: "Basic textarea", @@ -5601,6 +5665,36 @@ export const particles: ParticleItem[] = [ registryDependencies: ["@coss/toggle-group", "@coss/tooltip"], type: "registry:block", }, + { + categories: categories("toggle", "toggle group", "tabs", "filter"), + description: "Small tabs-style filter toggles", + files: [ + { path: "particles/p-toggle-group-10.tsx", type: "registry:block" }, + ], + name: "p-toggle-group-10", + registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], + type: "registry:block", + }, + { + categories: categories("toggle", "toggle group", "tabs", "filter"), + description: "Tabs-style filter toggles", + files: [ + { path: "particles/p-toggle-group-11.tsx", type: "registry:block" }, + ], + name: "p-toggle-group-11", + registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], + type: "registry:block", + }, + { + categories: categories("toggle", "toggle group", "tabs", "filter"), + description: "Large tabs-style filter toggles", + files: [ + { path: "particles/p-toggle-group-12.tsx", type: "registry:block" }, + ], + name: "p-toggle-group-12", + registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], + type: "registry:block", + }, { categories: categories("toggle"), description: "Basic toggle", diff --git a/apps/ui/registry/registry-ui.ts b/apps/ui/registry/registry-ui.ts index d144a68e9..17c9e01ef 100644 --- a/apps/ui/registry/registry-ui.ts +++ b/apps/ui/registry/registry-ui.ts @@ -701,6 +701,7 @@ export const ui: Registry["items"] = [ }, ], name: "tabs", + registryDependencies: ["@coss/segmented-control"], type: "registry:ui", }, { diff --git a/packages/ui/src/components/tabs.tsx b/packages/ui/src/components/tabs.tsx index 136eb35a0..c3ebe2260 100644 --- a/packages/ui/src/components/tabs.tsx +++ b/packages/ui/src/components/tabs.tsx @@ -1,10 +1,18 @@ "use client"; import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"; +import { + type SegmentedControlSize, + segmentedControlItemSizeClassNames, +} from "@coss/ui/lib/segmented-control"; import { cn } from "@coss/ui/lib/utils"; -import type React from "react"; +import * as React from "react"; -export type TabsVariant = "default" | "underline"; +type TabsVariant = "default" | "underline"; +type TabsSize = SegmentedControlSize; + +const TabsListContext: React.Context = + React.createContext("default"); export function Tabs({ className, @@ -24,10 +32,12 @@ export function Tabs({ export function TabsList({ variant = "default", + size = "default", className, children, ...props }: TabsPrimitive.List.Props & { + size?: TabsSize; variant?: TabsVariant; }): React.ReactElement { return ( @@ -40,10 +50,13 @@ export function TabsList({ : "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1 *:data-[slot=tabs-tab]:hover:bg-accent", className, )} + data-size={size} data-slot="tabs-list" {...props} > - {children} + + {children} + @@ -86,4 +107,10 @@ export function TabsPanel({ ); } -export { TabsPrimitive, TabsTab as TabsTrigger, TabsPanel as TabsContent }; +export { + TabsPrimitive, + TabsTab as TabsTrigger, + TabsPanel as TabsContent, + type TabsSize, + type TabsVariant, +}; diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts new file mode 100644 index 000000000..b473912e6 --- /dev/null +++ b/packages/ui/src/lib/segmented-control.ts @@ -0,0 +1,35 @@ +import { cva } from "class-variance-authority"; + +export type SegmentedControlSize = "default" | "lg" | "sm"; + +export const segmentedControlItemSizeClassNames: Record< + SegmentedControlSize, + string +> = { + default: "h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5", + lg: "h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5", + sm: "h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5", +}; + +export const segmentedControlRootClassName = + "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; + +export const segmentedControlItemVariants = cva( + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + { + defaultVariants: { + size: "default", + }, + variants: { + size: segmentedControlItemSizeClassNames, + state: { + checked: + "data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input", + current: + "aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input", + pressed: + "data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input", + }, + }, + }, +); From 7a52eff95e69eefeda8505f5e2991691bda61c4b Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 19:59:56 +0200 Subject: [PATCH 02/17] docs(ui): add tabs migration guidance --- apps/ui/content/docs/(root)/changelog.mdx | 32 +++++++++++++++++++++++ apps/ui/content/docs/components/tabs.mdx | 14 +++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/apps/ui/content/docs/(root)/changelog.mdx b/apps/ui/content/docs/(root)/changelog.mdx index 61597e582..bd2c89900 100644 --- a/apps/ui/content/docs/(root)/changelog.mdx +++ b/apps/ui/content/docs/(root)/changelog.mdx @@ -3,6 +3,38 @@ title: Changelog description: Breaking changes, migration guides, and notable updates. --- +## August 17, 2026 + +### Tabs sizing and segmented control styles + +**`TabsList`** now supports a **`size`** prop with **`"sm"`**, **`"default"`**, and **`"lg"`** values. The size propagates to its **`TabsTab`** children, and an individual tab can override the inherited size when necessary. + +The default Tabs appearance now uses the same optical item sizing as the [Segmented Control](/ui/docs/components/segmented-control) pattern. The default rendered height is slightly smaller than before so the inset active indicator remains visually balanced beside a Button of the corresponding size. + +Tabs now imports its size map from the **`@coss/segmented-control`** registry library. **`@coss/tabs`** declares this as a registry dependency, so the shadcn CLI installs it automatically with a fresh installation or CLI-managed update. + +**Migration:** + +Existing Tabs JSX requires no changes because **`"default"`** remains the default size. If you replace your local Tabs component through the CLI, review any local customizations before accepting the overwrite: + +```bash +npx shadcn@latest add @coss/tabs +``` + +If you update **`tabs.tsx`** manually, install the shared library first and then merge the latest Tabs implementation. Copying only the new Tabs file without this dependency results in an unresolved import. + +```bash +npx shadcn@latest add @coss/segmented-control +``` + +After updating, remove local height or horizontal-padding utilities from **`TabsList`** and **`TabsTab`** only where they unintentionally override the new **`size`** API. Keep intentional product-specific overrides. + +**Agent migration prompt:** + +```text +Update the local coss Tabs component to the latest segmented-control sizing while preserving project-specific customizations. Install the shared registry dependency with `npx shadcn@latest add @coss/segmented-control`, then merge the latest @coss/tabs implementation. TabsList now accepts size="sm" | "default" | "lg" (default: "default") and propagates it to TabsTab; a TabsTab size prop overrides the inherited value. Replace the old hard-coded TabsTab height and horizontal-padding classes with segmentedControlItemSizeClassNames from the shared library. Existing Tabs JSX does not need a size prop. Audit local h-* and px-* overrides on TabsList/TabsTab and remove only those that unintentionally conflict with the new size API. Run formatting and typechecking, then visually verify default and underline Tabs in every size used by the app. +``` + ## July 31, 2026 ### Scroll Area — overscroll contain diff --git a/apps/ui/content/docs/components/tabs.mdx b/apps/ui/content/docs/components/tabs.mdx index 1d8916a66..c08dd1dca 100644 --- a/apps/ui/content/docs/components/tabs.mdx +++ b/apps/ui/content/docs/components/tabs.mdx @@ -22,13 +22,25 @@ links: npx shadcn@latest add @coss/tabs ``` +The CLI installs the shared `@coss/segmented-control` registry dependency automatically. + -Copy and paste the following code into your project. +Install the following dependencies: + +```bash +npm install @base-ui/react class-variance-authority +``` + +Copy the shared segmented control styling into your project. + + + +Copy and paste the Tabs component into your project. From 1dbd739b192635884893472e1da9475706717c1d Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:16:28 +0200 Subject: [PATCH 03/17] docs(ui): mark segmented control as new --- apps/ui/lib/docs.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/ui/lib/docs.ts b/apps/ui/lib/docs.ts index d9f5d1169..baff695c5 100644 --- a/apps/ui/lib/docs.ts +++ b/apps/ui/lib/docs.ts @@ -1,5 +1,4 @@ export const PAGES_NEW = [ // "/docs/components/{component-name}", - "/docs/components/context-menu", - "/docs/components/otp-field", + "/docs/components/segmented-control", ]; From 772085c1a31e3e388cc0d7da00b39b3ff56568c8 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:19:58 +0200 Subject: [PATCH 04/17] fix(ui): add segmented control particle tag --- apps/ui/public/r/p-navigation-1.json | 1 + apps/ui/public/r/p-navigation-2.json | 1 + apps/ui/public/r/p-navigation-3.json | 1 + apps/ui/public/r/p-radio-group-7.json | 1 + apps/ui/public/r/p-radio-group-8.json | 1 + apps/ui/public/r/p-radio-group-9.json | 1 + apps/ui/public/r/p-tabs-1.json | 1 + apps/ui/public/r/p-tabs-14.json | 1 + apps/ui/public/r/p-tabs-15.json | 1 + apps/ui/public/r/p-toggle-group-10.json | 1 + apps/ui/public/r/p-toggle-group-11.json | 1 + apps/ui/public/r/p-toggle-group-12.json | 1 + apps/ui/public/r/registry.json | 12 +++++++ apps/ui/registry.json | 12 +++++++ apps/ui/registry/__index__.tsx | 24 +++++++------- apps/ui/registry/registry-categories.ts | 1 + apps/ui/registry/registry-particles.ts | 42 ++++++++++++++++++------- 17 files changed, 79 insertions(+), 24 deletions(-) diff --git a/apps/ui/public/r/p-navigation-1.json b/apps/ui/public/r/p-navigation-1.json index 41533cd03..d5b27e0c0 100644 --- a/apps/ui/public/r/p-navigation-1.json +++ b/apps/ui/public/r/p-navigation-1.json @@ -14,6 +14,7 @@ ], "categories": [ "navigation", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-navigation-2.json b/apps/ui/public/r/p-navigation-2.json index b34bd5de7..0d557f9f0 100644 --- a/apps/ui/public/r/p-navigation-2.json +++ b/apps/ui/public/r/p-navigation-2.json @@ -14,6 +14,7 @@ ], "categories": [ "navigation", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-navigation-3.json b/apps/ui/public/r/p-navigation-3.json index 0399fac89..fd48c33e5 100644 --- a/apps/ui/public/r/p-navigation-3.json +++ b/apps/ui/public/r/p-navigation-3.json @@ -14,6 +14,7 @@ ], "categories": [ "navigation", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-radio-group-7.json b/apps/ui/public/r/p-radio-group-7.json index a31343391..58549403e 100644 --- a/apps/ui/public/r/p-radio-group-7.json +++ b/apps/ui/public/r/p-radio-group-7.json @@ -15,6 +15,7 @@ ], "categories": [ "radio group", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-radio-group-8.json b/apps/ui/public/r/p-radio-group-8.json index ed81a4fab..6b6a6851f 100644 --- a/apps/ui/public/r/p-radio-group-8.json +++ b/apps/ui/public/r/p-radio-group-8.json @@ -15,6 +15,7 @@ ], "categories": [ "radio group", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-radio-group-9.json b/apps/ui/public/r/p-radio-group-9.json index 7e77665ff..308cb3bfa 100644 --- a/apps/ui/public/r/p-radio-group-9.json +++ b/apps/ui/public/r/p-radio-group-9.json @@ -15,6 +15,7 @@ ], "categories": [ "radio group", + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-tabs-1.json b/apps/ui/public/r/p-tabs-1.json index 7ecaecc3a..386c6eb4f 100644 --- a/apps/ui/public/r/p-tabs-1.json +++ b/apps/ui/public/r/p-tabs-1.json @@ -13,6 +13,7 @@ } ], "categories": [ + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-tabs-14.json b/apps/ui/public/r/p-tabs-14.json index 029a9b195..a3a109a43 100644 --- a/apps/ui/public/r/p-tabs-14.json +++ b/apps/ui/public/r/p-tabs-14.json @@ -13,6 +13,7 @@ } ], "categories": [ + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-tabs-15.json b/apps/ui/public/r/p-tabs-15.json index 39c7cca21..f08c158fa 100644 --- a/apps/ui/public/r/p-tabs-15.json +++ b/apps/ui/public/r/p-tabs-15.json @@ -13,6 +13,7 @@ } ], "categories": [ + "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json index 8002cd60e..dc2202a3b 100644 --- a/apps/ui/public/r/p-toggle-group-10.json +++ b/apps/ui/public/r/p-toggle-group-10.json @@ -16,6 +16,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json index 3a3b79dd8..8453eef1e 100644 --- a/apps/ui/public/r/p-toggle-group-11.json +++ b/apps/ui/public/r/p-toggle-group-11.json @@ -16,6 +16,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json index deedcf1b4..8ea294ee3 100644 --- a/apps/ui/public/r/p-toggle-group-12.json +++ b/apps/ui/public/r/p-toggle-group-12.json @@ -16,6 +16,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index 1e4d6ab11..1f0b0d4bf 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -8353,6 +8353,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Tabs-style segmented navigation", @@ -8371,6 +8372,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Small tabs-style segmented navigation", @@ -8389,6 +8391,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Large tabs-style segmented navigation", @@ -8770,6 +8773,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Small tabs-style segmented control", @@ -8789,6 +8793,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Tabs-style segmented control", @@ -8808,6 +8813,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Large tabs-style segmented control", @@ -10453,6 +10459,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Basic tabs", @@ -10710,6 +10717,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Small tabs", @@ -10727,6 +10735,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Large tabs", @@ -11481,6 +11490,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], @@ -11502,6 +11512,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], @@ -11523,6 +11534,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], diff --git a/apps/ui/registry.json b/apps/ui/registry.json index 1e4d6ab11..1f0b0d4bf 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -8353,6 +8353,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Tabs-style segmented navigation", @@ -8371,6 +8372,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Small tabs-style segmented navigation", @@ -8389,6 +8391,7 @@ { "categories": [ "navigation", + "segmented control", "tabs" ], "description": "Large tabs-style segmented navigation", @@ -8770,6 +8773,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Small tabs-style segmented control", @@ -8789,6 +8793,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Tabs-style segmented control", @@ -8808,6 +8813,7 @@ { "categories": [ "radio group", + "segmented control", "tabs" ], "description": "Large tabs-style segmented control", @@ -10453,6 +10459,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Basic tabs", @@ -10710,6 +10717,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Small tabs", @@ -10727,6 +10735,7 @@ }, { "categories": [ + "segmented control", "tabs" ], "description": "Large tabs", @@ -11481,6 +11490,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], @@ -11502,6 +11512,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], @@ -11523,6 +11534,7 @@ "categories": [ "toggle", "toggle group", + "segmented control", "tabs", "filter" ], diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index 348faffbe..b6fed34aa 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -7204,7 +7204,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","tabs"], + categories: ["navigation","segmented control","tabs"], meta: undefined, }, "p-navigation-2": { @@ -7222,7 +7222,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","tabs"], + categories: ["navigation","segmented control","tabs"], meta: undefined, }, "p-navigation-3": { @@ -7240,7 +7240,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","tabs"], + categories: ["navigation","segmented control","tabs"], meta: undefined, }, "p-pagination-1": { @@ -7564,7 +7564,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","tabs"], + categories: ["radio group","segmented control","tabs"], meta: undefined, }, "p-radio-group-8": { @@ -7582,7 +7582,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","tabs"], + categories: ["radio group","segmented control","tabs"], meta: undefined, }, "p-radio-group-9": { @@ -7600,7 +7600,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","tabs"], + categories: ["radio group","segmented control","tabs"], meta: undefined, }, "p-scroll-area-1": { @@ -8968,7 +8968,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["tabs"], + categories: ["segmented control","tabs"], meta: undefined, }, "p-tabs-2": { @@ -9202,7 +9202,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["tabs"], + categories: ["segmented control","tabs"], meta: undefined, }, "p-tabs-15": { @@ -9220,7 +9220,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["tabs"], + categories: ["segmented control","tabs"], meta: undefined, }, "p-textarea-1": { @@ -9904,7 +9904,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","tabs","filter"], + categories: ["toggle","toggle group","segmented control","tabs","filter"], meta: undefined, }, "p-toggle-group-11": { @@ -9922,7 +9922,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","tabs","filter"], + categories: ["toggle","toggle group","segmented control","tabs","filter"], meta: undefined, }, "p-toggle-group-12": { @@ -9940,7 +9940,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","tabs","filter"], + categories: ["toggle","toggle group","segmented control","tabs","filter"], meta: undefined, }, "p-toggle-1": { diff --git a/apps/ui/registry/registry-categories.ts b/apps/ui/registry/registry-categories.ts index 3ca76c6dc..dd8e332f1 100644 --- a/apps/ui/registry/registry-categories.ts +++ b/apps/ui/registry/registry-categories.ts @@ -50,6 +50,7 @@ export const registryCategories = [ "radio group", "scroll area", "select", + "segmented control", "separator", "sheet", "skeleton", diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index c7a7d300b..0bd2a7ffc 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -3955,7 +3955,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "tabs"), + categories: categories("navigation", "segmented control", "tabs"), description: "Tabs-style segmented navigation", files: [{ path: "particles/p-navigation-1.tsx", type: "registry:block" }], name: "p-navigation-1", @@ -3963,7 +3963,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "tabs"), + categories: categories("navigation", "segmented control", "tabs"), description: "Small tabs-style segmented navigation", files: [{ path: "particles/p-navigation-2.tsx", type: "registry:block" }], name: "p-navigation-2", @@ -3971,7 +3971,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "tabs"), + categories: categories("navigation", "segmented control", "tabs"), description: "Large tabs-style segmented navigation", files: [{ path: "particles/p-navigation-3.tsx", type: "registry:block" }], name: "p-navigation-3", @@ -4172,7 +4172,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "tabs"), + categories: categories("radio group", "segmented control", "tabs"), description: "Small tabs-style segmented control", files: [{ path: "particles/p-radio-group-7.tsx", type: "registry:block" }], name: "p-radio-group-7", @@ -4180,7 +4180,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "tabs"), + categories: categories("radio group", "segmented control", "tabs"), description: "Tabs-style segmented control", files: [{ path: "particles/p-radio-group-8.tsx", type: "registry:block" }], name: "p-radio-group-8", @@ -4188,7 +4188,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "tabs"), + categories: categories("radio group", "segmented control", "tabs"), description: "Large tabs-style segmented control", files: [{ path: "particles/p-radio-group-9.tsx", type: "registry:block" }], name: "p-radio-group-9", @@ -5157,7 +5157,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("tabs"), + categories: categories("segmented control", "tabs"), description: "Basic tabs", files: [{ path: "particles/p-tabs-1.tsx", type: "registry:block" }], name: "p-tabs-1", @@ -5280,7 +5280,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("tabs"), + categories: categories("segmented control", "tabs"), description: "Small tabs", files: [{ path: "particles/p-tabs-14.tsx", type: "registry:block" }], name: "p-tabs-14", @@ -5288,7 +5288,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("tabs"), + categories: categories("segmented control", "tabs"), description: "Large tabs", files: [{ path: "particles/p-tabs-15.tsx", type: "registry:block" }], name: "p-tabs-15", @@ -5666,7 +5666,13 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("toggle", "toggle group", "tabs", "filter"), + categories: categories( + "toggle", + "toggle group", + "segmented control", + "tabs", + "filter", + ), description: "Small tabs-style filter toggles", files: [ { path: "particles/p-toggle-group-10.tsx", type: "registry:block" }, @@ -5676,7 +5682,13 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("toggle", "toggle group", "tabs", "filter"), + categories: categories( + "toggle", + "toggle group", + "segmented control", + "tabs", + "filter", + ), description: "Tabs-style filter toggles", files: [ { path: "particles/p-toggle-group-11.tsx", type: "registry:block" }, @@ -5686,7 +5698,13 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("toggle", "toggle group", "tabs", "filter"), + categories: categories( + "toggle", + "toggle group", + "segmented control", + "tabs", + "filter", + ), description: "Large tabs-style filter toggles", files: [ { path: "particles/p-toggle-group-12.tsx", type: "registry:block" }, From 768cf61631de6018448fbf03fb1aeea5c39cb7b9 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:22:44 +0200 Subject: [PATCH 05/17] fix(ui): clarify segmented particle semantics --- apps/ui/public/r/p-navigation-1.json | 2 +- apps/ui/public/r/p-navigation-2.json | 2 +- apps/ui/public/r/p-navigation-3.json | 2 +- apps/ui/public/r/p-radio-group-7.json | 2 +- apps/ui/public/r/p-radio-group-8.json | 2 +- apps/ui/public/r/p-radio-group-9.json | 2 +- apps/ui/public/r/p-tabs-1.json | 2 +- apps/ui/public/r/p-tabs-14.json | 2 +- apps/ui/public/r/p-tabs-15.json | 2 +- apps/ui/public/r/p-toggle-group-10.json | 2 +- apps/ui/public/r/p-toggle-group-11.json | 2 +- apps/ui/public/r/p-toggle-group-12.json | 2 +- apps/ui/public/r/registry.json | 24 ++++++++++++------------ apps/ui/registry.json | 24 ++++++++++++------------ apps/ui/registry/__index__.tsx | 24 ++++++++++++------------ apps/ui/registry/registry-particles.ts | 24 ++++++++++++------------ 16 files changed, 60 insertions(+), 60 deletions(-) diff --git a/apps/ui/public/r/p-navigation-1.json b/apps/ui/public/r/p-navigation-1.json index d5b27e0c0..b065f0ab3 100644 --- a/apps/ui/public/r/p-navigation-1.json +++ b/apps/ui/public/r/p-navigation-1.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-navigation-1", - "description": "Tabs-style segmented navigation", + "description": "Segmented navigation built with links", "registryDependencies": [ "@coss/segmented-control" ], diff --git a/apps/ui/public/r/p-navigation-2.json b/apps/ui/public/r/p-navigation-2.json index 0d557f9f0..c14b6463a 100644 --- a/apps/ui/public/r/p-navigation-2.json +++ b/apps/ui/public/r/p-navigation-2.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-navigation-2", - "description": "Small tabs-style segmented navigation", + "description": "Small segmented navigation built with links", "registryDependencies": [ "@coss/segmented-control" ], diff --git a/apps/ui/public/r/p-navigation-3.json b/apps/ui/public/r/p-navigation-3.json index fd48c33e5..3a0815653 100644 --- a/apps/ui/public/r/p-navigation-3.json +++ b/apps/ui/public/r/p-navigation-3.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-navigation-3", - "description": "Large tabs-style segmented navigation", + "description": "Large segmented navigation built with links", "registryDependencies": [ "@coss/segmented-control" ], diff --git a/apps/ui/public/r/p-radio-group-7.json b/apps/ui/public/r/p-radio-group-7.json index 58549403e..5dae42c62 100644 --- a/apps/ui/public/r/p-radio-group-7.json +++ b/apps/ui/public/r/p-radio-group-7.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-radio-group-7", - "description": "Small tabs-style segmented control", + "description": "Small segmented control built with a radio group", "registryDependencies": [ "@coss/radio-group", "@coss/segmented-control" diff --git a/apps/ui/public/r/p-radio-group-8.json b/apps/ui/public/r/p-radio-group-8.json index 6b6a6851f..022cb888e 100644 --- a/apps/ui/public/r/p-radio-group-8.json +++ b/apps/ui/public/r/p-radio-group-8.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-radio-group-8", - "description": "Tabs-style segmented control", + "description": "Segmented control built with a radio group", "registryDependencies": [ "@coss/radio-group", "@coss/segmented-control" diff --git a/apps/ui/public/r/p-radio-group-9.json b/apps/ui/public/r/p-radio-group-9.json index 308cb3bfa..4b3e4a554 100644 --- a/apps/ui/public/r/p-radio-group-9.json +++ b/apps/ui/public/r/p-radio-group-9.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-radio-group-9", - "description": "Large tabs-style segmented control", + "description": "Large segmented control built with a radio group", "registryDependencies": [ "@coss/radio-group", "@coss/segmented-control" diff --git a/apps/ui/public/r/p-tabs-1.json b/apps/ui/public/r/p-tabs-1.json index 386c6eb4f..c58e629ec 100644 --- a/apps/ui/public/r/p-tabs-1.json +++ b/apps/ui/public/r/p-tabs-1.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-tabs-1", - "description": "Basic tabs", + "description": "Segmented control built with tabs", "registryDependencies": [ "@coss/tabs" ], diff --git a/apps/ui/public/r/p-tabs-14.json b/apps/ui/public/r/p-tabs-14.json index a3a109a43..870253345 100644 --- a/apps/ui/public/r/p-tabs-14.json +++ b/apps/ui/public/r/p-tabs-14.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-tabs-14", - "description": "Small tabs", + "description": "Small segmented control built with tabs", "registryDependencies": [ "@coss/tabs" ], diff --git a/apps/ui/public/r/p-tabs-15.json b/apps/ui/public/r/p-tabs-15.json index f08c158fa..b37366a86 100644 --- a/apps/ui/public/r/p-tabs-15.json +++ b/apps/ui/public/r/p-tabs-15.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-tabs-15", - "description": "Large tabs", + "description": "Large segmented control built with tabs", "registryDependencies": [ "@coss/tabs" ], diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json index dc2202a3b..13f796de0 100644 --- a/apps/ui/public/r/p-toggle-group-10.json +++ b/apps/ui/public/r/p-toggle-group-10.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-toggle-group-10", - "description": "Small tabs-style filter toggles", + "description": "Small segmented filter built with a toggle group", "registryDependencies": [ "@coss/segmented-control", "@coss/toggle-group" diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json index 8453eef1e..554ba119b 100644 --- a/apps/ui/public/r/p-toggle-group-11.json +++ b/apps/ui/public/r/p-toggle-group-11.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-toggle-group-11", - "description": "Tabs-style filter toggles", + "description": "Segmented filter built with a toggle group", "registryDependencies": [ "@coss/segmented-control", "@coss/toggle-group" diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json index 8ea294ee3..db35b415d 100644 --- a/apps/ui/public/r/p-toggle-group-12.json +++ b/apps/ui/public/r/p-toggle-group-12.json @@ -1,7 +1,7 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "p-toggle-group-12", - "description": "Large tabs-style filter toggles", + "description": "Large segmented filter built with a toggle group", "registryDependencies": [ "@coss/segmented-control", "@coss/toggle-group" diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index 1f0b0d4bf..7875804cc 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -8356,7 +8356,7 @@ "segmented control", "tabs" ], - "description": "Tabs-style segmented navigation", + "description": "Segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-1.tsx", @@ -8375,7 +8375,7 @@ "segmented control", "tabs" ], - "description": "Small tabs-style segmented navigation", + "description": "Small segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-2.tsx", @@ -8394,7 +8394,7 @@ "segmented control", "tabs" ], - "description": "Large tabs-style segmented navigation", + "description": "Large segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-3.tsx", @@ -8776,7 +8776,7 @@ "segmented control", "tabs" ], - "description": "Small tabs-style segmented control", + "description": "Small segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-7.tsx", @@ -8796,7 +8796,7 @@ "segmented control", "tabs" ], - "description": "Tabs-style segmented control", + "description": "Segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-8.tsx", @@ -8816,7 +8816,7 @@ "segmented control", "tabs" ], - "description": "Large tabs-style segmented control", + "description": "Large segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-9.tsx", @@ -10462,7 +10462,7 @@ "segmented control", "tabs" ], - "description": "Basic tabs", + "description": "Segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-1.tsx", @@ -10720,7 +10720,7 @@ "segmented control", "tabs" ], - "description": "Small tabs", + "description": "Small segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-14.tsx", @@ -10738,7 +10738,7 @@ "segmented control", "tabs" ], - "description": "Large tabs", + "description": "Large segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-15.tsx", @@ -11494,7 +11494,7 @@ "tabs", "filter" ], - "description": "Small tabs-style filter toggles", + "description": "Small segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-10.tsx", @@ -11516,7 +11516,7 @@ "tabs", "filter" ], - "description": "Tabs-style filter toggles", + "description": "Segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-11.tsx", @@ -11538,7 +11538,7 @@ "tabs", "filter" ], - "description": "Large tabs-style filter toggles", + "description": "Large segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-12.tsx", diff --git a/apps/ui/registry.json b/apps/ui/registry.json index 1f0b0d4bf..7875804cc 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -8356,7 +8356,7 @@ "segmented control", "tabs" ], - "description": "Tabs-style segmented navigation", + "description": "Segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-1.tsx", @@ -8375,7 +8375,7 @@ "segmented control", "tabs" ], - "description": "Small tabs-style segmented navigation", + "description": "Small segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-2.tsx", @@ -8394,7 +8394,7 @@ "segmented control", "tabs" ], - "description": "Large tabs-style segmented navigation", + "description": "Large segmented navigation built with links", "files": [ { "path": "registry/default/particles/p-navigation-3.tsx", @@ -8776,7 +8776,7 @@ "segmented control", "tabs" ], - "description": "Small tabs-style segmented control", + "description": "Small segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-7.tsx", @@ -8796,7 +8796,7 @@ "segmented control", "tabs" ], - "description": "Tabs-style segmented control", + "description": "Segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-8.tsx", @@ -8816,7 +8816,7 @@ "segmented control", "tabs" ], - "description": "Large tabs-style segmented control", + "description": "Large segmented control built with a radio group", "files": [ { "path": "registry/default/particles/p-radio-group-9.tsx", @@ -10462,7 +10462,7 @@ "segmented control", "tabs" ], - "description": "Basic tabs", + "description": "Segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-1.tsx", @@ -10720,7 +10720,7 @@ "segmented control", "tabs" ], - "description": "Small tabs", + "description": "Small segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-14.tsx", @@ -10738,7 +10738,7 @@ "segmented control", "tabs" ], - "description": "Large tabs", + "description": "Large segmented control built with tabs", "files": [ { "path": "registry/default/particles/p-tabs-15.tsx", @@ -11494,7 +11494,7 @@ "tabs", "filter" ], - "description": "Small tabs-style filter toggles", + "description": "Small segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-10.tsx", @@ -11516,7 +11516,7 @@ "tabs", "filter" ], - "description": "Tabs-style filter toggles", + "description": "Segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-11.tsx", @@ -11538,7 +11538,7 @@ "tabs", "filter" ], - "description": "Large tabs-style filter toggles", + "description": "Large segmented filter built with a toggle group", "files": [ { "path": "registry/default/particles/p-toggle-group-12.tsx", diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index b6fed34aa..addaf33c6 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -7191,7 +7191,7 @@ export const Index: Record = { }, "p-navigation-1": { name: "p-navigation-1", - description: "Tabs-style segmented navigation", + description: "Segmented navigation built with links", type: "registry:block", registryDependencies: ["@coss/segmented-control"], files: [{ @@ -7209,7 +7209,7 @@ export const Index: Record = { }, "p-navigation-2": { name: "p-navigation-2", - description: "Small tabs-style segmented navigation", + description: "Small segmented navigation built with links", type: "registry:block", registryDependencies: ["@coss/segmented-control"], files: [{ @@ -7227,7 +7227,7 @@ export const Index: Record = { }, "p-navigation-3": { name: "p-navigation-3", - description: "Large tabs-style segmented navigation", + description: "Large segmented navigation built with links", type: "registry:block", registryDependencies: ["@coss/segmented-control"], files: [{ @@ -7551,7 +7551,7 @@ export const Index: Record = { }, "p-radio-group-7": { name: "p-radio-group-7", - description: "Small tabs-style segmented control", + description: "Small segmented control built with a radio group", type: "registry:block", registryDependencies: ["@coss/radio-group","@coss/segmented-control"], files: [{ @@ -7569,7 +7569,7 @@ export const Index: Record = { }, "p-radio-group-8": { name: "p-radio-group-8", - description: "Tabs-style segmented control", + description: "Segmented control built with a radio group", type: "registry:block", registryDependencies: ["@coss/radio-group","@coss/segmented-control"], files: [{ @@ -7587,7 +7587,7 @@ export const Index: Record = { }, "p-radio-group-9": { name: "p-radio-group-9", - description: "Large tabs-style segmented control", + description: "Large segmented control built with a radio group", type: "registry:block", registryDependencies: ["@coss/radio-group","@coss/segmented-control"], files: [{ @@ -8955,7 +8955,7 @@ export const Index: Record = { }, "p-tabs-1": { name: "p-tabs-1", - description: "Basic tabs", + description: "Segmented control built with tabs", type: "registry:block", registryDependencies: ["@coss/tabs"], files: [{ @@ -9189,7 +9189,7 @@ export const Index: Record = { }, "p-tabs-14": { name: "p-tabs-14", - description: "Small tabs", + description: "Small segmented control built with tabs", type: "registry:block", registryDependencies: ["@coss/tabs"], files: [{ @@ -9207,7 +9207,7 @@ export const Index: Record = { }, "p-tabs-15": { name: "p-tabs-15", - description: "Large tabs", + description: "Large segmented control built with tabs", type: "registry:block", registryDependencies: ["@coss/tabs"], files: [{ @@ -9891,7 +9891,7 @@ export const Index: Record = { }, "p-toggle-group-10": { name: "p-toggle-group-10", - description: "Small tabs-style filter toggles", + description: "Small segmented filter built with a toggle group", type: "registry:block", registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], files: [{ @@ -9909,7 +9909,7 @@ export const Index: Record = { }, "p-toggle-group-11": { name: "p-toggle-group-11", - description: "Tabs-style filter toggles", + description: "Segmented filter built with a toggle group", type: "registry:block", registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], files: [{ @@ -9927,7 +9927,7 @@ export const Index: Record = { }, "p-toggle-group-12": { name: "p-toggle-group-12", - description: "Large tabs-style filter toggles", + description: "Large segmented filter built with a toggle group", type: "registry:block", registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], files: [{ diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index 0bd2a7ffc..603c7fd4c 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -3956,7 +3956,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("navigation", "segmented control", "tabs"), - description: "Tabs-style segmented navigation", + description: "Segmented navigation built with links", files: [{ path: "particles/p-navigation-1.tsx", type: "registry:block" }], name: "p-navigation-1", registryDependencies: ["@coss/segmented-control"], @@ -3964,7 +3964,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("navigation", "segmented control", "tabs"), - description: "Small tabs-style segmented navigation", + description: "Small segmented navigation built with links", files: [{ path: "particles/p-navigation-2.tsx", type: "registry:block" }], name: "p-navigation-2", registryDependencies: ["@coss/segmented-control"], @@ -3972,7 +3972,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("navigation", "segmented control", "tabs"), - description: "Large tabs-style segmented navigation", + description: "Large segmented navigation built with links", files: [{ path: "particles/p-navigation-3.tsx", type: "registry:block" }], name: "p-navigation-3", registryDependencies: ["@coss/segmented-control"], @@ -4173,7 +4173,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("radio group", "segmented control", "tabs"), - description: "Small tabs-style segmented control", + description: "Small segmented control built with a radio group", files: [{ path: "particles/p-radio-group-7.tsx", type: "registry:block" }], name: "p-radio-group-7", registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], @@ -4181,7 +4181,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("radio group", "segmented control", "tabs"), - description: "Tabs-style segmented control", + description: "Segmented control built with a radio group", files: [{ path: "particles/p-radio-group-8.tsx", type: "registry:block" }], name: "p-radio-group-8", registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], @@ -4189,7 +4189,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("radio group", "segmented control", "tabs"), - description: "Large tabs-style segmented control", + description: "Large segmented control built with a radio group", files: [{ path: "particles/p-radio-group-9.tsx", type: "registry:block" }], name: "p-radio-group-9", registryDependencies: ["@coss/radio-group", "@coss/segmented-control"], @@ -5158,7 +5158,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("segmented control", "tabs"), - description: "Basic tabs", + description: "Segmented control built with tabs", files: [{ path: "particles/p-tabs-1.tsx", type: "registry:block" }], name: "p-tabs-1", registryDependencies: ["@coss/tabs"], @@ -5281,7 +5281,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("segmented control", "tabs"), - description: "Small tabs", + description: "Small segmented control built with tabs", files: [{ path: "particles/p-tabs-14.tsx", type: "registry:block" }], name: "p-tabs-14", registryDependencies: ["@coss/tabs"], @@ -5289,7 +5289,7 @@ export const particles: ParticleItem[] = [ }, { categories: categories("segmented control", "tabs"), - description: "Large tabs", + description: "Large segmented control built with tabs", files: [{ path: "particles/p-tabs-15.tsx", type: "registry:block" }], name: "p-tabs-15", registryDependencies: ["@coss/tabs"], @@ -5673,7 +5673,7 @@ export const particles: ParticleItem[] = [ "tabs", "filter", ), - description: "Small tabs-style filter toggles", + description: "Small segmented filter built with a toggle group", files: [ { path: "particles/p-toggle-group-10.tsx", type: "registry:block" }, ], @@ -5689,7 +5689,7 @@ export const particles: ParticleItem[] = [ "tabs", "filter", ), - description: "Tabs-style filter toggles", + description: "Segmented filter built with a toggle group", files: [ { path: "particles/p-toggle-group-11.tsx", type: "registry:block" }, ], @@ -5705,7 +5705,7 @@ export const particles: ParticleItem[] = [ "tabs", "filter", ), - description: "Large tabs-style filter toggles", + description: "Large segmented filter built with a toggle group", files: [ { path: "particles/p-toggle-group-12.tsx", type: "registry:block" }, ], From 6f3fce7f1da4f21475751a5e0e00e73b60d612ce Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:24:42 +0200 Subject: [PATCH 06/17] fix(ui): exclude tabs from segmented search --- apps/ui/public/r/p-tabs-1.json | 1 - apps/ui/public/r/p-tabs-14.json | 1 - apps/ui/public/r/p-tabs-15.json | 1 - apps/ui/public/r/registry.json | 3 --- apps/ui/registry.json | 3 --- apps/ui/registry/__index__.tsx | 6 +++--- apps/ui/registry/registry-particles.ts | 6 +++--- 7 files changed, 6 insertions(+), 15 deletions(-) diff --git a/apps/ui/public/r/p-tabs-1.json b/apps/ui/public/r/p-tabs-1.json index c58e629ec..5f219095b 100644 --- a/apps/ui/public/r/p-tabs-1.json +++ b/apps/ui/public/r/p-tabs-1.json @@ -13,7 +13,6 @@ } ], "categories": [ - "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-tabs-14.json b/apps/ui/public/r/p-tabs-14.json index 870253345..ba56c5454 100644 --- a/apps/ui/public/r/p-tabs-14.json +++ b/apps/ui/public/r/p-tabs-14.json @@ -13,7 +13,6 @@ } ], "categories": [ - "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/p-tabs-15.json b/apps/ui/public/r/p-tabs-15.json index b37366a86..4e23b4a39 100644 --- a/apps/ui/public/r/p-tabs-15.json +++ b/apps/ui/public/r/p-tabs-15.json @@ -13,7 +13,6 @@ } ], "categories": [ - "segmented control", "tabs" ], "type": "registry:block" diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index 7875804cc..e016cdbe2 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -10459,7 +10459,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Segmented control built with tabs", @@ -10717,7 +10716,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Small segmented control built with tabs", @@ -10735,7 +10733,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Large segmented control built with tabs", diff --git a/apps/ui/registry.json b/apps/ui/registry.json index 7875804cc..e016cdbe2 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -10459,7 +10459,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Segmented control built with tabs", @@ -10717,7 +10716,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Small segmented control built with tabs", @@ -10735,7 +10733,6 @@ }, { "categories": [ - "segmented control", "tabs" ], "description": "Large segmented control built with tabs", diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index addaf33c6..6199fe550 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -8968,7 +8968,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["segmented control","tabs"], + categories: ["tabs"], meta: undefined, }, "p-tabs-2": { @@ -9202,7 +9202,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["segmented control","tabs"], + categories: ["tabs"], meta: undefined, }, "p-tabs-15": { @@ -9220,7 +9220,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["segmented control","tabs"], + categories: ["tabs"], meta: undefined, }, "p-textarea-1": { diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index 603c7fd4c..15a999544 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -5157,7 +5157,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("segmented control", "tabs"), + categories: categories("tabs"), description: "Segmented control built with tabs", files: [{ path: "particles/p-tabs-1.tsx", type: "registry:block" }], name: "p-tabs-1", @@ -5280,7 +5280,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("segmented control", "tabs"), + categories: categories("tabs"), description: "Small segmented control built with tabs", files: [{ path: "particles/p-tabs-14.tsx", type: "registry:block" }], name: "p-tabs-14", @@ -5288,7 +5288,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("segmented control", "tabs"), + categories: categories("tabs"), description: "Large segmented control built with tabs", files: [{ path: "particles/p-tabs-15.tsx", type: "registry:block" }], name: "p-tabs-15", From 6edb584f61133f1cf0f0ab1ed033282b1029ae73 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:26:32 +0200 Subject: [PATCH 07/17] style(ui): remove segmented state transition --- apps/ui/public/r/segmented-control.json | 2 +- apps/ui/registry/default/lib/segmented-control.ts | 2 +- packages/ui/src/lib/segmented-control.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/segmented-control.json b/apps/ui/public/r/segmented-control.json index 51f426c03..5c0f96df5 100644 --- a/apps/ui/public/r/segmented-control.json +++ b/apps/ui/public/r/segmented-control.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/default/lib/segmented-control.ts", - "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", "type": "registry:lib" } ], diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts index b473912e6..b8a059a8b 100644 --- a/apps/ui/registry/default/lib/segmented-control.ts +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts index b473912e6..b8a059a8b 100644 --- a/packages/ui/src/lib/segmented-control.ts +++ b/packages/ui/src/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color,background-color,box-shadow] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", From 551c59afe701b03173a86f89b34244ff8105c117 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:28:20 +0200 Subject: [PATCH 08/17] fix(ui): require segmented radio selection --- apps/ui/public/r/p-radio-group-7.json | 2 +- apps/ui/public/r/p-radio-group-8.json | 2 +- apps/ui/public/r/p-radio-group-9.json | 2 +- apps/ui/registry/default/particles/p-radio-group-7.tsx | 1 + apps/ui/registry/default/particles/p-radio-group-8.tsx | 1 + apps/ui/registry/default/particles/p-radio-group-9.tsx | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/p-radio-group-7.json b/apps/ui/public/r/p-radio-group-7.json index 5dae42c62..a26aac52d 100644 --- a/apps/ui/public/r/p-radio-group-7.json +++ b/apps/ui/public/r/p-radio-group-7.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-7.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"sm\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"sm\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-radio-group-8.json b/apps/ui/public/r/p-radio-group-8.json index 022cb888e..3f571f668 100644 --- a/apps/ui/public/r/p-radio-group-8.json +++ b/apps/ui/public/r/p-radio-group-8.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-8.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-radio-group-9.json b/apps/ui/public/r/p-radio-group-9.json index 4b3e4a554..17f88a68e 100644 --- a/apps/ui/public/r/p-radio-group-9.json +++ b/apps/ui/public/r/p-radio-group-9.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-9.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"lg\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"lg\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/registry/default/particles/p-radio-group-7.tsx b/apps/ui/registry/default/particles/p-radio-group-7.tsx index 1e31a259c..78be629f9 100644 --- a/apps/ui/registry/default/particles/p-radio-group-7.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-7.tsx @@ -21,6 +21,7 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" + required > Monthly diff --git a/apps/ui/registry/default/particles/p-radio-group-8.tsx b/apps/ui/registry/default/particles/p-radio-group-8.tsx index 40683b050..19bda1651 100644 --- a/apps/ui/registry/default/particles/p-radio-group-8.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-8.tsx @@ -20,6 +20,7 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" + required > Monthly diff --git a/apps/ui/registry/default/particles/p-radio-group-9.tsx b/apps/ui/registry/default/particles/p-radio-group-9.tsx index 8c8ddab39..0a8f7bb7c 100644 --- a/apps/ui/registry/default/particles/p-radio-group-9.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-9.tsx @@ -21,6 +21,7 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" + required > Monthly From 84a08f9643e4ef5888358a0a09c86ecc491e185d Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:29:52 +0200 Subject: [PATCH 09/17] fix(ui): remove redundant radio requirement --- apps/ui/public/r/p-radio-group-7.json | 2 +- apps/ui/public/r/p-radio-group-8.json | 2 +- apps/ui/public/r/p-radio-group-9.json | 2 +- apps/ui/registry/default/particles/p-radio-group-7.tsx | 1 - apps/ui/registry/default/particles/p-radio-group-8.tsx | 1 - apps/ui/registry/default/particles/p-radio-group-9.tsx | 1 - 6 files changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/ui/public/r/p-radio-group-7.json b/apps/ui/public/r/p-radio-group-7.json index a26aac52d..5dae42c62 100644 --- a/apps/ui/public/r/p-radio-group-7.json +++ b/apps/ui/public/r/p-radio-group-7.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-7.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"sm\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"sm\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-radio-group-8.json b/apps/ui/public/r/p-radio-group-8.json index 3f571f668..022cb888e 100644 --- a/apps/ui/public/r/p-radio-group-8.json +++ b/apps/ui/public/r/p-radio-group-8.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-8.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-radio-group-9.json b/apps/ui/public/r/p-radio-group-9.json index 17f88a68e..4b3e4a554 100644 --- a/apps/ui/public/r/p-radio-group-9.json +++ b/apps/ui/public/r/p-radio-group-9.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-radio-group-9.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"lg\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n RadioGroupPrimitive,\n RadioPrimitive,\n} from \"@/registry/default/ui/radio-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n className: \"grow\",\n size: \"lg\",\n state: \"checked\",\n});\n\nexport default function Particle() {\n return (\n \n \n Monthly\n \n \n Yearly\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/registry/default/particles/p-radio-group-7.tsx b/apps/ui/registry/default/particles/p-radio-group-7.tsx index 78be629f9..1e31a259c 100644 --- a/apps/ui/registry/default/particles/p-radio-group-7.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-7.tsx @@ -21,7 +21,6 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" - required > Monthly diff --git a/apps/ui/registry/default/particles/p-radio-group-8.tsx b/apps/ui/registry/default/particles/p-radio-group-8.tsx index 19bda1651..40683b050 100644 --- a/apps/ui/registry/default/particles/p-radio-group-8.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-8.tsx @@ -20,7 +20,6 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" - required > Monthly diff --git a/apps/ui/registry/default/particles/p-radio-group-9.tsx b/apps/ui/registry/default/particles/p-radio-group-9.tsx index 0a8f7bb7c..8c8ddab39 100644 --- a/apps/ui/registry/default/particles/p-radio-group-9.tsx +++ b/apps/ui/registry/default/particles/p-radio-group-9.tsx @@ -21,7 +21,6 @@ export default function Particle() { aria-label="Billing period" className={segmentedControlRootClassName} defaultValue="monthly" - required > Monthly From 47ba9f80950b873a63ef5eddf7d85571d5377163 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:31:27 +0200 Subject: [PATCH 10/17] fix(ui): keep segmented toggle selected --- apps/ui/public/r/p-toggle-group-10.json | 2 +- apps/ui/public/r/p-toggle-group-11.json | 2 +- apps/ui/public/r/p-toggle-group-12.json | 2 +- apps/ui/registry/default/particles/p-toggle-group-10.tsx | 7 +++++++ apps/ui/registry/default/particles/p-toggle-group-11.tsx | 7 +++++++ apps/ui/registry/default/particles/p-toggle-group-12.tsx | 7 +++++++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json index 13f796de0..598df484a 100644 --- a/apps/ui/public/r/p-toggle-group-10.json +++ b/apps/ui/public/r/p-toggle-group-10.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-10.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n size=\"sm\"\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json index 554ba119b..5557b0c78 100644 --- a/apps/ui/public/r/p-toggle-group-11.json +++ b/apps/ui/public/r/p-toggle-group-11.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-11.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json index db35b415d..c66492f85 100644 --- a/apps/ui/public/r/p-toggle-group-12.json +++ b/apps/ui/public/r/p-toggle-group-12.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-12.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n size=\"lg\"\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/registry/default/particles/p-toggle-group-10.tsx b/apps/ui/registry/default/particles/p-toggle-group-10.tsx index 263a5a3fb..0aa90893f 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-10.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-10.tsx @@ -1,3 +1,5 @@ +"use client"; + import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -18,6 +20,11 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} + onValueChange={(value, eventDetails) => { + if (value.length === 0) { + eventDetails.cancel(); + } + }} size="sm" > diff --git a/apps/ui/registry/default/particles/p-toggle-group-11.tsx b/apps/ui/registry/default/particles/p-toggle-group-11.tsx index eb0bd13d2..59d687cec 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-11.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-11.tsx @@ -1,3 +1,5 @@ +"use client"; + import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -15,6 +17,11 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} + onValueChange={(value, eventDetails) => { + if (value.length === 0) { + eventDetails.cancel(); + } + }} > Open diff --git a/apps/ui/registry/default/particles/p-toggle-group-12.tsx b/apps/ui/registry/default/particles/p-toggle-group-12.tsx index 5cf497c09..52e0f97a6 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-12.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-12.tsx @@ -1,3 +1,5 @@ +"use client"; + import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -18,6 +20,11 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} + onValueChange={(value, eventDetails) => { + if (value.length === 0) { + eventDetails.cancel(); + } + }} size="lg" > From ef353de6dfa4fd0f99c3773777c3ec3bb14e732f Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:32:36 +0200 Subject: [PATCH 11/17] style(ui): preserve segmented text transition --- apps/ui/public/r/segmented-control.json | 2 +- apps/ui/registry/default/lib/segmented-control.ts | 2 +- packages/ui/src/lib/segmented-control.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/segmented-control.json b/apps/ui/public/r/segmented-control.json index 5c0f96df5..d8ab82856 100644 --- a/apps/ui/public/r/segmented-control.json +++ b/apps/ui/public/r/segmented-control.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/default/lib/segmented-control.ts", - "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", "type": "registry:lib" } ], diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts index b8a059a8b..171361229 100644 --- a/apps/ui/registry/default/lib/segmented-control.ts +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts index b8a059a8b..171361229 100644 --- a/packages/ui/src/lib/segmented-control.ts +++ b/packages/ui/src/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", From badf2fa992a65c39ecfef9001fded30e5838a660 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:33:35 +0200 Subject: [PATCH 12/17] revert(ui): allow empty segmented toggles --- apps/ui/public/r/p-toggle-group-10.json | 2 +- apps/ui/public/r/p-toggle-group-11.json | 2 +- apps/ui/public/r/p-toggle-group-12.json | 2 +- apps/ui/registry/default/particles/p-toggle-group-10.tsx | 7 ------- apps/ui/registry/default/particles/p-toggle-group-11.tsx | 7 ------- apps/ui/registry/default/particles/p-toggle-group-12.tsx | 7 ------- 6 files changed, 3 insertions(+), 24 deletions(-) diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json index 598df484a..13f796de0 100644 --- a/apps/ui/public/r/p-toggle-group-10.json +++ b/apps/ui/public/r/p-toggle-group-10.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-10.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n size=\"sm\"\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json index 5557b0c78..554ba119b 100644 --- a/apps/ui/public/r/p-toggle-group-11.json +++ b/apps/ui/public/r/p-toggle-group-11.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-11.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json index c66492f85..db35b415d 100644 --- a/apps/ui/public/r/p-toggle-group-12.json +++ b/apps/ui/public/r/p-toggle-group-12.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-toggle-group-12.tsx", - "content": "\"use client\";\n\nimport {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n {\n if (value.length === 0) {\n eventDetails.cancel();\n }\n }}\n size=\"lg\"\n >\n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", + "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/registry/default/particles/p-toggle-group-10.tsx b/apps/ui/registry/default/particles/p-toggle-group-10.tsx index 0aa90893f..263a5a3fb 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-10.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-10.tsx @@ -1,5 +1,3 @@ -"use client"; - import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -20,11 +18,6 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} - onValueChange={(value, eventDetails) => { - if (value.length === 0) { - eventDetails.cancel(); - } - }} size="sm" > diff --git a/apps/ui/registry/default/particles/p-toggle-group-11.tsx b/apps/ui/registry/default/particles/p-toggle-group-11.tsx index 59d687cec..eb0bd13d2 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-11.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-11.tsx @@ -1,5 +1,3 @@ -"use client"; - import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -17,11 +15,6 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} - onValueChange={(value, eventDetails) => { - if (value.length === 0) { - eventDetails.cancel(); - } - }} > Open diff --git a/apps/ui/registry/default/particles/p-toggle-group-12.tsx b/apps/ui/registry/default/particles/p-toggle-group-12.tsx index 52e0f97a6..5cf497c09 100644 --- a/apps/ui/registry/default/particles/p-toggle-group-12.tsx +++ b/apps/ui/registry/default/particles/p-toggle-group-12.tsx @@ -1,5 +1,3 @@ -"use client"; - import { segmentedControlItemVariants, segmentedControlRootClassName, @@ -20,11 +18,6 @@ export default function Particle() { aria-label="Filter issues" className={segmentedControlRootClassName} defaultValue={["open"]} - onValueChange={(value, eventDetails) => { - if (value.length === 0) { - eventDetails.cancel(); - } - }} size="lg" > From 3fb198d4196ba87cdc467a03cb38910c3a7fd81f Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:34:36 +0200 Subject: [PATCH 13/17] style(ui): remove segmented transitions --- apps/ui/public/r/segmented-control.json | 2 +- apps/ui/registry/default/lib/segmented-control.ts | 2 +- packages/ui/src/lib/segmented-control.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/segmented-control.json b/apps/ui/public/r/segmented-control.json index d8ab82856..5c0f96df5 100644 --- a/apps/ui/public/r/segmented-control.json +++ b/apps/ui/public/r/segmented-control.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/default/lib/segmented-control.ts", - "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", "type": "registry:lib" } ], diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts index 171361229..b8a059a8b 100644 --- a/apps/ui/registry/default/lib/segmented-control.ts +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts index 171361229..b8a059a8b 100644 --- a/packages/ui/src/lib/segmented-control.ts +++ b/packages/ui/src/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none transition-[color] hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", From f5fb5dfc6495bbc6c6bbe93253c2ec9405e4e9e5 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Mon, 17 Aug 2026 20:40:11 +0200 Subject: [PATCH 14/17] style(ui): isolate segmented focus transition --- apps/ui/public/r/segmented-control.json | 2 +- apps/ui/registry/default/lib/segmented-control.ts | 2 +- packages/ui/src/lib/segmented-control.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ui/public/r/segmented-control.json b/apps/ui/public/r/segmented-control.json index 5c0f96df5..472fb26f0 100644 --- a/apps/ui/public/r/segmented-control.json +++ b/apps/ui/public/r/segmented-control.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/default/lib/segmented-control.ts", - "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-2 outline-transparent transition-[outline-color] hover:bg-transparent hover:text-muted-foreground focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", "type": "registry:lib" } ], diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts index b8a059a8b..a229e9cd7 100644 --- a/apps/ui/registry/default/lib/segmented-control.ts +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-2 outline-transparent transition-[outline-color] hover:bg-transparent hover:text-muted-foreground focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts index b8a059a8b..a229e9cd7 100644 --- a/packages/ui/src/lib/segmented-control.ts +++ b/packages/ui/src/lib/segmented-control.ts @@ -15,7 +15,7 @@ export const segmentedControlRootClassName = "relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5"; export const segmentedControlItemVariants = cva( - "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-none hover:bg-transparent hover:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", + "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-2 outline-transparent transition-[outline-color] hover:bg-transparent hover:text-muted-foreground focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm", { defaultVariants: { size: "default", From 33ecb06f327c3e5c46f48dd3cff6c019703541a6 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Tue, 18 Aug 2026 16:05:29 +0200 Subject: [PATCH 15/17] fix(ui): refine segmented control spacing --- .../docs/components/segmented-control.mdx | 2 +- apps/ui/public/r/p-navigation-1.json | 3 +-- apps/ui/public/r/p-navigation-2.json | 3 +-- apps/ui/public/r/p-navigation-3.json | 3 +-- apps/ui/public/r/p-radio-group-7.json | 3 +-- apps/ui/public/r/p-radio-group-8.json | 3 +-- apps/ui/public/r/p-radio-group-9.json | 3 +-- apps/ui/public/r/p-toggle-group-10.json | 1 - apps/ui/public/r/p-toggle-group-11.json | 1 - apps/ui/public/r/p-toggle-group-12.json | 1 - apps/ui/public/r/registry.json | 21 ++++++------------- apps/ui/public/r/segmented-control.json | 2 +- apps/ui/registry.json | 21 ++++++------------- apps/ui/registry/__index__.tsx | 18 ++++++++-------- .../registry/default/lib/segmented-control.ts | 6 +++--- apps/ui/registry/registry-particles.ts | 15 ++++++------- packages/ui/src/lib/segmented-control.ts | 6 +++--- 17 files changed, 41 insertions(+), 71 deletions(-) diff --git a/apps/ui/content/docs/components/segmented-control.mdx b/apps/ui/content/docs/components/segmented-control.mdx index cb9eb29fb..87ee17330 100644 --- a/apps/ui/content/docs/components/segmented-control.mdx +++ b/apps/ui/content/docs/components/segmented-control.mdx @@ -69,7 +69,7 @@ const itemClassName = segmentedControlItemVariants({ Use `checked` with Radio Group, `current` with navigation links, and `pressed` with Toggle Group. Tabs retain their own animated indicator and do not use the shared state recipe. -Each size uses the horizontal padding of the corresponding Button size. The outer segmented surface is slightly taller than that Button to optically balance its inset selected item when the controls appear next to each other. +At the outside edges, the item padding and the surface's `p-0.5` inset combine to match the horizontal padding of the corresponding Button size. The outer segmented surface is slightly taller than that Button to optically balance its inset selected item when the controls appear next to each other. = {\n default: \"h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-2 outline-transparent transition-[outline-color] hover:bg-transparent hover:text-muted-foreground focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", + "content": "import { cva } from \"class-variance-authority\";\n\nexport type SegmentedControlSize = \"default\" | \"lg\" | \"sm\";\n\nexport const segmentedControlItemSizeClassNames: Record<\n SegmentedControlSize,\n string\n> = {\n default: \"h-8.5 px-[calc(--spacing(2.5)-1px)] sm:h-7.5\",\n lg: \"h-9.5 px-[calc(--spacing(3)-1px)] sm:h-8.5\",\n sm: \"h-7.5 px-[calc(--spacing(2)-1px)] sm:h-6.5\",\n};\n\nexport const segmentedControlRootClassName =\n \"relative z-0 flex w-fit items-center justify-center gap-0.5 rounded-lg bg-muted p-0.5\";\n\nexport const segmentedControlItemVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium text-base text-muted-foreground/72 outline-2 outline-transparent transition-[outline-color] hover:bg-transparent hover:text-muted-foreground focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm\",\n {\n defaultVariants: {\n size: \"default\",\n },\n variants: {\n size: segmentedControlItemSizeClassNames,\n state: {\n checked:\n \"data-checked:bg-background data-checked:text-foreground data-checked:shadow-sm/5 dark:data-checked:bg-input\",\n current:\n \"aria-[current=page]:bg-background aria-[current=page]:text-foreground aria-[current=page]:shadow-sm/5 dark:aria-[current=page]:bg-input\",\n pressed:\n \"data-pressed:bg-background data-pressed:text-foreground data-pressed:shadow-sm/5 dark:data-pressed:bg-input\",\n },\n },\n },\n);\n", "type": "registry:lib" } ], diff --git a/apps/ui/registry.json b/apps/ui/registry.json index e016cdbe2..38ee6acd6 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -8353,8 +8353,7 @@ { "categories": [ "navigation", - "segmented control", - "tabs" + "segmented control" ], "description": "Segmented navigation built with links", "files": [ @@ -8372,8 +8371,7 @@ { "categories": [ "navigation", - "segmented control", - "tabs" + "segmented control" ], "description": "Small segmented navigation built with links", "files": [ @@ -8391,8 +8389,7 @@ { "categories": [ "navigation", - "segmented control", - "tabs" + "segmented control" ], "description": "Large segmented navigation built with links", "files": [ @@ -8773,8 +8770,7 @@ { "categories": [ "radio group", - "segmented control", - "tabs" + "segmented control" ], "description": "Small segmented control built with a radio group", "files": [ @@ -8793,8 +8789,7 @@ { "categories": [ "radio group", - "segmented control", - "tabs" + "segmented control" ], "description": "Segmented control built with a radio group", "files": [ @@ -8813,8 +8808,7 @@ { "categories": [ "radio group", - "segmented control", - "tabs" + "segmented control" ], "description": "Large segmented control built with a radio group", "files": [ @@ -11488,7 +11482,6 @@ "toggle", "toggle group", "segmented control", - "tabs", "filter" ], "description": "Small segmented filter built with a toggle group", @@ -11510,7 +11503,6 @@ "toggle", "toggle group", "segmented control", - "tabs", "filter" ], "description": "Segmented filter built with a toggle group", @@ -11532,7 +11524,6 @@ "toggle", "toggle group", "segmented control", - "tabs", "filter" ], "description": "Large segmented filter built with a toggle group", diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index 6199fe550..b1175b9a7 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -7204,7 +7204,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","segmented control","tabs"], + categories: ["navigation","segmented control"], meta: undefined, }, "p-navigation-2": { @@ -7222,7 +7222,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","segmented control","tabs"], + categories: ["navigation","segmented control"], meta: undefined, }, "p-navigation-3": { @@ -7240,7 +7240,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["navigation","segmented control","tabs"], + categories: ["navigation","segmented control"], meta: undefined, }, "p-pagination-1": { @@ -7564,7 +7564,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","segmented control","tabs"], + categories: ["radio group","segmented control"], meta: undefined, }, "p-radio-group-8": { @@ -7582,7 +7582,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","segmented control","tabs"], + categories: ["radio group","segmented control"], meta: undefined, }, "p-radio-group-9": { @@ -7600,7 +7600,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["radio group","segmented control","tabs"], + categories: ["radio group","segmented control"], meta: undefined, }, "p-scroll-area-1": { @@ -9904,7 +9904,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","segmented control","tabs","filter"], + categories: ["toggle","toggle group","segmented control","filter"], meta: undefined, }, "p-toggle-group-11": { @@ -9922,7 +9922,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","segmented control","tabs","filter"], + categories: ["toggle","toggle group","segmented control","filter"], meta: undefined, }, "p-toggle-group-12": { @@ -9940,7 +9940,7 @@ export const Index: Record = { const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name return { default: mod.default || mod[exportName] } }), - categories: ["toggle","toggle group","segmented control","tabs","filter"], + categories: ["toggle","toggle group","segmented control","filter"], meta: undefined, }, "p-toggle-1": { diff --git a/apps/ui/registry/default/lib/segmented-control.ts b/apps/ui/registry/default/lib/segmented-control.ts index a229e9cd7..bcef88500 100644 --- a/apps/ui/registry/default/lib/segmented-control.ts +++ b/apps/ui/registry/default/lib/segmented-control.ts @@ -6,9 +6,9 @@ export const segmentedControlItemSizeClassNames: Record< SegmentedControlSize, string > = { - default: "h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5", - lg: "h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5", - sm: "h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5", + default: "h-8.5 px-[calc(--spacing(2.5)-1px)] sm:h-7.5", + lg: "h-9.5 px-[calc(--spacing(3)-1px)] sm:h-8.5", + sm: "h-7.5 px-[calc(--spacing(2)-1px)] sm:h-6.5", }; export const segmentedControlRootClassName = diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index 15a999544..b56910589 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -3955,7 +3955,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "segmented control", "tabs"), + categories: categories("navigation", "segmented control"), description: "Segmented navigation built with links", files: [{ path: "particles/p-navigation-1.tsx", type: "registry:block" }], name: "p-navigation-1", @@ -3963,7 +3963,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "segmented control", "tabs"), + categories: categories("navigation", "segmented control"), description: "Small segmented navigation built with links", files: [{ path: "particles/p-navigation-2.tsx", type: "registry:block" }], name: "p-navigation-2", @@ -3971,7 +3971,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("navigation", "segmented control", "tabs"), + categories: categories("navigation", "segmented control"), description: "Large segmented navigation built with links", files: [{ path: "particles/p-navigation-3.tsx", type: "registry:block" }], name: "p-navigation-3", @@ -4172,7 +4172,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "segmented control", "tabs"), + categories: categories("radio group", "segmented control"), description: "Small segmented control built with a radio group", files: [{ path: "particles/p-radio-group-7.tsx", type: "registry:block" }], name: "p-radio-group-7", @@ -4180,7 +4180,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "segmented control", "tabs"), + categories: categories("radio group", "segmented control"), description: "Segmented control built with a radio group", files: [{ path: "particles/p-radio-group-8.tsx", type: "registry:block" }], name: "p-radio-group-8", @@ -4188,7 +4188,7 @@ export const particles: ParticleItem[] = [ type: "registry:block", }, { - categories: categories("radio group", "segmented control", "tabs"), + categories: categories("radio group", "segmented control"), description: "Large segmented control built with a radio group", files: [{ path: "particles/p-radio-group-9.tsx", type: "registry:block" }], name: "p-radio-group-9", @@ -5670,7 +5670,6 @@ export const particles: ParticleItem[] = [ "toggle", "toggle group", "segmented control", - "tabs", "filter", ), description: "Small segmented filter built with a toggle group", @@ -5686,7 +5685,6 @@ export const particles: ParticleItem[] = [ "toggle", "toggle group", "segmented control", - "tabs", "filter", ), description: "Segmented filter built with a toggle group", @@ -5702,7 +5700,6 @@ export const particles: ParticleItem[] = [ "toggle", "toggle group", "segmented control", - "tabs", "filter", ), description: "Large segmented filter built with a toggle group", diff --git a/packages/ui/src/lib/segmented-control.ts b/packages/ui/src/lib/segmented-control.ts index a229e9cd7..bcef88500 100644 --- a/packages/ui/src/lib/segmented-control.ts +++ b/packages/ui/src/lib/segmented-control.ts @@ -6,9 +6,9 @@ export const segmentedControlItemSizeClassNames: Record< SegmentedControlSize, string > = { - default: "h-8.5 px-[calc(--spacing(3)-1px)] sm:h-7.5", - lg: "h-9.5 px-[calc(--spacing(3.5)-1px)] sm:h-8.5", - sm: "h-7.5 px-[calc(--spacing(2.5)-1px)] sm:h-6.5", + default: "h-8.5 px-[calc(--spacing(2.5)-1px)] sm:h-7.5", + lg: "h-9.5 px-[calc(--spacing(3)-1px)] sm:h-8.5", + sm: "h-7.5 px-[calc(--spacing(2)-1px)] sm:h-6.5", }; export const segmentedControlRootClassName = From d21958d1b8d9d10f50f1b53f3ad02b1bff023451 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Tue, 18 Aug 2026 16:43:27 +0200 Subject: [PATCH 16/17] docs(skills): add segmented control guidance --- apps/ui/skills/coss-particles/SKILL.md | 23 ++++++-- apps/ui/skills/coss/SKILL.md | 4 +- .../coss/references/component-registry.md | 3 + .../coss/references/primitives/radio-group.md | 4 +- .../skills/coss/references/primitives/tabs.md | 20 +++++-- .../references/primitives/toggle-group.md | 5 +- .../coss/references/segmented-control.md | 59 +++++++++++++++++++ 7 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 apps/ui/skills/coss/references/segmented-control.md diff --git a/apps/ui/skills/coss-particles/SKILL.md b/apps/ui/skills/coss-particles/SKILL.md index 19f5c4a8c..9d91d0d33 100644 --- a/apps/ui/skills/coss-particles/SKILL.md +++ b/apps/ui/skills/coss-particles/SKILL.md @@ -37,7 +37,7 @@ Run the generator script from the coss repo root: node apps/ui/scripts/generate-particle-index.cjs ``` -Total: **484 particles** across **52 component types** +Total: **495 particles** across **53 component types** ## Component types @@ -70,13 +70,14 @@ Total: **484 particles** across **52 component types** - [kbd](#kbd) (1) - [menu](#menu) (9) - [meter](#meter) (4) +- [navigation](#navigation) (3) - [number-field](#number-field) (11) - [otp-field](#otp-field) (9) - [pagination](#pagination) (3) - [popover](#popover) (3) - [preview-card](#preview-card) (1) - [progress](#progress) (3) -- [radio-group](#radio-group) (6) +- [radio-group](#radio-group) (9) - [scroll-area](#scroll-area) (5) - [select](#select) (23) - [separator](#separator) (1) @@ -86,11 +87,11 @@ Total: **484 particles** across **52 component types** - [spinner](#spinner) (1) - [switch](#switch) (6) - [table](#table) (8) -- [tabs](#tabs) (13) +- [tabs](#tabs) (15) - [textarea](#textarea) (15) - [toast](#toast) (13) - [toggle](#toggle) (8) -- [toggle-group](#toggle-group) (9) +- [toggle-group](#toggle-group) (12) - [toolbar](#toolbar) (1) - [tooltip](#tooltip) (4) @@ -496,6 +497,12 @@ Total: **484 particles** across **52 component types** - Meter with formatted value | [JSON](https://coss.com/ui/r/p-meter-3.json) - Meter with range | [JSON](https://coss.com/ui/r/p-meter-4.json) +### navigation + +- Segmented navigation built with links | [JSON](https://coss.com/ui/r/p-navigation-1.json) +- Small segmented navigation built with links | [JSON](https://coss.com/ui/r/p-navigation-2.json) +- Large segmented navigation built with links | [JSON](https://coss.com/ui/r/p-navigation-3.json) + ### number-field - Basic number field | [JSON](https://coss.com/ui/r/p-number-field-1.json) @@ -552,6 +559,9 @@ Total: **484 particles** across **52 component types** - Radio group card | [JSON](https://coss.com/ui/r/p-radio-group-4.json) - Radio group in form | [JSON](https://coss.com/ui/r/p-radio-group-5.json) - Theme selector with image cards | [JSON](https://coss.com/ui/r/p-radio-group-6.json) +- Small segmented control built with a radio group | [JSON](https://coss.com/ui/r/p-radio-group-7.json) +- Segmented control built with a radio group | [JSON](https://coss.com/ui/r/p-radio-group-8.json) +- Large segmented control built with a radio group | [JSON](https://coss.com/ui/r/p-radio-group-9.json) ### scroll-area @@ -667,6 +677,8 @@ Total: **484 particles** across **52 component types** - Vertical tabs with underline and icon before name | [JSON](https://coss.com/ui/r/p-tabs-11.json) - Tabs with icon only and count badge | [JSON](https://coss.com/ui/r/p-tabs-12.json) - Tabs with icon only and grouped tooltips | [JSON](https://coss.com/ui/r/p-tabs-13.json) +- Small segmented control built with tabs | [JSON](https://coss.com/ui/r/p-tabs-14.json) +- Large segmented control built with tabs | [JSON](https://coss.com/ui/r/p-tabs-15.json) ### textarea @@ -724,6 +736,9 @@ Total: **484 particles** across **52 component types** - Toggle group with disabled item | [JSON](https://coss.com/ui/r/p-toggle-group-7.json) - Multiple selection toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-8.json) - Toggle group with tooltips | [JSON](https://coss.com/ui/r/p-toggle-group-9.json) +- Small segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-10.json) +- Segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-11.json) +- Large segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-12.json) ### toolbar diff --git a/apps/ui/skills/coss/SKILL.md b/apps/ui/skills/coss/SKILL.md index 8cbda0751..c17ca3053 100644 --- a/apps/ui/skills/coss/SKILL.md +++ b/apps/ui/skills/coss/SKILL.md @@ -1,6 +1,6 @@ --- name: coss -description: Helps implement coss UI components correctly. Use when building UIs with coss primitives (buttons, dialogs, selects, forms, menus, tabs, inputs, toasts, etc.), migrating from shadcn/Radix to coss/Base UI, composing trigger-based overlays, or troubleshooting coss component behavior. Covers imports, accessibility, Tailwind styling, and common pitfalls. +description: Helps implement coss UI components correctly. Use when building UIs with coss primitives and patterns (buttons, dialogs, selects, forms, menus, tabs, segmented controls, inputs, toasts, etc.), migrating from shadcn/Radix to coss/Base UI, composing trigger-based overlays, or troubleshooting coss component behavior. Covers imports, accessibility, Tailwind styling, and common pitfalls. compatibility: Requires Tailwind CSS v4 and @base-ui/react. Designed for React projects using the coss component registry. license: MIT metadata: @@ -60,6 +60,7 @@ Rule references (read on demand when the task touches these areas): - `./references/rules/forms.md` — Field composition, validation, input patterns - `./references/rules/composition.md` — Trigger/popup hierarchies, grouped controls - `./references/rules/migration.md` — shadcn/Radix to coss/Base UI migration patterns +- `./references/segmented-control.md` — choose Radio Group, links, Toggle Group, or Tabs before applying segmented-control styling - `./references/portal-props.md` — optional `portalProps` on composed popups and toast providers (`keepMounted`, `container`, which surfaces support it) ## Component discovery @@ -115,4 +116,3 @@ Before returning code: - composition structure is valid for selected primitive(s) - accessibility and explicit control types (`button`, `input`, etc.) are present - migration-sensitive flows are verified (type/lint, keyboard/a11y behavior, and SSR-sensitive primitives like Select/Command) - diff --git a/apps/ui/skills/coss/references/component-registry.md b/apps/ui/skills/coss/references/component-registry.md index 1a3a2b291..9fd564bce 100644 --- a/apps/ui/skills/coss/references/component-registry.md +++ b/apps/ui/skills/coss/references/component-registry.md @@ -4,6 +4,9 @@ Use this file to quickly identify the right coss primitive for a UI task. Each e For optional **`portalProps`** on composed `*Popup` components and **toast** providers (Base UI portal forwarding), see `./references/portal-props.md`. +## Cross-component patterns +- **Segmented Control** — Shared visual treatment for radio choices, navigation links, exclusive toggles, or tabbed panels; choose semantics first. `./references/segmented-control.md` + ## Overlays & Popups - **Dialog** — Centered modal requiring user focus. `./references/primitives/dialog.md` - **AlertDialog** — Destructive/critical confirmation modal. `./references/primitives/alert-dialog.md` diff --git a/apps/ui/skills/coss/references/primitives/radio-group.md b/apps/ui/skills/coss/references/primitives/radio-group.md index d7ff91391..001a06158 100644 --- a/apps/ui/skills/coss/references/primitives/radio-group.md +++ b/apps/ui/skills/coss/references/primitives/radio-group.md @@ -10,6 +10,7 @@ - If multiple options can be selected -> use CheckboxGroup instead. - If options are many and need search/filtering -> use Select or Combobox instead. - If the choices are binary (on/off) -> use Switch or Checkbox instead. +- If each option reveals a content panel rather than selecting a value -> use Tabs instead. ## Install @@ -85,7 +86,7 @@ const [value, setValue] = useState("default") ### More examples -See `p-radio-group-1` through `p-radio-group-5` for disabled, description, card-style, and form integration patterns. +See `p-radio-group-1` through `p-radio-group-5` for disabled, description, card-style, and form integration patterns. For a segmented presentation, use `p-radio-group-7`, `p-radio-group-8`, or `p-radio-group-9`; read `../segmented-control.md` before choosing the underlying primitive. ## Common pitfalls @@ -99,4 +100,5 @@ See `p-radio-group-1` through `p-radio-group-5` for disabled, description, card- - with description: `p-radio-group-3` - card style: `p-radio-group-4` - form integration: `p-radio-group-5` +- segmented, small/default/large: `p-radio-group-7`, `p-radio-group-8`, `p-radio-group-9` - form composition references: `p-form-1`, `p-form-2`, `p-input-group-24` diff --git a/apps/ui/skills/coss/references/primitives/tabs.md b/apps/ui/skills/coss/references/primitives/tabs.md index 769e700e1..350a852c7 100644 --- a/apps/ui/skills/coss/references/primitives/tabs.md +++ b/apps/ui/skills/coss/references/primitives/tabs.md @@ -14,9 +14,11 @@ npx shadcn@latest add @coss/tabs Manual deps from docs: ```bash -# No extra runtime dependency required for this primitive. +npm install @base-ui/react class-variance-authority ``` +The CLI installs the shared `@coss/segmented-control` registry dependency automatically. For a manual installation, also copy `lib/segmented-control.ts` before copying the Tabs component. + ## Canonical imports ```tsx @@ -57,11 +59,20 @@ const [value, setValue] = useState("tab-1") ``` +Sizes are set on `TabsList` and inherited by its tabs. An individual `TabsTab` can override the inherited size. + +```tsx + + Tab 1 + Tab 2 + +``` + Underline variant: ```tsx - - + + Tab 1 Tab 2 @@ -79,8 +90,9 @@ Underline variant: - Mismatching `TabsTab value` and `TabsPanel value` pairs. - Using tabs for workflows that require route-level navigation instead. +- Using tabs for a form value or reversible filter just because it looks like a segmented control. Read `../segmented-control.md` and choose semantics first. - Mounting expensive panel content without considering visibility/performance. ## Useful particle references -See `p-tabs-1` through `p-tabs-4` for variants and orientations. Related: `p-toolbar-1`, `p-card-1`. +See `p-tabs-1` through `p-tabs-4` for variants and orientations, plus `p-tabs-14` and `p-tabs-15` for small and large segmented Tabs. Related: `p-toolbar-1`, `p-card-1`. diff --git a/apps/ui/skills/coss/references/primitives/toggle-group.md b/apps/ui/skills/coss/references/primitives/toggle-group.md index 45d6ff556..d4568a60e 100644 --- a/apps/ui/skills/coss/references/primitives/toggle-group.md +++ b/apps/ui/skills/coss/references/primitives/toggle-group.md @@ -53,7 +53,7 @@ Toggle group with icon buttons: ``` -Multiple selection (default). For single selection use `type="single"`. +Toggle Group is exclusive by default and may be cleared. Add `multiple` only when more than one item may be pressed. Controlled toggle group: @@ -68,7 +68,7 @@ const [value, setValue] = useState(["bold"]) ### More examples -See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, disabled, multiple, and tooltip patterns. +See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, disabled, multiple, and tooltip patterns. For an exclusive segmented filter or mode, use `p-toggle-group-10`, `p-toggle-group-11`, or `p-toggle-group-12`; read `../segmented-control.md` before choosing the underlying primitive. ## Common pitfalls @@ -86,3 +86,4 @@ See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, - with disabled toggle: `p-toggle-group-7` - multiple selection: `p-toggle-group-8` - with tooltips: `p-toggle-group-9` +- segmented filter, small/default/large: `p-toggle-group-10`, `p-toggle-group-11`, `p-toggle-group-12` diff --git a/apps/ui/skills/coss/references/segmented-control.md b/apps/ui/skills/coss/references/segmented-control.md new file mode 100644 index 000000000..ff53e0b58 --- /dev/null +++ b/apps/ui/skills/coss/references/segmented-control.md @@ -0,0 +1,59 @@ +# coss Segmented Control Pattern + +A segmented control is a shared visual treatment, not a standalone behavior. Choose the underlying primitive from the interaction before applying the styling. + +## Choose the behavior + +| Intent | Use | State model | +| --- | --- | --- | +| Choose one value, especially in a form | Radio Group | Exactly one mutually exclusive value | +| Navigate to another URL or route | Links | Browser navigation with `aria-current="page"` on the current link | +| Apply an exclusive filter or reversible mode | Toggle Group | At most one pressed item by default; the current item may be cleared | +| Switch between associated content panels | Tabs | Each tab controls a matching panel | + +Do not use Tabs for navigation links, form values, or filters merely because the result should look segmented. Do not use Toggle Group when one value must always remain selected; use Radio Group instead. + +## Install a particle + +| Implementation | Small | Default | Large | +| --- | --- | --- | --- | +| Radio Group | `@coss/p-radio-group-7` | `@coss/p-radio-group-8` | `@coss/p-radio-group-9` | +| Navigation links | `@coss/p-navigation-2` | `@coss/p-navigation-1` | `@coss/p-navigation-3` | +| Toggle Group | `@coss/p-toggle-group-10` | `@coss/p-toggle-group-11` | `@coss/p-toggle-group-12` | + +The CLI installs the relevant primitive and the shared `@coss/segmented-control` styling library automatically. + +## Custom composition + +Install the styling library directly when none of the particles matches: + +```bash +npx shadcn@latest add @coss/segmented-control +``` + +```tsx +import { + segmentedControlItemVariants, + segmentedControlRootClassName, +} from "@/lib/segmented-control" +``` + +Apply `segmentedControlRootClassName` to the group surface. Generate one item class with the matching state selector: + +```tsx +const itemClassName = segmentedControlItemVariants({ + size: "default", + state: "checked", +}) +``` + +- `state: "checked"` for Radio Group +- `state: "current"` for navigation links +- `state: "pressed"` for Toggle Group +- `size: "sm" | "default" | "lg"` + +Use the exported Radio Group primitives for a custom segmented radio presentation so the native radio indicator is not rendered. Keep a default or controlled value when the interface requires one option to remain selected. + +Tabs do not use the shared state recipe because they retain their animated indicator. They import the shared size map: set `size="sm" | "default" | "lg"` on `TabsList`, and use a `TabsTab` size only as an item-level override. + +Reuse the shared root and item recipes instead of copying their classes into a new segmented particle. This keeps Tabs and the radio, navigation, and toggle implementations optically aligned. From 6ce88ec0ba3d1218df6a51b2cf307aebc2e7cfd1 Mon Sep 17 00:00:00 2001 From: pasqualevitiello Date: Tue, 18 Aug 2026 16:47:16 +0200 Subject: [PATCH 17/17] refactor(ui): remove segmented toggle particles --- .../docs/components/segmented-control.mdx | 17 ----- .../content/docs/components/toggle-group.mdx | 2 - apps/ui/public/r/p-toggle-group-10.json | 23 ------- apps/ui/public/r/p-toggle-group-11.json | 23 ------- apps/ui/public/r/p-toggle-group-12.json | 23 ------- apps/ui/public/r/registry.json | 63 ------------------- apps/ui/registry.json | 63 ------------------- apps/ui/registry/__index__.tsx | 54 ---------------- .../default/particles/p-toggle-group-10.tsx | 34 ---------- .../default/particles/p-toggle-group-11.tsx | 30 --------- .../default/particles/p-toggle-group-12.tsx | 34 ---------- apps/ui/registry/registry-particles.ts | 45 ------------- apps/ui/skills/coss-particles/SKILL.md | 8 +-- .../references/primitives/toggle-group.md | 3 +- .../coss/references/segmented-control.md | 3 +- 15 files changed, 5 insertions(+), 420 deletions(-) delete mode 100644 apps/ui/public/r/p-toggle-group-10.json delete mode 100644 apps/ui/public/r/p-toggle-group-11.json delete mode 100644 apps/ui/public/r/p-toggle-group-12.json delete mode 100644 apps/ui/registry/default/particles/p-toggle-group-10.tsx delete mode 100644 apps/ui/registry/default/particles/p-toggle-group-11.tsx delete mode 100644 apps/ui/registry/default/particles/p-toggle-group-12.tsx diff --git a/apps/ui/content/docs/components/segmented-control.mdx b/apps/ui/content/docs/components/segmented-control.mdx index 87ee17330..9ccbf2113 100644 --- a/apps/ui/content/docs/components/segmented-control.mdx +++ b/apps/ui/content/docs/components/segmented-control.mdx @@ -28,7 +28,6 @@ Segmented controls are provided as particles. Install the implementation and siz | -------------- | ----- | ------- | ----- | | Radio Group | `@coss/p-radio-group-7` | `@coss/p-radio-group-8` | `@coss/p-radio-group-9` | | Navigation | `@coss/p-navigation-2` | `@coss/p-navigation-1` | `@coss/p-navigation-3` | -| Toggle Group | `@coss/p-toggle-group-10` | `@coss/p-toggle-group-11` | `@coss/p-toggle-group-12` | For example, install the default Radio Group version with: @@ -108,22 +107,6 @@ Use links when each segment points to a different destination. Apply `aria-curre -## Filters and modes - -Use a single-selection Toggle Group when segments apply a filter, view, or reversible mode. Use Radio Group instead when one value must always remain selected. - -### Small Toggle Group - - - -### Default Toggle Group - - - -### Large Toggle Group - - - ## Related content Use Tabs when each segment controls an associated content panel. Tabs share the visual language of segmented controls but keep their animated indicator, orientation support, and panel semantics. diff --git a/apps/ui/content/docs/components/toggle-group.mdx b/apps/ui/content/docs/components/toggle-group.mdx index f42fe9219..fd22c6c27 100644 --- a/apps/ui/content/docs/components/toggle-group.mdx +++ b/apps/ui/content/docs/components/toggle-group.mdx @@ -78,8 +78,6 @@ Visual separator between toggle buttons. ## Examples -For tabs-style filters and modes, see the [Segmented Control](/ui/docs/components/segmented-control) pattern. - ### Small Toggles diff --git a/apps/ui/public/r/p-toggle-group-10.json b/apps/ui/public/r/p-toggle-group-10.json deleted file mode 100644 index e15b9de5f..000000000 --- a/apps/ui/public/r/p-toggle-group-10.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema/registry-item.json", - "name": "p-toggle-group-10", - "description": "Small segmented filter built with a toggle group", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "files": [ - { - "path": "registry/default/particles/p-toggle-group-10.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"sm\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", - "type": "registry:block" - } - ], - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "type": "registry:block" -} \ No newline at end of file diff --git a/apps/ui/public/r/p-toggle-group-11.json b/apps/ui/public/r/p-toggle-group-11.json deleted file mode 100644 index 451992b1d..000000000 --- a/apps/ui/public/r/p-toggle-group-11.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema/registry-item.json", - "name": "p-toggle-group-11", - "description": "Segmented filter built with a toggle group", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "files": [ - { - "path": "registry/default/particles/p-toggle-group-11.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({ state: \"pressed\" });\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", - "type": "registry:block" - } - ], - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "type": "registry:block" -} \ No newline at end of file diff --git a/apps/ui/public/r/p-toggle-group-12.json b/apps/ui/public/r/p-toggle-group-12.json deleted file mode 100644 index 5fe633a3c..000000000 --- a/apps/ui/public/r/p-toggle-group-12.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema/registry-item.json", - "name": "p-toggle-group-12", - "description": "Large segmented filter built with a toggle group", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "files": [ - { - "path": "registry/default/particles/p-toggle-group-12.tsx", - "content": "import {\n segmentedControlItemVariants,\n segmentedControlRootClassName,\n} from \"@/registry/default/lib/segmented-control\";\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nconst itemClassName = segmentedControlItemVariants({\n size: \"lg\",\n state: \"pressed\",\n});\n\nexport default function Particle() {\n return (\n \n \n Open\n \n \n Assigned\n \n \n Urgent\n \n \n );\n}\n", - "type": "registry:block" - } - ], - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "type": "registry:block" -} \ No newline at end of file diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index 38ee6acd6..c8034a72a 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -11477,69 +11477,6 @@ ], "type": "registry:block" }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Small segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-10.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-10", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-11.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-11", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Large segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-12.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-12", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, { "categories": [ "toggle" diff --git a/apps/ui/registry.json b/apps/ui/registry.json index 38ee6acd6..c8034a72a 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -11477,69 +11477,6 @@ ], "type": "registry:block" }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Small segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-10.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-10", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-11.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-11", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, - { - "categories": [ - "toggle", - "toggle group", - "segmented control", - "filter" - ], - "description": "Large segmented filter built with a toggle group", - "files": [ - { - "path": "registry/default/particles/p-toggle-group-12.tsx", - "type": "registry:block" - } - ], - "name": "p-toggle-group-12", - "registryDependencies": [ - "@coss/segmented-control", - "@coss/toggle-group" - ], - "type": "registry:block" - }, { "categories": [ "toggle" diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index b1175b9a7..7e3b89b7c 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -9889,60 +9889,6 @@ export const Index: Record = { categories: ["toggle","toggle group"], meta: undefined, }, - "p-toggle-group-10": { - name: "p-toggle-group-10", - description: "Small segmented filter built with a toggle group", - type: "registry:block", - registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], - files: [{ - path: "registry/default/particles/p-toggle-group-10.tsx", - type: "registry:block", - target: "" - }], - component: React.lazy(async () => { - const mod = await import("@/registry/default/particles/p-toggle-group-10.tsx") - const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name - return { default: mod.default || mod[exportName] } - }), - categories: ["toggle","toggle group","segmented control","filter"], - meta: undefined, - }, - "p-toggle-group-11": { - name: "p-toggle-group-11", - description: "Segmented filter built with a toggle group", - type: "registry:block", - registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], - files: [{ - path: "registry/default/particles/p-toggle-group-11.tsx", - type: "registry:block", - target: "" - }], - component: React.lazy(async () => { - const mod = await import("@/registry/default/particles/p-toggle-group-11.tsx") - const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name - return { default: mod.default || mod[exportName] } - }), - categories: ["toggle","toggle group","segmented control","filter"], - meta: undefined, - }, - "p-toggle-group-12": { - name: "p-toggle-group-12", - description: "Large segmented filter built with a toggle group", - type: "registry:block", - registryDependencies: ["@coss/segmented-control","@coss/toggle-group"], - files: [{ - path: "registry/default/particles/p-toggle-group-12.tsx", - type: "registry:block", - target: "" - }], - component: React.lazy(async () => { - const mod = await import("@/registry/default/particles/p-toggle-group-12.tsx") - const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name - return { default: mod.default || mod[exportName] } - }), - categories: ["toggle","toggle group","segmented control","filter"], - meta: undefined, - }, "p-toggle-1": { name: "p-toggle-1", description: "Basic toggle", diff --git a/apps/ui/registry/default/particles/p-toggle-group-10.tsx b/apps/ui/registry/default/particles/p-toggle-group-10.tsx deleted file mode 100644 index 263a5a3fb..000000000 --- a/apps/ui/registry/default/particles/p-toggle-group-10.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { - segmentedControlItemVariants, - segmentedControlRootClassName, -} from "@/registry/default/lib/segmented-control"; -import { - ToggleGroup, - ToggleGroupItem, -} from "@/registry/default/ui/toggle-group"; - -const itemClassName = segmentedControlItemVariants({ - size: "sm", - state: "pressed", -}); - -export default function Particle() { - return ( - - - Open - - - Assigned - - - Urgent - - - ); -} diff --git a/apps/ui/registry/default/particles/p-toggle-group-11.tsx b/apps/ui/registry/default/particles/p-toggle-group-11.tsx deleted file mode 100644 index eb0bd13d2..000000000 --- a/apps/ui/registry/default/particles/p-toggle-group-11.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { - segmentedControlItemVariants, - segmentedControlRootClassName, -} from "@/registry/default/lib/segmented-control"; -import { - ToggleGroup, - ToggleGroupItem, -} from "@/registry/default/ui/toggle-group"; - -const itemClassName = segmentedControlItemVariants({ state: "pressed" }); - -export default function Particle() { - return ( - - - Open - - - Assigned - - - Urgent - - - ); -} diff --git a/apps/ui/registry/default/particles/p-toggle-group-12.tsx b/apps/ui/registry/default/particles/p-toggle-group-12.tsx deleted file mode 100644 index 5cf497c09..000000000 --- a/apps/ui/registry/default/particles/p-toggle-group-12.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { - segmentedControlItemVariants, - segmentedControlRootClassName, -} from "@/registry/default/lib/segmented-control"; -import { - ToggleGroup, - ToggleGroupItem, -} from "@/registry/default/ui/toggle-group"; - -const itemClassName = segmentedControlItemVariants({ - size: "lg", - state: "pressed", -}); - -export default function Particle() { - return ( - - - Open - - - Assigned - - - Urgent - - - ); -} diff --git a/apps/ui/registry/registry-particles.ts b/apps/ui/registry/registry-particles.ts index b56910589..843eee8e8 100644 --- a/apps/ui/registry/registry-particles.ts +++ b/apps/ui/registry/registry-particles.ts @@ -5665,51 +5665,6 @@ export const particles: ParticleItem[] = [ registryDependencies: ["@coss/toggle-group", "@coss/tooltip"], type: "registry:block", }, - { - categories: categories( - "toggle", - "toggle group", - "segmented control", - "filter", - ), - description: "Small segmented filter built with a toggle group", - files: [ - { path: "particles/p-toggle-group-10.tsx", type: "registry:block" }, - ], - name: "p-toggle-group-10", - registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], - type: "registry:block", - }, - { - categories: categories( - "toggle", - "toggle group", - "segmented control", - "filter", - ), - description: "Segmented filter built with a toggle group", - files: [ - { path: "particles/p-toggle-group-11.tsx", type: "registry:block" }, - ], - name: "p-toggle-group-11", - registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], - type: "registry:block", - }, - { - categories: categories( - "toggle", - "toggle group", - "segmented control", - "filter", - ), - description: "Large segmented filter built with a toggle group", - files: [ - { path: "particles/p-toggle-group-12.tsx", type: "registry:block" }, - ], - name: "p-toggle-group-12", - registryDependencies: ["@coss/segmented-control", "@coss/toggle-group"], - type: "registry:block", - }, { categories: categories("toggle"), description: "Basic toggle", diff --git a/apps/ui/skills/coss-particles/SKILL.md b/apps/ui/skills/coss-particles/SKILL.md index 9d91d0d33..6c03d889d 100644 --- a/apps/ui/skills/coss-particles/SKILL.md +++ b/apps/ui/skills/coss-particles/SKILL.md @@ -37,7 +37,7 @@ Run the generator script from the coss repo root: node apps/ui/scripts/generate-particle-index.cjs ``` -Total: **495 particles** across **53 component types** +Total: **492 particles** across **53 component types** ## Component types @@ -91,7 +91,7 @@ Total: **495 particles** across **53 component types** - [textarea](#textarea) (15) - [toast](#toast) (13) - [toggle](#toggle) (8) -- [toggle-group](#toggle-group) (12) +- [toggle-group](#toggle-group) (9) - [toolbar](#toolbar) (1) - [tooltip](#tooltip) (4) @@ -736,10 +736,6 @@ Total: **495 particles** across **53 component types** - Toggle group with disabled item | [JSON](https://coss.com/ui/r/p-toggle-group-7.json) - Multiple selection toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-8.json) - Toggle group with tooltips | [JSON](https://coss.com/ui/r/p-toggle-group-9.json) -- Small segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-10.json) -- Segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-11.json) -- Large segmented filter built with a toggle group | [JSON](https://coss.com/ui/r/p-toggle-group-12.json) - ### toolbar - Toolbar with toggles, buttons, and select | [JSON](https://coss.com/ui/r/p-toolbar-1.json) diff --git a/apps/ui/skills/coss/references/primitives/toggle-group.md b/apps/ui/skills/coss/references/primitives/toggle-group.md index d4568a60e..66212ad55 100644 --- a/apps/ui/skills/coss/references/primitives/toggle-group.md +++ b/apps/ui/skills/coss/references/primitives/toggle-group.md @@ -68,7 +68,7 @@ const [value, setValue] = useState(["bold"]) ### More examples -See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, disabled, multiple, and tooltip patterns. For an exclusive segmented filter or mode, use `p-toggle-group-10`, `p-toggle-group-11`, or `p-toggle-group-12`; read `../segmented-control.md` before choosing the underlying primitive. +See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, disabled, multiple, and tooltip patterns. Read `../segmented-control.md` before applying segmented styling to a custom reversible mode. ## Common pitfalls @@ -86,4 +86,3 @@ See `p-toggle-group-1` through `p-toggle-group-9` for sizes, outline, vertical, - with disabled toggle: `p-toggle-group-7` - multiple selection: `p-toggle-group-8` - with tooltips: `p-toggle-group-9` -- segmented filter, small/default/large: `p-toggle-group-10`, `p-toggle-group-11`, `p-toggle-group-12` diff --git a/apps/ui/skills/coss/references/segmented-control.md b/apps/ui/skills/coss/references/segmented-control.md index ff53e0b58..47a3cee3a 100644 --- a/apps/ui/skills/coss/references/segmented-control.md +++ b/apps/ui/skills/coss/references/segmented-control.md @@ -19,10 +19,11 @@ Do not use Tabs for navigation links, form values, or filters merely because the | --- | --- | --- | --- | | Radio Group | `@coss/p-radio-group-7` | `@coss/p-radio-group-8` | `@coss/p-radio-group-9` | | Navigation links | `@coss/p-navigation-2` | `@coss/p-navigation-1` | `@coss/p-navigation-3` | -| Toggle Group | `@coss/p-toggle-group-10` | `@coss/p-toggle-group-11` | `@coss/p-toggle-group-12` | The CLI installs the relevant primitive and the shared `@coss/segmented-control` styling library automatically. +COSS does not publish a Toggle Group segmented particle. Use the shared styling directly only when a reversible mode genuinely allows no active option. + ## Custom composition Install the styling library directly when none of the particles matches: