@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,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 />`.
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/status-badge.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/status-badge.md -->
|
|
2
|
-
|
|
3
|
-
# status-badge
|
|
4
|
-
|
|
5
|
-
Tiny presence dot only, no built-in label; 12 status colors and xs/sm/md sizes, place text beside it yourself
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add status-badge`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { StatusBadge } from "@/components/ui/status-badge"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `statusBadgeVariants`
|
|
16
|
-
|
|
17
|
-
## StatusBadge props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `primary \| danger \| success \| warning \| info \| highlighted \| away \| verified \| cyan \| lime \| neutral \| white` (Error tone is \"danger\" (there is no \"error\" or \"destructive\" key); \"white\" is the only variant that drops the built-in outline ring, for use on dark surfaces) | `primary` |
|
|
22
|
-
| size | `xs \| sm \| md` (Fixed pixel diameters (xs 4px, sm 6px, md 8px); standalone, no Field/InputGroup size cascade) | `md` |
|
|
23
|
-
|
|
24
|
-
Extends `React.ComponentProps<"span">`.
|
|
25
|
-
|
|
26
|
-
## Examples
|
|
27
|
-
|
|
28
|
-
From `status-badge-demo`:
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
import { StatusBadge } from "@/components/ui/status-badge"
|
|
32
|
-
|
|
33
|
-
export default function StatusBadgeDemo() {
|
|
34
|
-
return (
|
|
35
|
-
<div className="flex flex-wrap items-center gap-4">
|
|
36
|
-
<div className="flex items-center gap-2">
|
|
37
|
-
<StatusBadge variant="success" />
|
|
38
|
-
<span className="text-body text-sm">Online</span>
|
|
39
|
-
</div>
|
|
40
|
-
<div className="flex items-center gap-2">
|
|
41
|
-
<StatusBadge variant="away" />
|
|
42
|
-
<span className="text-body text-sm">Away</span>
|
|
43
|
-
</div>
|
|
44
|
-
<div className="flex items-center gap-2">
|
|
45
|
-
<StatusBadge variant="danger" />
|
|
46
|
-
<span className="text-body text-sm">Offline</span>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
From `status-badge-in-avatar`:
|
|
54
|
-
|
|
55
|
-
```tsx
|
|
56
|
-
import { StatusBadge } from "@/components/ui/status-badge"
|
|
57
|
-
|
|
58
|
-
export default function StatusBadgeInAvatar() {
|
|
59
|
-
return (
|
|
60
|
-
<div className="flex flex-wrap items-center gap-6">
|
|
61
|
-
<div className="relative">
|
|
62
|
-
<div className="from-light to-weak size-10 rounded-full bg-gradient-to-br" />
|
|
63
|
-
<StatusBadge variant="success" className="absolute right-0 bottom-0" />
|
|
64
|
-
</div>
|
|
65
|
-
<div className="relative">
|
|
66
|
-
<div className="from-light to-weak size-10 rounded-full bg-gradient-to-br" />
|
|
67
|
-
<StatusBadge variant="away" className="absolute right-0 bottom-0" />
|
|
68
|
-
</div>
|
|
69
|
-
<div className="relative">
|
|
70
|
-
<div className="from-light to-weak size-10 rounded-full bg-gradient-to-br" />
|
|
71
|
-
<StatusBadge variant="neutral" className="absolute right-0 bottom-0" />
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
More: `npx @create-ui/cli view status-badge` or MCP `get_item_examples_from_registries` with "status-badge-demo" / "status-badge-example".
|
|
79
|
-
|
|
80
|
-
## When to use
|
|
81
|
-
StatusBadge is a dot-only presence/state indicator (a single `<span role="status">` circle): online dots on avatars, live markers on rows, status legends. It carries no text; a sibling label or the host element gives it meaning. If the indicator needs a label or count use Badge, for transient events use Toast, and for loading use Spinner.
|
|
82
|
-
|
|
83
|
-
## Gotchas
|
|
84
|
-
- Do not pass children; the component renders a fixed-size dot (`size-1`/`1.5`/`2`, i.e. 4-8px) and any content would overflow the box. Render the label as a sibling in a flex row: `<StatusBadge variant="success" /> <span>Online</span>`.
|
|
85
|
-
- A white outline ring (`outline-static-white outline`) is built into every variant so the dot stays legible layered over avatars; only the `white` variant removes it (`outline-0`). Do not re-add `ring-*` or borders to fake this.
|
|
86
|
-
- Avatar pinning is manual composition: wrap the avatar in `relative` and position the badge with `className="absolute right-0 bottom-0"`. There is no `position`/anchor prop.
|
|
87
|
-
- This is not shadcn's `Badge`: no text slot and no `asChild`.
|
|
88
|
-
- `role="status"` is hardcoded, but the dot has no announced content, so pair it with a visible text label or put `aria-label` on the surrounding element.
|
|
89
|
-
- No `data-variant`/`data-size` attributes are emitted; CSS targeting goes through `data-slot="status-badge"` plus classes. `shrink-0` is built in, so it will not squash in tight flex rows.
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/switch-group.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/switch-group.md -->
|
|
2
|
-
|
|
3
|
-
# switch-group
|
|
4
|
-
|
|
5
|
-
Field wrapper that labels a Switch and cascades variant, size, shape, thumbType and ioTrigger; placement left or right
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add switch-group`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { SwitchGroup } from "@/components/ui/switch-group"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `switchGroupVariants`
|
|
16
|
-
|
|
17
|
-
## SwitchGroup props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `SwitchVariant` | `primary` |
|
|
22
|
-
| size | `xs \| sm \| md` (Sets the Field label scale and the child Switch size via context; Field's own size and orientation props are stripped from the API (orientation is locked horizontal)) | `md` |
|
|
23
|
-
| shape | `SwitchShape` | `pill` |
|
|
24
|
-
| thumbType | `SwitchThumbType` | `short` |
|
|
25
|
-
| ioTrigger | `boolean` | `false` |
|
|
26
|
-
| placement | `left \| right` (right is a CSS-only flip (flex-row-reverse); keep the Switch first in the DOM either way) | `left` |
|
|
27
|
-
|
|
28
|
-
Extends `React.ComponentProps<typeof Field>`.
|
|
29
|
-
|
|
30
|
-
## Examples
|
|
31
|
-
|
|
32
|
-
From `switch-group-demo`:
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { FieldContent } from "@/components/ui/field"
|
|
36
|
-
import { Label, LabelDescription, LabelMain } from "@/components/ui/label"
|
|
37
|
-
import { Switch } from "@/components/ui/switch"
|
|
38
|
-
import { SwitchGroup } from "@/components/ui/switch-group"
|
|
39
|
-
|
|
40
|
-
export default function SwitchGroupDemo() {
|
|
41
|
-
return (
|
|
42
|
-
<SwitchGroup className="w-[340px]">
|
|
43
|
-
<Switch id="sw-demo" defaultChecked />
|
|
44
|
-
<FieldContent>
|
|
45
|
-
<LabelMain>
|
|
46
|
-
<Label htmlFor="sw-demo">Push notifications</Label>
|
|
47
|
-
<LabelDescription>
|
|
48
|
-
Get alerts the moment something happens on your account.
|
|
49
|
-
</LabelDescription>
|
|
50
|
-
</LabelMain>
|
|
51
|
-
</FieldContent>
|
|
52
|
-
</SwitchGroup>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
From `switch-group-disabled`:
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
import { FieldContent } from "@/components/ui/field"
|
|
61
|
-
import { Label, LabelDescription, LabelMain } from "@/components/ui/label"
|
|
62
|
-
import { Switch } from "@/components/ui/switch"
|
|
63
|
-
import { SwitchGroup } from "@/components/ui/switch-group"
|
|
64
|
-
|
|
65
|
-
export default function SwitchGroupDisabled() {
|
|
66
|
-
return (
|
|
67
|
-
<div className="flex flex-col gap-6">
|
|
68
|
-
<SwitchGroup disabled className="w-[340px]">
|
|
69
|
-
<Switch id="sw-disabled-on" checked disabled />
|
|
70
|
-
<FieldContent>
|
|
71
|
-
<LabelMain>
|
|
72
|
-
<Label htmlFor="sw-disabled-on">Push notifications</Label>
|
|
73
|
-
<LabelDescription>
|
|
74
|
-
Disabled state cascades to label and description.
|
|
75
|
-
</LabelDescription>
|
|
76
|
-
</LabelMain>
|
|
77
|
-
</FieldContent>
|
|
78
|
-
</SwitchGroup>
|
|
79
|
-
|
|
80
|
-
<SwitchGroup disabled className="w-[340px]">
|
|
81
|
-
<Switch id="sw-disabled-off" checked={false} disabled />
|
|
82
|
-
<FieldContent>
|
|
83
|
-
<LabelMain>
|
|
84
|
-
<Label htmlFor="sw-disabled-off">Marketing emails</Label>
|
|
85
|
-
<LabelDescription>
|
|
86
|
-
The unchecked row reads muted too.
|
|
87
|
-
</LabelDescription>
|
|
88
|
-
</LabelMain>
|
|
89
|
-
</FieldContent>
|
|
90
|
-
</SwitchGroup>
|
|
91
|
-
</div>
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
More: `npx @create-ui/cli view switch-group` or MCP `get_item_examples_from_registries` with "switch-group-demo" / "switch-group-example".
|
|
97
|
-
|
|
98
|
-
## When to use
|
|
99
|
-
One labelled switch row for settings that apply the moment they flip: notification preferences, feature flags, privacy toggles. Stack several SwitchGroups in a column for a settings panel. Do NOT use it inside a submit-to-save form (use CheckboxGroup), for one-of-many selection (use RadioGroup), or for a bare unlabelled toggle in a toolbar or table cell (use Switch directly).
|
|
100
|
-
|
|
101
|
-
## Gotchas
|
|
102
|
-
- Despite the name, SwitchGroup is a single row, not a multi-switch container, and it renders no Switch of its own. There is no SwitchGroupItem; you compose the anatomy yourself:
|
|
103
|
-
|
|
104
|
-
```tsx
|
|
105
|
-
<SwitchGroup>
|
|
106
|
-
<Switch id="x" />
|
|
107
|
-
<FieldContent>
|
|
108
|
-
<LabelMain>
|
|
109
|
-
<Label htmlFor="x">Title</Label>
|
|
110
|
-
<LabelDescription>Optional helper.</LabelDescription>
|
|
111
|
-
</LabelMain>
|
|
112
|
-
<FieldFooter>{/* optional, e.g. TextLink */}</FieldFooter>
|
|
113
|
-
</FieldContent>
|
|
114
|
-
</SwitchGroup>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
- The child Switch resolves each look prop as explicit prop ?? SwitchContext ?? default, so any prop set directly on the Switch silently overrides the group; configure looks on the group and keep the Switch bare except id/checked/disabled.
|
|
118
|
-
- The context the group provides carries variant, size, shape, thumbType, ioTrigger only. SwitchGroup has no thumbIcon prop and never forwards one; set thumbIcon on the Switch itself.
|
|
119
|
-
- Label association is manual: the Field root is a role="group" div, not a label, so always pair Switch id with Label htmlFor.
|
|
120
|
-
- For a disabled row, set disabled on BOTH the group (label/description fade via Field) and the child Switch (the actual control), as in switch-group-disabled.
|
|
121
|
-
- The label block must sit inside FieldContent: Field only top-aligns the switch when a direct [data-slot=field-content] child exists (has-[] selector), so loose Label siblings sit in a row and break the stacking.
|
|
122
|
-
- SwitchGroup is a Field, so its root is full-width: placed inline (e.g. the right side of a justify-between header or toolbar) it wraps onto its own full-width line unless you constrain it with an explicit width (className="w-auto", max-w-*, or a fixed width).
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/switch.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/switch.md -->
|
|
2
|
-
|
|
3
|
-
# switch
|
|
4
|
-
|
|
5
|
-
Toggle switch; variant primary/info/neutral/inverse/semantic, thumbType short/long, ioTrigger and thumbIcon options
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add switch`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { Switch } from "@/components/ui/switch"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `SwitchContext`, `switchVariants`
|
|
16
|
-
|
|
17
|
-
## Switch props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `primary \| info \| neutral \| inverse \| semantic` (semantic = red when off, green when on (accept/reject patterns)) | `primary` |
|
|
22
|
-
| size | `md \| sm \| xs` | `md` |
|
|
23
|
-
| shape | `pill \| rounded` | `pill` |
|
|
24
|
-
| thumbType | `short \| long` (long is a statically wider thumb and track; checked travel distance is unchanged) | `short` |
|
|
25
|
-
| ioTrigger | `boolean` (aria-hidden I/O glyphs in the track: line when on, circle when off) | `false` |
|
|
26
|
-
| thumbIcon | `boolean` (aria-hidden check/close icons inside the thumb) | `false` |
|
|
27
|
-
|
|
28
|
-
Extends `React.ComponentProps<typeof SwitchPrimitive.Root>`.
|
|
29
|
-
|
|
30
|
-
## Examples
|
|
31
|
-
|
|
32
|
-
From `switch-demo`:
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { Switch } from "@/components/ui/switch"
|
|
36
|
-
|
|
37
|
-
export default function SwitchDemo() {
|
|
38
|
-
return (
|
|
39
|
-
<div className="flex items-center gap-3">
|
|
40
|
-
<Switch defaultChecked />
|
|
41
|
-
<Switch />
|
|
42
|
-
</div>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
From `switch-thumb-icon`:
|
|
48
|
-
|
|
49
|
-
```tsx
|
|
50
|
-
import { Switch } from "@/components/ui/switch"
|
|
51
|
-
|
|
52
|
-
export default function SwitchThumbIcon() {
|
|
53
|
-
return (
|
|
54
|
-
<div className="flex items-center gap-4">
|
|
55
|
-
<Switch thumbIcon defaultChecked />
|
|
56
|
-
<Switch thumbIcon />
|
|
57
|
-
</div>
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
More: `npx @create-ui/cli view switch` or MCP `get_item_examples_from_registries` with "switch-demo" / "switch-example".
|
|
63
|
-
|
|
64
|
-
## When to use
|
|
65
|
-
|
|
66
|
-
A single standalone on/off control. A boolean that only commits on form submit is `Checkbox`. A switch with a label and description in one apply-immediately row is `SwitchGroup` (it wraps `Field orientation="horizontal"` and feeds `SwitchContext`); do not hand-roll that row from `Field` + `Switch`. Exception: inside a submit-to-save form that deliberately uses toggles, `SwitchGroup` is wrong - compose `Field size="md" orientation="horizontal"` + `FieldContent` (`FieldLabel` + `FieldDescription`) + `Switch`, as in the field-composition example.
|
|
67
|
-
|
|
68
|
-
## Gotchas
|
|
69
|
-
|
|
70
|
-
- Every visual prop resolves `prop ?? SwitchContext ?? default`. `SwitchGroup` provides context for `variant`/`size`/`shape`/`thumbType`/`ioTrigger`, so set those on the group, not the inner Switch. `thumbIcon` is NOT in the group context; set it on the Switch itself. For an ad-hoc cluster, wrap in the exported `SwitchContext.Provider`.
|
|
71
|
-
- `Field` size does NOT cascade here: Switch reads only `SwitchContext`, never Field's context. In a plain `Field` row, set `size` on the Switch itself.
|
|
72
|
-
- Do not pass children to `<Switch>`; it renders its own thumb/icon internals and silently replaces anything you pass. The label lives outside (`Label htmlFor` + `id`, or `aria-label`).
|
|
73
|
-
- Track width is a fixed pixel value per `size` x `thumbType`, and the checked `translate-x` is fixed per `size` (22/18/14px). Overriding width via `className` desyncs the thumb travel; change `size`/`thumbType` instead.
|
|
74
|
-
- The clickable area is silently enlarged by an `after:` pseudo-element (12px horizontally, 8px vertically past the track); keep other clickable controls clear of that zone.
|
|
75
|
-
- Error state comes from passing `aria-invalid` (persistent red outline), not from a variant.
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE - do not edit. Source: registry/ui/tab-menu.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/tab-menu.md -->
|
|
2
|
-
|
|
3
|
-
# tab-menu
|
|
4
|
-
|
|
5
|
-
Navigation tab list with no content panels; vertical/horizontal button and line variants, leadingIcon/trailingIcon items
|
|
6
|
-
|
|
7
|
-
Install: `npx @create-ui/cli add tab-menu`
|
|
8
|
-
|
|
9
|
-
## Import
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { TabMenu, TabMenuItem } from "@/components/ui/tab-menu"
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Also exported: `tabMenuVariants`, `tabMenuItemVariants`
|
|
16
|
-
|
|
17
|
-
## TabMenu props
|
|
18
|
-
|
|
19
|
-
| Prop | Type | Default |
|
|
20
|
-
| --- | --- | --- |
|
|
21
|
-
| variant | `vertical-button \| vertical-line \| horizontal-line \| horizontal-button` | `vertical-button` |
|
|
22
|
-
| size | `sm \| md \| lg` | `md` |
|
|
23
|
-
| indicator | `left \| top \| bottom` (line variants render no active line without it; designed pairings: vertical-button+left, vertical-line/horizontal-line+top|bottom; horizontal-button takes none) | - |
|
|
24
|
-
| value | `string` | - |
|
|
25
|
-
| defaultValue | `string` | - |
|
|
26
|
-
| onValueChange | `(value: string) => void` | - |
|
|
27
|
-
|
|
28
|
-
Extends `React.ComponentProps<"div">`.
|
|
29
|
-
|
|
30
|
-
## TabMenuItem props
|
|
31
|
-
|
|
32
|
-
| Prop | Type | Default |
|
|
33
|
-
| --- | --- | --- |
|
|
34
|
-
| asChild | `boolean` | `false` |
|
|
35
|
-
| value | `string` | - |
|
|
36
|
-
| selected | `boolean` (overrides value matching; use for route-driven tabs where the pathname decides) | - |
|
|
37
|
-
| leadingIcon | `ReactNode` | - |
|
|
38
|
-
| trailingIcon | `ReactNode` | - |
|
|
39
|
-
| label | `ReactNode` (the label slot; bare children are NOT the label (they render as extra content next to it, e.g. a Badge)) | - |
|
|
40
|
-
|
|
41
|
-
Extends `React.ComponentProps<"button">`.
|
|
42
|
-
|
|
43
|
-
## Icons
|
|
44
|
-
|
|
45
|
-
Icons go through icon props - never as children next to text, and never with sizing classes (the component sizes icons per `size`): `TabMenuItem` (`leadingIcon` / `trailingIcon`). Import icons from `@create-ui/assets/icons` (Remix `Ri*`).
|
|
46
|
-
|
|
47
|
-
## Examples
|
|
48
|
-
|
|
49
|
-
From `tab-menu-demo`:
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
import {
|
|
53
|
-
RiBankCardFill,
|
|
54
|
-
RiInboxLine,
|
|
55
|
-
RiInformationFill,
|
|
56
|
-
RiSettings6Fill,
|
|
57
|
-
} from "@create-ui/assets/icons"
|
|
58
|
-
|
|
59
|
-
import { TabMenu, TabMenuItem } from "@/components/ui/tab-menu"
|
|
60
|
-
|
|
61
|
-
export default function TabMenuDemo() {
|
|
62
|
-
return (
|
|
63
|
-
<TabMenu
|
|
64
|
-
variant="horizontal-line"
|
|
65
|
-
indicator="bottom"
|
|
66
|
-
size="lg"
|
|
67
|
-
defaultValue="activity"
|
|
68
|
-
>
|
|
69
|
-
<TabMenuItem
|
|
70
|
-
value="overview"
|
|
71
|
-
leadingIcon={<RiInformationFill />}
|
|
72
|
-
label="Overview"
|
|
73
|
-
/>
|
|
74
|
-
<TabMenuItem
|
|
75
|
-
value="activity"
|
|
76
|
-
leadingIcon={<RiInboxLine />}
|
|
77
|
-
label="Activity"
|
|
78
|
-
/>
|
|
79
|
-
<TabMenuItem
|
|
80
|
-
value="billing"
|
|
81
|
-
leadingIcon={<RiBankCardFill />}
|
|
82
|
-
label="Billing"
|
|
83
|
-
/>
|
|
84
|
-
<TabMenuItem
|
|
85
|
-
value="settings"
|
|
86
|
-
leadingIcon={<RiSettings6Fill />}
|
|
87
|
-
label="Settings"
|
|
88
|
-
/>
|
|
89
|
-
</TabMenu>
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
From `tab-menu-with-badge`:
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
import {
|
|
98
|
-
RiBankCardFill,
|
|
99
|
-
RiInboxLine,
|
|
100
|
-
RiSettings6Fill,
|
|
101
|
-
} from "@create-ui/assets/icons"
|
|
102
|
-
|
|
103
|
-
import { Badge } from "@/components/ui/badge"
|
|
104
|
-
import { StatusBadge } from "@/components/ui/status-badge"
|
|
105
|
-
import { TabMenu, TabMenuItem } from "@/components/ui/tab-menu"
|
|
106
|
-
|
|
107
|
-
export default function TabMenuWithBadge() {
|
|
108
|
-
return (
|
|
109
|
-
<TabMenu
|
|
110
|
-
className="w-[320px]"
|
|
111
|
-
variant="vertical-button"
|
|
112
|
-
size="lg"
|
|
113
|
-
defaultValue="activity"
|
|
114
|
-
>
|
|
115
|
-
<TabMenuItem
|
|
116
|
-
value="activity"
|
|
117
|
-
leadingIcon={<RiInboxLine />}
|
|
118
|
-
label="Activity"
|
|
119
|
-
>
|
|
120
|
-
<Badge variant="info" appearance="soft" size="sm">
|
|
121
|
-
12
|
|
122
|
-
</Badge>
|
|
123
|
-
</TabMenuItem>
|
|
124
|
-
<TabMenuItem
|
|
125
|
-
value="billing"
|
|
126
|
-
leadingIcon={<RiBankCardFill />}
|
|
127
|
-
label="Billing"
|
|
128
|
-
>
|
|
129
|
-
<Badge variant="success" appearance="soft" size="sm">
|
|
130
|
-
New
|
|
131
|
-
</Badge>
|
|
132
|
-
</TabMenuItem>
|
|
133
|
-
<TabMenuItem
|
|
134
|
-
value="settings"
|
|
135
|
-
leadingIcon={<RiSettings6Fill />}
|
|
136
|
-
label="Settings"
|
|
137
|
-
>
|
|
138
|
-
<StatusBadge variant="primary" size="md" />
|
|
139
|
-
</TabMenuItem>
|
|
140
|
-
</TabMenu>
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
More: `npx @create-ui/cli view tab-menu` or MCP `get_item_examples_from_registries` with "tab-menu-demo" / "tab-menu-example".
|
|
146
|
-
|
|
147
|
-
## When to use
|
|
148
|
-
|
|
149
|
-
Tab-style navigation: settings sidebars, section switchers, routed nav as links. TabMenu renders the tab list only; there are no content-panel components, so render panels yourself keyed by the active value (`{tab === "billing" && <BillingPanel />}`). For 2-5 inline mutually exclusive options without rich item content, use SegmentedControl instead.
|
|
150
|
-
|
|
151
|
-
## Gotchas
|
|
152
|
-
|
|
153
|
-
- There is no shadcn-style `Tabs` / `TabsList` / `TabsTrigger` / `TabsContent` set; do not invent one. `TabMenu` itself owns the value (`defaultValue`, or controlled `value` + `onValueChange`) and that is the whole API.
|
|
154
|
-
- Text goes in the `label` prop; bare children are NOT the label, they render as extra content beside it (the badge slot, see tab-menu-with-badge). Icons only via `leadingIcon` / `trailingIcon`, never as children.
|
|
155
|
-
- `asChild` needs exactly one non-Fragment element child or it silently falls back to a plain `<button>`. The child's own text becomes the label (`label` is only a fallback when the child has no children) and the extra-children badge slot is unavailable; icons stay as props on `TabMenuItem`:
|
|
156
|
-
|
|
157
|
-
```tsx
|
|
158
|
-
<TabMenuItem asChild value="billing" leadingIcon={<RiBankCardFill />}>
|
|
159
|
-
<Link href="/billing">Billing</Link>
|
|
160
|
-
</TabMenuItem>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
- Line variants show no active marker beyond text color unless `indicator` is set; button variants (`vertical-button`, `horizontal-button`) get the sliding `bg-weak` pill automatically.
|
|
164
|
-
- This is not ARIA tabs: a `role="group"` of `aria-pressed` buttons where every item is its own Tab stop; there is no arrow-key roving like Radix Tabs. asChild items get no `aria-pressed`; their `disabled` maps to `aria-disabled` + `tabIndex={-1}`.
|
|
165
|
-
- An item `onClick` that calls `event.preventDefault()` blocks the value commit; `disabled` items skip both `onClick` and `onValueChange`.
|