@create-ui/cli 0.6.0 → 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 +16 -16
- 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 -52
- 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/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/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,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.
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/social-login-button.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/social-login-button.md -->
|
|
2
|
-
|
|
3
|
-
# social-login-button
|
|
4
|
-
|
|
5
|
-
OAuth sign-in button for 13 brands like Google, Apple and GitHub plus custom; colorful/black/white appearance, iconOnly
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add social-login-button`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { SocialLoginButton } from "@/components/ui/social-login-button"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `socialLoginButtonVariants`
|
|
16
|
-
|
|
17
|
-
## SocialLoginButton props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| size | `lg \| md` | `lg` |
|
|
22
|
-
| shape | `rounded \| pill \| square` | `rounded` |
|
|
23
|
-
| iconOnly | `boolean` (Removes the visible label, leaving no accessible name; always pass aria-label) | `false` |
|
|
24
|
-
| appearance | `colorful \| black \| white` (Defaults to colorful (literal brand-colored background); the generated table misses this default) | - |
|
|
25
|
-
| asChild | `boolean` (The slotted child's own children are REPLACED by the injected icon+label; slot an empty <a> carrying href/aria-label) | - |
|
|
26
|
-
| brand | `apple \| behance \| discord \| dribbble \| facebook \| github \| gitlab \| google \| linkedin \| microsoft \| slack \| sso \| x \| custom` (Also fixes the copy: rendered text is always 'Continue with {label}'; custom wording only via brand=\"custom\" config.label, and only the brand-name part (the 'Continue with' prefix is hard-coded)) | - |
|
|
27
|
-
| config | `{ icon: IconComponent label?: string color?: string }` (Only accepted with brand=\"custom\" (discriminated union). The icon gets no fill, just the appearance text color (white on colorful, theme text on black/white), so draw it with currentColor) | - |
|
|
28
|
-
|
|
29
|
-
Extends `React.ComponentProps<"button">`.
|
|
30
|
-
|
|
31
|
-
## Icons
|
|
32
|
-
|
|
33
|
-
Icons go through icon props - never as children next to text, and never with sizing classes (the component sizes icons per `size`): `SocialLoginButton` (). Import icons from `@create-ui/assets/icons` (Remix `Ri*`).
|
|
34
|
-
|
|
35
|
-
## Examples
|
|
36
|
-
|
|
37
|
-
From `social-login-button-demo`:
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import { SocialLoginButton } from "@/components/ui/social-login-button"
|
|
41
|
-
|
|
42
|
-
export default function SocialLoginButtonDemo() {
|
|
43
|
-
return (
|
|
44
|
-
<div className="flex w-full flex-col items-center justify-center gap-3">
|
|
45
|
-
<div className="flex flex-wrap items-center justify-center gap-2">
|
|
46
|
-
<SocialLoginButton brand="google" appearance="white" />
|
|
47
|
-
<SocialLoginButton brand="apple" appearance="white" />
|
|
48
|
-
</div>
|
|
49
|
-
<div className="flex flex-wrap items-center justify-center gap-2">
|
|
50
|
-
<SocialLoginButton brand="dribbble" shape="pill" />
|
|
51
|
-
<SocialLoginButton brand="x" shape="pill" />
|
|
52
|
-
</div>
|
|
53
|
-
<div className="flex flex-wrap items-center justify-center gap-2">
|
|
54
|
-
<SocialLoginButton
|
|
55
|
-
brand="google"
|
|
56
|
-
iconOnly
|
|
57
|
-
aria-label="Continue with Google"
|
|
58
|
-
/>
|
|
59
|
-
<SocialLoginButton
|
|
60
|
-
brand="apple"
|
|
61
|
-
appearance="black"
|
|
62
|
-
iconOnly
|
|
63
|
-
aria-label="Continue with Apple"
|
|
64
|
-
/>
|
|
65
|
-
<SocialLoginButton
|
|
66
|
-
brand="github"
|
|
67
|
-
appearance="white"
|
|
68
|
-
iconOnly
|
|
69
|
-
aria-label="Continue with Github"
|
|
70
|
-
/>
|
|
71
|
-
<SocialLoginButton
|
|
72
|
-
brand="dribbble"
|
|
73
|
-
shape="pill"
|
|
74
|
-
iconOnly
|
|
75
|
-
aria-label="Continue with Dribbble"
|
|
76
|
-
/>
|
|
77
|
-
<SocialLoginButton
|
|
78
|
-
brand="x"
|
|
79
|
-
shape="pill"
|
|
80
|
-
iconOnly
|
|
81
|
-
aria-label="Continue with X"
|
|
82
|
-
/>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
From `social-login-button-as-child`:
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
"use client"
|
|
93
|
-
|
|
94
|
-
import { SocialLoginButton } from "@/components/ui/social-login-button"
|
|
95
|
-
|
|
96
|
-
export default function SocialLoginButtonAsChild() {
|
|
97
|
-
return (
|
|
98
|
-
<div className="flex flex-wrap justify-center gap-2">
|
|
99
|
-
<SocialLoginButton asChild brand="google">
|
|
100
|
-
<a href="#" aria-label="Continue with Google" />
|
|
101
|
-
</SocialLoginButton>
|
|
102
|
-
<SocialLoginButton asChild brand="apple" appearance="black">
|
|
103
|
-
<a href="#" aria-label="Continue with Apple" />
|
|
104
|
-
</SocialLoginButton>
|
|
105
|
-
<SocialLoginButton asChild brand="github" appearance="white">
|
|
106
|
-
<a href="#" aria-label="Continue with Github" />
|
|
107
|
-
</SocialLoginButton>
|
|
108
|
-
</div>
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
More: `npx @create-ui/cli view social-login-button` or MCP `get_item_examples_from_registries` with "social-login-button-demo" / "social-login-button-example".
|
|
114
|
-
|
|
115
|
-
## When to use
|
|
116
|
-
Branded "Continue with X" buttons for OAuth/SSO sign-in and sign-up flows: preset brands plus brand="custom" with a config object. Do NOT use it for generic CTAs (use Button), app/extension store links (use AppStoreBadge), or passive brand chips (use Badge).
|
|
117
|
-
|
|
118
|
-
## Gotchas
|
|
119
|
-
- Children are ignored unless asChild: `<SocialLoginButton brand="google">Sign in</SocialLoginButton>` silently drops "Sign in" (children are destructured out and never rendered); the label always comes from the brand config.
|
|
120
|
-
- Ignore the generated Icons section: there are NO leadingIcon/trailingIcon/icon props. The glyph is auto-picked per brand AND appearance: white glyph on colorful; under black/white appearances most brands keep their full-color glyph, and only brands with a theme-aware mono asset (apple, github, x) swap. Custom icons go through config.icon only.
|
|
121
|
-
- asChild is not shadcn-Button-style Slot passthrough: the component clones the slotted child and REPLACES its children with the icon+label content:
|
|
122
|
-
|
|
123
|
-
```tsx
|
|
124
|
-
<SocialLoginButton asChild brand="google">
|
|
125
|
-
<a href="/auth/google" aria-label="Continue with Google" />
|
|
126
|
-
</SocialLoginButton>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
- Non-iconOnly buttons have fixed widths (w-[300px] at lg, w-[250px] at md) so provider stacks align. For full-width auth forms pass className="w-full"; cn() merges it over the CVA width.
|
|
130
|
-
- appearance="colorful" pins the literal brand color and static black/white tokens, so it does NOT flip in dark mode; only the sso preset defines a dark variant. black/white appearances use semantic tokens and do flip with the theme.
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/spinner.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/spinner.md -->
|
|
2
|
-
|
|
3
|
-
# spinner
|
|
4
|
-
|
|
5
|
-
Loading indicator with a conic-gradient arc; 12 color variants, solid/gradient appearance, spin/pulse/tick animations
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add spinner`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { Spinner } from "@/components/ui/spinner"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `spinnerVariants`
|
|
16
|
-
|
|
17
|
-
## Spinner props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `primary \| info \| success \| warning \| danger \| away \| neutral \| neutral-static \| neutral-soft \| inverse \| inverse-static \| inverse-soft` | `primary` |
|
|
22
|
-
| appearance | `solid \| gradient` | `gradient` |
|
|
23
|
-
| cap | `sharp \| rounded` (Visual effect only with appearance=\"solid\" (rounded caps render as separate dot elements); with gradient appearance the prop only sets the data-cap attribute.) | `rounded` |
|
|
24
|
-
| line | `short \| long` | `long` |
|
|
25
|
-
| animation | `spin \| pulse \| tick` | `pulse` |
|
|
26
|
-
| size | `xs \| sm \| md \| lg` (Also scales the arc stroke width via inline styles (1px at xs up to 2px at lg); the stroke cannot be restyled through className.) | `sm` |
|
|
27
|
-
|
|
28
|
-
Extends `React.ComponentProps<"div">`.
|
|
29
|
-
|
|
30
|
-
## Examples
|
|
31
|
-
|
|
32
|
-
From `spinner-demo`:
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { Spinner } from "@/components/ui/spinner"
|
|
36
|
-
|
|
37
|
-
export default function SpinnerDemo() {
|
|
38
|
-
return <Spinner size="lg" />
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
From `spinner-appearance`:
|
|
43
|
-
|
|
44
|
-
```tsx
|
|
45
|
-
import { Spinner } from "@/components/ui/spinner"
|
|
46
|
-
|
|
47
|
-
export default function SpinnerAppearance() {
|
|
48
|
-
return (
|
|
49
|
-
<div className="flex flex-wrap items-center gap-6">
|
|
50
|
-
<Spinner appearance="gradient" animation="spin" size="lg" />
|
|
51
|
-
<Spinner appearance="solid" animation="spin" size="lg" />
|
|
52
|
-
</div>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
More: `npx @create-ui/cli view spinner` or MCP `get_item_examples_from_registries` with "spinner-demo" / "spinner-example".
|
|
58
|
-
|
|
59
|
-
## When to use
|
|
60
|
-
Indeterminate in-flight work: saves, network calls, slow validation, page bootstrapping. Do NOT use it when progress is measurable (use Progress) or for a loading button (use Button's `loading` prop, which renders the Spinner, blocks interaction, and sets `aria-busy` for you - never compose `<Spinner />` + `disabled` by hand).
|
|
61
|
-
|
|
62
|
-
## Gotchas
|
|
63
|
-
- This is NOT the shadcn `Loader2` + `animate-spin` pattern. It is a pure-CSS `<div>` (conic-gradient + mask, zero SVG). Never reach for lucide icons or `animate-spin` utilities; render `<Spinner />`.
|
|
64
|
-
- `children` is excluded at the type level (`Omit<..., "children">`). It draws its own arc; put visible copy ("Saving...") next to it, not inside it.
|
|
65
|
-
- The arc and caps track `currentColor`: `variant` applies a `text-*` token class, so `className="text-emerald-500"` (merged last via `cn()`) recolors them. The solid track ring does NOT follow `currentColor` - its `bg-*` color always comes from `variant`.
|
|
66
|
-
- The background track ring only renders when `appearance="solid"`; the default `gradient` has no track and its arc tail fades to transparent.
|
|
67
|
-
- Sets `role="status"` and `aria-label="Loading"` automatically; pass your own `aria-label` for specific operations.
|
|
68
|
-
- The exported `spinnerVariants` CVA defaults `size` to `lg`, but the `Spinner` component prop defaults to `sm`. Calling `spinnerVariants()` directly yields a different size than `<Spinner />`.
|