@create-ui/cli 0.5.9 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-KFQXWKJJ.js +19 -0
- package/dist/chunk-KFQXWKJJ.js.map +1 -0
- package/dist/{chunk-2ELKDGGM.js → chunk-OGAWGP7T.js} +3 -3
- package/dist/{chunk-2ELKDGGM.js.map → chunk-OGAWGP7T.js.map} +1 -1
- package/dist/chunk-OITQ46YK.js +99 -0
- package/dist/chunk-OITQ46YK.js.map +1 -0
- package/dist/index.js +28 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +1 -1
- package/dist/skills/createui/SKILL.md +81 -54
- package/dist/skills/createui/cli.md +1 -1
- package/dist/skills/createui/customization.md +14 -12
- package/dist/skills/createui/evals/evals.json +77 -0
- package/dist/skills/createui/mcp.md +12 -26
- package/dist/skills/createui/rules/a11y.md +148 -0
- package/dist/skills/createui/rules/composition.md +64 -26
- package/dist/skills/createui/rules/forms.md +2 -2
- package/dist/skills/createui/rules/icons.md +1 -1
- package/dist/skills/createui/rules/styling.md +2 -2
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-643QI2I2.js +0 -102
- package/dist/chunk-643QI2I2.js.map +0 -1
- package/dist/chunk-KQTXDVKV.js +0 -19
- package/dist/chunk-KQTXDVKV.js.map +0 -1
- package/dist/skills/createui/reference/accordion.md +0 -127
- package/dist/skills/createui/reference/app-store-badge.md +0 -88
- package/dist/skills/createui/reference/aspect-ratio.md +0 -52
- package/dist/skills/createui/reference/avatar.md +0 -230
- package/dist/skills/createui/reference/badge.md +0 -110
- package/dist/skills/createui/reference/breadcrumb.md +0 -153
- package/dist/skills/createui/reference/button-group.md +0 -116
- package/dist/skills/createui/reference/button.md +0 -104
- package/dist/skills/createui/reference/checkbox-group.md +0 -118
- package/dist/skills/createui/reference/checkbox.md +0 -79
- package/dist/skills/createui/reference/chip.md +0 -115
- package/dist/skills/createui/reference/close-button.md +0 -83
- package/dist/skills/createui/reference/command.md +0 -69
- package/dist/skills/createui/reference/country-flag.md +0 -109
- package/dist/skills/createui/reference/credit-card-input.md +0 -76
- package/dist/skills/createui/reference/date-input.md +0 -71
- package/dist/skills/createui/reference/dropdown-menu.md +0 -164
- package/dist/skills/createui/reference/field.md +0 -186
- package/dist/skills/createui/reference/info-tooltip.md +0 -110
- package/dist/skills/createui/reference/inline-alert.md +0 -146
- package/dist/skills/createui/reference/input-group.md +0 -171
- package/dist/skills/createui/reference/input-otp.md +0 -130
- package/dist/skills/createui/reference/input-stepper.md +0 -120
- package/dist/skills/createui/reference/input.md +0 -118
- package/dist/skills/createui/reference/label.md +0 -121
- package/dist/skills/createui/reference/pagination.md +0 -157
- package/dist/skills/createui/reference/password-strength.md +0 -70
- package/dist/skills/createui/reference/phone-input.md +0 -77
- package/dist/skills/createui/reference/progress.md +0 -158
- package/dist/skills/createui/reference/radio-group.md +0 -133
- package/dist/skills/createui/reference/radio.md +0 -79
- package/dist/skills/createui/reference/scroll-area.md +0 -212
- package/dist/skills/createui/reference/segmented-control.md +0 -146
- package/dist/skills/createui/reference/select.md +0 -204
- package/dist/skills/createui/reference/separator.md +0 -99
- package/dist/skills/createui/reference/social-login-button.md +0 -130
- package/dist/skills/createui/reference/spinner.md +0 -68
- package/dist/skills/createui/reference/status-badge.md +0 -89
- package/dist/skills/createui/reference/switch-group.md +0 -122
- package/dist/skills/createui/reference/switch.md +0 -75
- package/dist/skills/createui/reference/tab-menu.md +0 -165
- package/dist/skills/createui/reference/text-link.md +0 -84
- package/dist/skills/createui/reference/textarea.md +0 -50
- package/dist/skills/createui/reference/toast.md +0 -162
- package/dist/skills/createui/reference/tooltip.md +0 -63
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/scroll-area.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/scroll-area.md -->
|
|
2
|
-
|
|
3
|
-
# scroll-area
|
|
4
|
-
|
|
5
|
-
Custom-scrollbar viewport; vertical, horizontal or both, filled/ghost scrollbar styles and optional edge fade
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add scroll-area`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `scrollBarVariants`
|
|
16
|
-
|
|
17
|
-
## ScrollArea props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| appearance | `filled \| ghost` (filled adds a bg-weak track behind the thumb; ghost shows only the thumb; forwarded to all auto-rendered scrollbars) | `filled` |
|
|
22
|
-
| size | `sm \| md \| lg` (Set once on ScrollArea; forwarded to every auto-rendered scrollbar) | `md` |
|
|
23
|
-
| orientation | `vertical \| horizontal \| both` (Auto-renders the matching scrollbar(s); a Corner is always rendered, so 'both' needs no extra children) | `vertical` |
|
|
24
|
-
| fade | `boolean` (End-of-scroll gradient only (bottom / right edge); hides at scroll end or when content fits, re-checked on scroll, resize, and DOM mutations) | `false` |
|
|
25
|
-
|
|
26
|
-
Extends `React.ComponentProps<typeof ScrollAreaPrimitive.Root>`.
|
|
27
|
-
|
|
28
|
-
## ScrollBar props
|
|
29
|
-
|
|
30
|
-
| Prop | Type | Default |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| appearance | `filled \| ghost` (filled adds a bg-weak track behind the thumb; ghost shows only the thumb; forwarded to all auto-rendered scrollbars) | `filled` |
|
|
33
|
-
| size | `sm \| md \| lg` (Set once on ScrollArea; forwarded to every auto-rendered scrollbar) | `md` |
|
|
34
|
-
|
|
35
|
-
Extends `React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>`.
|
|
36
|
-
|
|
37
|
-
## Examples
|
|
38
|
-
|
|
39
|
-
From `scroll-area-demo`:
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
import * as React from "react"
|
|
43
|
-
|
|
44
|
-
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
45
|
-
import { Separator } from "@/components/ui/separator"
|
|
46
|
-
|
|
47
|
-
const components = [
|
|
48
|
-
"Accordion",
|
|
49
|
-
"Alert Banner",
|
|
50
|
-
"App Store Badge",
|
|
51
|
-
"Aspect Ratio",
|
|
52
|
-
"Avatar",
|
|
53
|
-
"Badge",
|
|
54
|
-
"Breadcrumb",
|
|
55
|
-
"Button",
|
|
56
|
-
"Button Group",
|
|
57
|
-
"Checkbox",
|
|
58
|
-
"Checkbox Group",
|
|
59
|
-
"Chip",
|
|
60
|
-
"Close Button",
|
|
61
|
-
"Command",
|
|
62
|
-
"Country Flag",
|
|
63
|
-
"Credit Card Input",
|
|
64
|
-
"Date Input",
|
|
65
|
-
"Dialog",
|
|
66
|
-
"Dropdown Menu",
|
|
67
|
-
"Field",
|
|
68
|
-
"Info Tooltip",
|
|
69
|
-
"Inline Alert",
|
|
70
|
-
"Input",
|
|
71
|
-
"Input Group",
|
|
72
|
-
"Input OTP",
|
|
73
|
-
"Input Stepper",
|
|
74
|
-
"Label",
|
|
75
|
-
"Modal",
|
|
76
|
-
"Pagination",
|
|
77
|
-
"Password Strength",
|
|
78
|
-
"Phone Input",
|
|
79
|
-
"Popover",
|
|
80
|
-
"Progress",
|
|
81
|
-
"Radio",
|
|
82
|
-
"Radio Group",
|
|
83
|
-
"Scroll Area",
|
|
84
|
-
"Segmented Control",
|
|
85
|
-
"Select",
|
|
86
|
-
"Separator",
|
|
87
|
-
"Social Login Button",
|
|
88
|
-
"Spinner",
|
|
89
|
-
"Status Badge",
|
|
90
|
-
"Switch",
|
|
91
|
-
"Switch Group",
|
|
92
|
-
"Tab Menu",
|
|
93
|
-
"Text Link",
|
|
94
|
-
"Textarea",
|
|
95
|
-
"Toast",
|
|
96
|
-
"Tooltip",
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
export default function ScrollAreaDemo() {
|
|
100
|
-
return (
|
|
101
|
-
<ScrollArea className="bg-weakest text-strong h-72 w-48 rounded-md">
|
|
102
|
-
<div className="p-4">
|
|
103
|
-
<h4 className="mb-4 text-sm leading-none font-medium">Components</h4>
|
|
104
|
-
{components.map((component) => (
|
|
105
|
-
<React.Fragment key={component}>
|
|
106
|
-
<div className="text-sm">{component}</div>
|
|
107
|
-
<Separator className="my-2" />
|
|
108
|
-
</React.Fragment>
|
|
109
|
-
))}
|
|
110
|
-
</div>
|
|
111
|
-
</ScrollArea>
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
From `scroll-area-fade`:
|
|
117
|
-
|
|
118
|
-
```tsx
|
|
119
|
-
import * as React from "react"
|
|
120
|
-
|
|
121
|
-
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
122
|
-
import { Separator } from "@/components/ui/separator"
|
|
123
|
-
|
|
124
|
-
const components = [
|
|
125
|
-
"Accordion",
|
|
126
|
-
"Alert Banner",
|
|
127
|
-
"App Store Badge",
|
|
128
|
-
"Aspect Ratio",
|
|
129
|
-
"Avatar",
|
|
130
|
-
"Badge",
|
|
131
|
-
"Breadcrumb",
|
|
132
|
-
"Button",
|
|
133
|
-
"Button Group",
|
|
134
|
-
"Checkbox",
|
|
135
|
-
"Checkbox Group",
|
|
136
|
-
"Chip",
|
|
137
|
-
"Close Button",
|
|
138
|
-
"Command",
|
|
139
|
-
"Country Flag",
|
|
140
|
-
"Credit Card Input",
|
|
141
|
-
"Date Input",
|
|
142
|
-
"Dialog",
|
|
143
|
-
"Dropdown Menu",
|
|
144
|
-
"Field",
|
|
145
|
-
"Info Tooltip",
|
|
146
|
-
"Inline Alert",
|
|
147
|
-
"Input",
|
|
148
|
-
"Input Group",
|
|
149
|
-
"Input OTP",
|
|
150
|
-
"Input Stepper",
|
|
151
|
-
"Label",
|
|
152
|
-
"Modal",
|
|
153
|
-
"Pagination",
|
|
154
|
-
"Password Strength",
|
|
155
|
-
"Phone Input",
|
|
156
|
-
"Popover",
|
|
157
|
-
"Progress",
|
|
158
|
-
"Radio",
|
|
159
|
-
"Radio Group",
|
|
160
|
-
"Scroll Area",
|
|
161
|
-
"Segmented Control",
|
|
162
|
-
"Select",
|
|
163
|
-
"Separator",
|
|
164
|
-
"Social Login Button",
|
|
165
|
-
"Spinner",
|
|
166
|
-
"Status Badge",
|
|
167
|
-
"Switch",
|
|
168
|
-
"Switch Group",
|
|
169
|
-
"Tab Menu",
|
|
170
|
-
"Text Link",
|
|
171
|
-
"Textarea",
|
|
172
|
-
"Toast",
|
|
173
|
-
"Tooltip",
|
|
174
|
-
]
|
|
175
|
-
|
|
176
|
-
export default function ScrollAreaFade() {
|
|
177
|
-
return (
|
|
178
|
-
<ScrollArea fade className="bg-weakest text-strong h-72 w-48 rounded-md">
|
|
179
|
-
<div className="p-4">
|
|
180
|
-
<h4 className="mb-4 text-sm leading-none font-medium">Components</h4>
|
|
181
|
-
{components.map((component) => (
|
|
182
|
-
<React.Fragment key={component}>
|
|
183
|
-
<div className="text-sm">{component}</div>
|
|
184
|
-
<Separator className="my-2" />
|
|
185
|
-
</React.Fragment>
|
|
186
|
-
))}
|
|
187
|
-
</div>
|
|
188
|
-
</ScrollArea>
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
More: `npx @create-ui/cli view scroll-area` or MCP `get_item_examples_from_registries` with "scroll-area-demo" / "scroll-area-example".
|
|
194
|
-
|
|
195
|
-
## When to use
|
|
196
|
-
Styled overlay-scrollbar viewport for content that overflows a fixed-size surface: lists in panels, image rows, wide grids. Do not use it for full-page scrolling (let the browser handle that). DropdownMenu and Select content panels already scroll on their own; do not wrap them in ScrollArea.
|
|
197
|
-
|
|
198
|
-
## Gotchas
|
|
199
|
-
- Unlike shadcn, you never add a `<ScrollBar>` child. `ScrollArea` renders viewport, scrollbar(s), and corner itself from `orientation`; horizontal scrolling is `orientation="horizontal"`, not an extra child. A `<ScrollBar>` child would land inside the scrolled viewport content; the export exists only for fully custom setups.
|
|
200
|
-
- Width/height constraints go on the root `className` (e.g. `h-72 w-48`); the internal viewport is `size-full` and inherits the root's radius. Without a fixed dimension on the enabled axis nothing scrolls.
|
|
201
|
-
- Horizontal content must actually overflow: a non-wrapping flex row with `shrink-0` children inside a width-constrained root, e.g.
|
|
202
|
-
|
|
203
|
-
```tsx
|
|
204
|
-
<ScrollArea orientation="horizontal" className="w-full max-w-96 rounded-md p-4">
|
|
205
|
-
<div className="flex gap-4">{items /* each child shrink-0 */}</div>
|
|
206
|
-
</ScrollArea>
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
- `fade` overlays mark only the scroll END of each enabled axis (bottom for vertical, right for horizontal); there is no top/left start fade. They are `aria-hidden` and `pointer-events-none`, and dynamic content is handled automatically (scroll listener + ResizeObserver + MutationObserver).
|
|
210
|
-
- The fade gradient ends in the `static-white` token (white in light mode, black in dark), not the container's own background. On a tinted container (e.g. `bg-weakest`) the fade edge will not exactly match the surface color.
|
|
211
|
-
- Scrollbars are `forceMount`ed and toggle via opacity (`data-[state=hidden/visible]`); show/hide timing comes from the Radix root's `type` and `scrollHideDelay` props, which pass through `ScrollArea` untouched.
|
|
212
|
-
- The `cn-scroll-area*` classes are intentional style-less hooks for consumer CSS targeting; do not strip them as dead code.
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/segmented-control.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/segmented-control.md -->
|
|
2
|
-
|
|
3
|
-
# segmented-control
|
|
4
|
-
|
|
5
|
-
Single-select between 2-7 options with an animated sliding indicator; value/onValueChange, flat or grouped appearance
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add segmented-control`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { SegmentedControl, SegmentedControlItem } from "@/components/ui/segmented-control"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `segmentedControlVariants`, `segmentedControlItemVariants`, `segmentedControlIndicatorVariants`
|
|
16
|
-
|
|
17
|
-
## SegmentedControl props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `primary \| neutral` | `primary` |
|
|
22
|
-
| shape | `rounded \| pill` | `rounded` |
|
|
23
|
-
| size | `xs \| sm \| md \| lg \| xl` | `md` |
|
|
24
|
-
| appearance | `flat \| grouped` (flat = independent-looking buttons, grouped = padded bg-weak container (pricing-toggle look); the active pill slides in BOTH) | `flat` |
|
|
25
|
-
| value | `string` | - |
|
|
26
|
-
| defaultValue | `string` | - |
|
|
27
|
-
| onValueChange | `(value: string) => void` | - |
|
|
28
|
-
|
|
29
|
-
Extends `React.ComponentProps<"div">`.
|
|
30
|
-
|
|
31
|
-
## SegmentedControlItem props
|
|
32
|
-
|
|
33
|
-
| Prop | Type | Default |
|
|
34
|
-
| --- | --- | --- |
|
|
35
|
-
| variant | `primary \| neutral` | `primary` |
|
|
36
|
-
| shape | `rounded \| pill` | `rounded` |
|
|
37
|
-
| size | `xs \| sm \| md \| lg \| xl` | `md` |
|
|
38
|
-
| appearance | `flat \| grouped` (flat = independent-looking buttons, grouped = padded bg-weak container (pricing-toggle look); the active pill slides in BOTH) | `flat` |
|
|
39
|
-
| iconOnly | `boolean` (renders children as a single centered icon (like Button); leadingIcon/trailingIcon are ignored; add aria-label (the text label is gone)) | `false` |
|
|
40
|
-
| asChild | `boolean` (skips aria-pressed and type=button; disabled becomes aria-disabled + tabIndex=-1 instead of the native attribute) | `false` |
|
|
41
|
-
| value | `string` | - |
|
|
42
|
-
| selected | `boolean` (forces the active state without binding value on the root; the sliding indicator still moves to it) | - |
|
|
43
|
-
| leadingIcon | `ReactNode` | - |
|
|
44
|
-
| trailingIcon | `ReactNode` | - |
|
|
45
|
-
|
|
46
|
-
Extends `React.ComponentProps<"button">`.
|
|
47
|
-
|
|
48
|
-
## Icons
|
|
49
|
-
|
|
50
|
-
Icons go through icon props - never as children next to text, and never with sizing classes (the component sizes icons per `size`): `SegmentedControlItem` (`leadingIcon` / `trailingIcon`). Import icons from `@create-ui/assets/icons` (Remix `Ri*`).
|
|
51
|
-
|
|
52
|
-
## Examples
|
|
53
|
-
|
|
54
|
-
From `segmented-control-demo`:
|
|
55
|
-
|
|
56
|
-
```tsx
|
|
57
|
-
import {
|
|
58
|
-
RiLayoutGridFill,
|
|
59
|
-
RiLineChartLine,
|
|
60
|
-
RiListUnordered,
|
|
61
|
-
} from "@create-ui/assets/icons"
|
|
62
|
-
|
|
63
|
-
import {
|
|
64
|
-
SegmentedControl,
|
|
65
|
-
SegmentedControlItem,
|
|
66
|
-
} from "@/components/ui/segmented-control"
|
|
67
|
-
|
|
68
|
-
export default function SegmentedControlDemo() {
|
|
69
|
-
return (
|
|
70
|
-
<SegmentedControl
|
|
71
|
-
variant="neutral"
|
|
72
|
-
appearance="grouped"
|
|
73
|
-
defaultValue="list"
|
|
74
|
-
>
|
|
75
|
-
<SegmentedControlItem value="grid" leadingIcon={<RiLayoutGridFill />}>
|
|
76
|
-
Grid
|
|
77
|
-
</SegmentedControlItem>
|
|
78
|
-
<SegmentedControlItem value="list" leadingIcon={<RiListUnordered />}>
|
|
79
|
-
List
|
|
80
|
-
</SegmentedControlItem>
|
|
81
|
-
<SegmentedControlItem value="chart" leadingIcon={<RiLineChartLine />}>
|
|
82
|
-
Chart
|
|
83
|
-
</SegmentedControlItem>
|
|
84
|
-
</SegmentedControl>
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
From `segmented-control-appearance`:
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
import {
|
|
93
|
-
RiInbox2Line,
|
|
94
|
-
RiSettings6Fill,
|
|
95
|
-
RiUser3Line,
|
|
96
|
-
} from "@create-ui/assets/icons"
|
|
97
|
-
|
|
98
|
-
import {
|
|
99
|
-
SegmentedControl,
|
|
100
|
-
SegmentedControlItem,
|
|
101
|
-
} from "@/components/ui/segmented-control"
|
|
102
|
-
|
|
103
|
-
export default function SegmentedControlAppearance() {
|
|
104
|
-
return (
|
|
105
|
-
<div className="flex flex-col items-start gap-4">
|
|
106
|
-
<SegmentedControl variant="neutral" appearance="flat" className="gap-2">
|
|
107
|
-
<SegmentedControlItem leadingIcon={<RiInbox2Line />}>
|
|
108
|
-
Inbox
|
|
109
|
-
</SegmentedControlItem>
|
|
110
|
-
<SegmentedControlItem selected leadingIcon={<RiUser3Line />}>
|
|
111
|
-
Mine
|
|
112
|
-
</SegmentedControlItem>
|
|
113
|
-
<SegmentedControlItem leadingIcon={<RiSettings6Fill />}>
|
|
114
|
-
Archived
|
|
115
|
-
</SegmentedControlItem>
|
|
116
|
-
</SegmentedControl>
|
|
117
|
-
|
|
118
|
-
<SegmentedControl
|
|
119
|
-
variant="neutral"
|
|
120
|
-
appearance="grouped"
|
|
121
|
-
defaultValue="week"
|
|
122
|
-
>
|
|
123
|
-
<SegmentedControlItem value="day">Day</SegmentedControlItem>
|
|
124
|
-
<SegmentedControlItem value="week">Week</SegmentedControlItem>
|
|
125
|
-
<SegmentedControlItem value="month">Month</SegmentedControlItem>
|
|
126
|
-
</SegmentedControl>
|
|
127
|
-
</div>
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
More: `npx @create-ui/cli view segmented-control` or MCP `get_item_examples_from_registries` with "segmented-control-demo" / "segmented-control-example".
|
|
133
|
-
|
|
134
|
-
## When to use
|
|
135
|
-
|
|
136
|
-
Single-select between 2-7 mutually exclusive options that benefit from being visible at once: view mode, time range, billing period. Drive it with `value`/`onValueChange` or `defaultValue`; never hand-roll it as a row of `Button`s with manual active state. Wrong tool for: multi-select (`CheckboxGroup`), route or section navigation (`TabMenu`), lists past ~7 (`Select`), a boolean (`Switch`), or form-style radio choices (`RadioGroup`).
|
|
137
|
-
|
|
138
|
-
## Gotchas
|
|
139
|
-
|
|
140
|
-
- This is NOT Radix ToggleGroup: there is no `type` prop (single-select only), clicking the active item does not deselect it, and every item is its own Tab stop (`role="group"` + `aria-pressed` per button, no arrow-key roving).
|
|
141
|
-
- An item without `value` never commits a selection; its `onClick` still fires, and calling `event.preventDefault()` inside `onClick` blocks the commit even when `value` is set.
|
|
142
|
-
- The visible active background is a separate floating element (`data-slot="segmented-control-indicator"`) measured from the `data-state="on"` item; in `flat` appearance the selected item's own bg/shadow turn transparent once the indicator mounts. Style the indicator for active background/shadow; active text color stays on the item.
|
|
143
|
-
- `flat` items sit flush with no gap; add spacing on the root yourself (`className="gap-2"`), as the appearance example does.
|
|
144
|
-
- `variant`/`shape`/`size`/`appearance` cascade from the root via context; set them once on `SegmentedControl`, not per item (per-item props exist only as overrides).
|
|
145
|
-
- `appearance="grouped"` adds container padding on top of the item height (xs/sm +4px, md/lg +8px, xl +16px), so a grouped control is taller than its `size` suggests: grouped xs/sm = 28/32px, md = 40px, lg = 48px, xl = 64px. Next to a `Button` in a toolbar, pair by rendered height, not by size name (e.g. grouped sm = 32px aligns with Button md).
|
|
146
|
-
- `iconOnly` gives the item a FIXED square (`size-N`). Adding `flex-1` / `w-full` / `grow` via `className` makes the flex layout override that fixed width and stretch the square into a wide rectangle. For a compact icon toggle, add NO width class and let the square stand. Only stretch deliberately (e.g. a full-width 2-up mobile switcher) - and then accept it is no longer square.
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/select.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/select.md -->
|
|
2
|
-
|
|
3
|
-
# select
|
|
4
|
-
|
|
5
|
-
Radix select for picking one option from a dropdown list; size and state inherit from Field, compact width variant
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add select`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { Select, SelectProvider, SelectShell, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from "@/components/ui/select"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `selectShellVariants`, `selectTriggerVariants`, `useSelectContext`
|
|
16
|
-
|
|
17
|
-
## Select props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| size | `xs \| sm \| md` | - |
|
|
22
|
-
| variant | `default \| compact` (compact = width-fits-content (shell w-fit, trigger flex-none) for toolbars/inline pickers; NOT auto-applied inside InputGroup, pass it explicitly) | `default` |
|
|
23
|
-
| loading | `boolean` (also hard-disables the whole root (disabled || loading) and swaps the chevron for a Spinner; the shell goes pointer-events-none) | `false` |
|
|
24
|
-
| invalid | `boolean` | `false` |
|
|
25
|
-
|
|
26
|
-
Extends `React.ComponentProps<typeof SelectPrimitive.Root>`.
|
|
27
|
-
|
|
28
|
-
## SelectProvider props
|
|
29
|
-
|
|
30
|
-
| Prop | Type | Default |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| size | `xs \| sm \| md` | `sm` |
|
|
33
|
-
| variant | `default \| compact` (compact = width-fits-content (shell w-fit, trigger flex-none) for toolbars/inline pickers; NOT auto-applied inside InputGroup, pass it explicitly) | `default` |
|
|
34
|
-
| invalid | `boolean` | `false` |
|
|
35
|
-
| disabled | `boolean` | `false` |
|
|
36
|
-
| loading | `boolean` (also hard-disables the whole root (disabled || loading) and swaps the chevron for a Spinner; the shell goes pointer-events-none) | `false` |
|
|
37
|
-
| children | `ReactNode` | - |
|
|
38
|
-
|
|
39
|
-
## SelectTrigger props
|
|
40
|
-
|
|
41
|
-
| Prop | Type | Default |
|
|
42
|
-
| --- | --- | --- |
|
|
43
|
-
| size | `xs \| sm \| md` | `sm` |
|
|
44
|
-
| variant | `default \| compact` (compact = width-fits-content (shell w-fit, trigger flex-none) for toolbars/inline pickers; NOT auto-applied inside InputGroup, pass it explicitly) | `default` |
|
|
45
|
-
|
|
46
|
-
Extends `React.ComponentProps<typeof SelectPrimitive.Trigger>`.
|
|
47
|
-
|
|
48
|
-
## Examples
|
|
49
|
-
|
|
50
|
-
From `select-demo`:
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
"use client"
|
|
54
|
-
|
|
55
|
-
import * as React from "react"
|
|
56
|
-
import {
|
|
57
|
-
France,
|
|
58
|
-
Germany,
|
|
59
|
-
Japan,
|
|
60
|
-
Turkey,
|
|
61
|
-
UnitedStates,
|
|
62
|
-
} from "@create-ui/assets/flags"
|
|
63
|
-
|
|
64
|
-
import {
|
|
65
|
-
Select,
|
|
66
|
-
SelectContent,
|
|
67
|
-
SelectGroup,
|
|
68
|
-
SelectItem,
|
|
69
|
-
SelectTrigger,
|
|
70
|
-
SelectValue,
|
|
71
|
-
} from "@/components/ui/select"
|
|
72
|
-
|
|
73
|
-
const COUNTRIES = [
|
|
74
|
-
{
|
|
75
|
-
value: "de",
|
|
76
|
-
label: "Germany",
|
|
77
|
-
flag: <Germany className="size-5 shrink-0" />,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
value: "us",
|
|
81
|
-
label: "United States",
|
|
82
|
-
flag: <UnitedStates className="size-5 shrink-0" />,
|
|
83
|
-
},
|
|
84
|
-
{ value: "jp", label: "Japan", flag: <Japan className="size-5 shrink-0" /> },
|
|
85
|
-
{
|
|
86
|
-
value: "fr",
|
|
87
|
-
label: "France",
|
|
88
|
-
flag: <France className="size-5 shrink-0" />,
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
value: "tr",
|
|
92
|
-
label: "Türkiye",
|
|
93
|
-
flag: <Turkey className="size-5 shrink-0" />,
|
|
94
|
-
},
|
|
95
|
-
]
|
|
96
|
-
|
|
97
|
-
export default function SelectDemo() {
|
|
98
|
-
const [value, setValue] = React.useState<string | undefined>("de")
|
|
99
|
-
const selected = COUNTRIES.find((c) => c.value === value)
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<div className="w-full max-w-xs">
|
|
103
|
-
<Select size="md" value={value} onValueChange={setValue}>
|
|
104
|
-
<SelectTrigger>
|
|
105
|
-
{selected?.flag}
|
|
106
|
-
<SelectValue placeholder="Select country">
|
|
107
|
-
{selected?.label}
|
|
108
|
-
</SelectValue>
|
|
109
|
-
</SelectTrigger>
|
|
110
|
-
<SelectContent>
|
|
111
|
-
<SelectGroup>
|
|
112
|
-
<SelectItem value="de">
|
|
113
|
-
<Germany className="size-5 shrink-0" />
|
|
114
|
-
Germany
|
|
115
|
-
</SelectItem>
|
|
116
|
-
<SelectItem value="us">
|
|
117
|
-
<UnitedStates className="size-5 shrink-0" />
|
|
118
|
-
United States
|
|
119
|
-
</SelectItem>
|
|
120
|
-
<SelectItem value="jp">
|
|
121
|
-
<Japan className="size-5 shrink-0" />
|
|
122
|
-
Japan
|
|
123
|
-
</SelectItem>
|
|
124
|
-
<SelectItem value="fr">
|
|
125
|
-
<France className="size-5 shrink-0" />
|
|
126
|
-
France
|
|
127
|
-
</SelectItem>
|
|
128
|
-
<SelectItem value="tr">
|
|
129
|
-
<Turkey className="size-5 shrink-0" />
|
|
130
|
-
Türkiye
|
|
131
|
-
</SelectItem>
|
|
132
|
-
</SelectGroup>
|
|
133
|
-
</SelectContent>
|
|
134
|
-
</Select>
|
|
135
|
-
</div>
|
|
136
|
-
)
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
From `select-in-input-group`:
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
"use client"
|
|
144
|
-
|
|
145
|
-
import * as React from "react"
|
|
146
|
-
|
|
147
|
-
import {
|
|
148
|
-
InputGroup,
|
|
149
|
-
InputGroupControl,
|
|
150
|
-
InputGroupSlot,
|
|
151
|
-
} from "@/components/ui/input-group"
|
|
152
|
-
import {
|
|
153
|
-
Select,
|
|
154
|
-
SelectContent,
|
|
155
|
-
SelectGroup,
|
|
156
|
-
SelectItem,
|
|
157
|
-
SelectTrigger,
|
|
158
|
-
SelectValue,
|
|
159
|
-
} from "@/components/ui/select"
|
|
160
|
-
|
|
161
|
-
export default function SelectInInputGroup() {
|
|
162
|
-
const [currency, setCurrency] = React.useState("usd")
|
|
163
|
-
|
|
164
|
-
return (
|
|
165
|
-
<div className="w-full max-w-xs">
|
|
166
|
-
<InputGroup size="md">
|
|
167
|
-
<Select variant="compact" value={currency} onValueChange={setCurrency}>
|
|
168
|
-
<SelectTrigger aria-label="Currency">
|
|
169
|
-
<SelectValue />
|
|
170
|
-
</SelectTrigger>
|
|
171
|
-
<SelectContent>
|
|
172
|
-
<SelectGroup>
|
|
173
|
-
<SelectItem value="usd">USD</SelectItem>
|
|
174
|
-
<SelectItem value="eur">EUR</SelectItem>
|
|
175
|
-
<SelectItem value="jpy">JPY</SelectItem>
|
|
176
|
-
<SelectItem value="try">TRY</SelectItem>
|
|
177
|
-
</SelectGroup>
|
|
178
|
-
</SelectContent>
|
|
179
|
-
</Select>
|
|
180
|
-
<InputGroupSlot>
|
|
181
|
-
<InputGroupControl placeholder="0.00" inputMode="decimal" />
|
|
182
|
-
</InputGroupSlot>
|
|
183
|
-
</InputGroup>
|
|
184
|
-
</div>
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
More: `npx @create-ui/cli view select` or MCP `get_item_examples_from_registries` with "select-demo" / "select-example".
|
|
190
|
-
|
|
191
|
-
## When to use
|
|
192
|
-
Select picks one value from a short predefined list (country, currency, role, plan). Wrap it in Field for the label and the size/state cascade. Long or searchable lists are Command territory; a single boolean is Switch (settings row) or Checkbox (form); a few always-visible options are SegmentedControl.
|
|
193
|
-
## Gotchas
|
|
194
|
-
- SelectTrigger auto-wraps itself in SelectShell when standalone, and renders bare when it detects an InputShell (from InputGroup) or explicit SelectShell ancestor. Border, focus, and state chrome live on the shell, so overrides belong there, not on the trigger.
|
|
195
|
-
- Inside InputGroup you must pass variant="compact" yourself; the default variant's trigger is flex-1 w-full and squeezes the sibling Input.
|
|
196
|
-
- Size resolves explicit prop > InputGroup context > Field context > "sm"; invalid/disabled/loading on the root fall back to Field. Set them once on Field, never re-set per part.
|
|
197
|
-
- The chevron (and the trailing primary check indicator on items) is auto-rendered; never append your own caret.
|
|
198
|
-
- SelectItem auto-detects a leading icon: with multiple children whose first is an element, that first child becomes the leading slot and the rest becomes truncating text. Pass icon and label as plain siblings:
|
|
199
|
-
```tsx
|
|
200
|
-
<SelectItem value="de">
|
|
201
|
-
<Germany className="size-5 shrink-0" />
|
|
202
|
-
Germany
|
|
203
|
-
</SelectItem>
|
|
204
|
-
```
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/separator.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/separator.md -->
|
|
2
|
-
|
|
3
|
-
# separator
|
|
4
|
-
|
|
5
|
-
Horizontal divider line; optional inline label or icon content aligned start, center or end
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add separator`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { Separator } from "@/components/ui/separator"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Separator props
|
|
16
|
-
|
|
17
|
-
| Prop | Type | Default |
|
|
18
|
-
| --- | --- | --- |
|
|
19
|
-
| align | `start \| center \| end` (Labeled mode only: drops the flanking line on that side so the label sits flush. Ignored when there are no children.) | `center` |
|
|
20
|
-
|
|
21
|
-
Extends `React.ComponentProps<"div">`.
|
|
22
|
-
|
|
23
|
-
## Examples
|
|
24
|
-
|
|
25
|
-
From `separator-demo`:
|
|
26
|
-
|
|
27
|
-
```tsx
|
|
28
|
-
import { Separator } from "@/components/ui/separator"
|
|
29
|
-
|
|
30
|
-
export default function SeparatorDemo() {
|
|
31
|
-
return (
|
|
32
|
-
<div className="text-body text-ui-control-md flex w-[420px] flex-col gap-4">
|
|
33
|
-
<p>
|
|
34
|
-
Workspace settings are scoped to the current organization and apply to
|
|
35
|
-
every member.
|
|
36
|
-
</p>
|
|
37
|
-
<Separator />
|
|
38
|
-
<p>
|
|
39
|
-
Personal preferences only affect your account and follow you across
|
|
40
|
-
workspaces.
|
|
41
|
-
</p>
|
|
42
|
-
</div>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
From `separator-with-label`:
|
|
48
|
-
|
|
49
|
-
```tsx
|
|
50
|
-
import { Button } from "@/components/ui/button"
|
|
51
|
-
import { Separator } from "@/components/ui/separator"
|
|
52
|
-
|
|
53
|
-
export default function SeparatorWithLabel() {
|
|
54
|
-
return (
|
|
55
|
-
<div className="flex w-[360px] flex-col gap-4">
|
|
56
|
-
<Button variant="primary" appearance="solid">
|
|
57
|
-
Continue with email
|
|
58
|
-
</Button>
|
|
59
|
-
<Separator>OR</Separator>
|
|
60
|
-
<Button variant="neutral-solid" appearance="outline">
|
|
61
|
-
Create a free account
|
|
62
|
-
</Button>
|
|
63
|
-
</div>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
More: `npx @create-ui/cli view separator` or MCP `get_item_examples_from_registries` with "separator-demo" / "separator-example".
|
|
69
|
-
|
|
70
|
-
## When to use
|
|
71
|
-
Horizontal rule between related-but-distinct content, and the labeled "OR" divider
|
|
72
|
-
(pass children). Do not hand-roll `<hr>` or `<div className="border-t">`. It is
|
|
73
|
-
horizontal-only: for vertical dividers between adjacent controls use ButtonGroup,
|
|
74
|
-
which draws its own borders between items. Inside forms prefer `FieldSeparator`
|
|
75
|
-
from field.tsx, which wraps this same Separator with vertical padding and a
|
|
76
|
-
background-backed centered label.
|
|
77
|
-
|
|
78
|
-
## Gotchas
|
|
79
|
-
- Not the Radix/shadcn separator: no `orientation`, no `decorative` prop, so the
|
|
80
|
-
shadcn habit `orientation="vertical"` is a type error. `role="separator"` is
|
|
81
|
-
hardcoded, but props spread after it, so pass `role="presentation"` to make it
|
|
82
|
-
purely decorative.
|
|
83
|
-
- The line is a border, not a background bar: `h-0 border-t border-light` (shadcn
|
|
84
|
-
uses `h-px bg-border`). `bg-*` classes change nothing visible; recolor with
|
|
85
|
-
`border-*` classes.
|
|
86
|
-
- `className` lands on different elements per mode. Plain: on the line itself, so
|
|
87
|
-
`className="border-strong"` recolors it directly. Labeled: on the outer flex
|
|
88
|
-
wrapper while the two lines keep internal classes, so recolor them via a
|
|
89
|
-
descendant selector:
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
<Separator className="[&>span[aria-hidden]]:border-strong">OR</Separator>
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
- Any truthy `children` switches the render entirely: flex row with two flanking
|
|
96
|
-
`aria-hidden` line spans and a fixed `gap-3`.
|
|
97
|
-
- The label slot styling is fixed: `text-placeholder`, `text-ui-control-md`, and
|
|
98
|
-
every nested `<svg>` is forced to `size-6`. Drop in a bare icon as children;
|
|
99
|
-
manual icon size classes are overridden.
|