@create-ui/cli 0.5.7 → 0.5.9

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.
Files changed (71) hide show
  1. package/dist/{chunk-RMTTHCB3.js → chunk-2ELKDGGM.js} +3 -3
  2. package/dist/{chunk-RMTTHCB3.js.map → chunk-2ELKDGGM.js.map} +1 -1
  3. package/dist/chunk-643QI2I2.js +102 -0
  4. package/dist/chunk-643QI2I2.js.map +1 -0
  5. package/dist/{chunk-NQFMXHMH.js → chunk-KQTXDVKV.js} +3 -3
  6. package/dist/chunk-KQTXDVKV.js.map +1 -0
  7. package/dist/index.js +35 -35
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp/index.js +1 -1
  10. package/dist/registry/index.js +1 -1
  11. package/dist/skills/createui/SKILL.md +201 -177
  12. package/dist/skills/createui/agents/openai.yml +1 -1
  13. package/dist/skills/createui/cli.md +42 -42
  14. package/dist/skills/createui/customization.md +20 -15
  15. package/dist/skills/createui/evals/evals.json +68 -5
  16. package/dist/skills/createui/mcp.md +14 -5
  17. package/dist/skills/createui/reference/accordion.md +127 -0
  18. package/dist/skills/createui/reference/app-store-badge.md +88 -0
  19. package/dist/skills/createui/reference/aspect-ratio.md +52 -0
  20. package/dist/skills/createui/reference/avatar.md +230 -0
  21. package/dist/skills/createui/reference/badge.md +110 -0
  22. package/dist/skills/createui/reference/breadcrumb.md +153 -0
  23. package/dist/skills/createui/reference/button-group.md +116 -0
  24. package/dist/skills/createui/reference/button.md +104 -0
  25. package/dist/skills/createui/reference/checkbox-group.md +118 -0
  26. package/dist/skills/createui/reference/checkbox.md +79 -0
  27. package/dist/skills/createui/reference/chip.md +115 -0
  28. package/dist/skills/createui/reference/close-button.md +83 -0
  29. package/dist/skills/createui/reference/command.md +69 -0
  30. package/dist/skills/createui/reference/country-flag.md +109 -0
  31. package/dist/skills/createui/reference/credit-card-input.md +76 -0
  32. package/dist/skills/createui/reference/date-input.md +71 -0
  33. package/dist/skills/createui/reference/dropdown-menu.md +164 -0
  34. package/dist/skills/createui/reference/field.md +186 -0
  35. package/dist/skills/createui/reference/info-tooltip.md +110 -0
  36. package/dist/skills/createui/reference/inline-alert.md +146 -0
  37. package/dist/skills/createui/reference/input-group.md +171 -0
  38. package/dist/skills/createui/reference/input-otp.md +130 -0
  39. package/dist/skills/createui/reference/input-stepper.md +120 -0
  40. package/dist/skills/createui/reference/input.md +118 -0
  41. package/dist/skills/createui/reference/label.md +121 -0
  42. package/dist/skills/createui/reference/pagination.md +157 -0
  43. package/dist/skills/createui/reference/password-strength.md +70 -0
  44. package/dist/skills/createui/reference/phone-input.md +77 -0
  45. package/dist/skills/createui/reference/progress.md +158 -0
  46. package/dist/skills/createui/reference/radio-group.md +133 -0
  47. package/dist/skills/createui/reference/radio.md +79 -0
  48. package/dist/skills/createui/reference/scroll-area.md +212 -0
  49. package/dist/skills/createui/reference/segmented-control.md +146 -0
  50. package/dist/skills/createui/reference/select.md +204 -0
  51. package/dist/skills/createui/reference/separator.md +99 -0
  52. package/dist/skills/createui/reference/social-login-button.md +130 -0
  53. package/dist/skills/createui/reference/spinner.md +68 -0
  54. package/dist/skills/createui/reference/status-badge.md +89 -0
  55. package/dist/skills/createui/reference/switch-group.md +122 -0
  56. package/dist/skills/createui/reference/switch.md +75 -0
  57. package/dist/skills/createui/reference/tab-menu.md +165 -0
  58. package/dist/skills/createui/reference/text-link.md +84 -0
  59. package/dist/skills/createui/reference/textarea.md +50 -0
  60. package/dist/skills/createui/reference/toast.md +162 -0
  61. package/dist/skills/createui/reference/tooltip.md +63 -0
  62. package/dist/skills/createui/rules/composition.md +41 -25
  63. package/dist/skills/createui/rules/design.md +266 -0
  64. package/dist/skills/createui/rules/forms.md +44 -15
  65. package/dist/skills/createui/rules/icons.md +64 -18
  66. package/dist/skills/createui/rules/styling.md +53 -14
  67. package/dist/utils/index.js +1 -1
  68. package/package.json +1 -1
  69. package/dist/chunk-M5DYT2NE.js +0 -64
  70. package/dist/chunk-M5DYT2NE.js.map +0 -1
  71. package/dist/chunk-NQFMXHMH.js.map +0 -1
@@ -0,0 +1,171 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/input-group.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/input-group.md -->
2
+
3
+ # input-group
4
+
5
+ Composable input shell with slots for icons, addons, selects, buttons, kbd hints and card badges around the control
6
+
7
+ Install: `npx @create-ui/cli add input-group`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { InputGroup, InputGroupProvider, InputGroupShell, InputGroupSlot, InputGroupControl, InputGroupTextarea, InputGroupToolbar, InputGroupLeadingIcon, InputGroupAddon, InputGroupSelect, InputGroupButton, InputGroupCard, InputGroupKbd, InputGroupHelperIcon, InputGroupField } from "@/components/ui/input-group"
13
+ ```
14
+
15
+ Also exported: `useInputGroup`, `useOptionalInputGroup`
16
+
17
+ ## InputGroup props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | size | `InputSize` (xs | sm | md (the InputSize scale); usually inherited from Field - set it once there) | - |
22
+ | invalid | `boolean` | - |
23
+ | disabled | `boolean` | - |
24
+ | loading | `boolean` | - |
25
+ | multiline | `boolean` (switches the shell to flex-col; pair with InputGroupTextarea instead of InputGroupControl) | - |
26
+
27
+ Extends `React.ComponentProps<"div">`.
28
+
29
+ ## InputGroupProvider props
30
+
31
+ | Prop | Type | Default |
32
+ | --- | --- | --- |
33
+ | size | `InputSize` (xs | sm | md (the InputSize scale); usually inherited from Field - set it once there) | `sm` |
34
+ | invalid | `boolean` | - |
35
+ | disabled | `boolean` | `false` |
36
+ | loading | `boolean` | `false` |
37
+ | children | `ReactNode` | - |
38
+
39
+ ## InputGroupToolbar props
40
+
41
+ | Prop | Type | Default |
42
+ | --- | --- | --- |
43
+ | position | `start \| end \| between` | - |
44
+
45
+ Extends `React.ComponentProps<"div">`.
46
+
47
+ ## InputGroupSelect props
48
+
49
+ | Prop | Type | Default |
50
+ | --- | --- | --- |
51
+ | className | `string` | - |
52
+ | triggerClassName | `string` | - |
53
+ | placeholder | `ReactNode` | - |
54
+ | prefix | `ReactNode` | - |
55
+ | valueChildren | `ReactNode` | - |
56
+ | aria-label | `string` | - |
57
+ | aria-labelledby | `string` | - |
58
+
59
+ Extends `React.ComponentProps<typeof Select>`.
60
+
61
+ ## InputGroupHelperIcon props
62
+
63
+ | Prop | Type | Default |
64
+ | --- | --- | --- |
65
+ | invalidIcon | `ReactNode` | - |
66
+
67
+ Extends `React.ComponentProps<"span">`.
68
+
69
+ ## InputGroupField props
70
+
71
+ | Prop | Type | Default |
72
+ | --- | --- | --- |
73
+ | label | `ReactNode` | - |
74
+ | description | `ReactNode` | - |
75
+ | error | `ReactNode` | - |
76
+ | size | `InputSize` (xs | sm | md (the InputSize scale); usually inherited from Field - set it once there) | `sm` |
77
+ | disabled | `boolean` | - |
78
+ | children | `ReactNode` | - |
79
+
80
+ Extends `React.ComponentProps<"div">`.
81
+
82
+ ## Examples
83
+
84
+ From `input-group-demo`:
85
+
86
+ ```tsx
87
+ import { RiSearch2Line } from "@create-ui/assets/icons"
88
+
89
+ import {
90
+ InputGroup,
91
+ InputGroupButton,
92
+ InputGroupControl,
93
+ InputGroupKbd,
94
+ InputGroupSlot,
95
+ } from "@/components/ui/input-group"
96
+
97
+ export default function InputGroupDemo() {
98
+ return (
99
+ <InputGroup className="max-w-md">
100
+ <InputGroupSlot>
101
+ <RiSearch2Line />
102
+ <InputGroupControl placeholder="Search anything…" />
103
+ <InputGroupKbd>K</InputGroupKbd>
104
+ </InputGroupSlot>
105
+ <InputGroupButton>Search</InputGroupButton>
106
+ </InputGroup>
107
+ )
108
+ }
109
+ ```
110
+
111
+ From `input-group-with-select`:
112
+
113
+ ```tsx
114
+ "use client"
115
+
116
+ import * as React from "react"
117
+
118
+ import { Field, FieldLabel } from "@/components/ui/field"
119
+ import {
120
+ InputGroup,
121
+ InputGroupControl,
122
+ InputGroupLeadingIcon,
123
+ InputGroupSelect,
124
+ InputGroupSlot,
125
+ } from "@/components/ui/input-group"
126
+ import { SelectItem } from "@/components/ui/select"
127
+
128
+ const CURRENCY_SYMBOLS: Record<string, string> = {
129
+ usd: "$",
130
+ eur: "€",
131
+ gbp: "£",
132
+ }
133
+
134
+ export default function InputGroupWithSelect() {
135
+ const [currency, setCurrency] = React.useState("usd")
136
+
137
+ return (
138
+ <Field className="max-w-md">
139
+ <FieldLabel htmlFor="input-group-with-select-amount">Amount</FieldLabel>
140
+ <InputGroup>
141
+ <InputGroupLeadingIcon>
142
+ <span className="font-medium">{CURRENCY_SYMBOLS[currency]}</span>
143
+ </InputGroupLeadingIcon>
144
+ <InputGroupSlot>
145
+ <InputGroupControl
146
+ id="input-group-with-select-amount"
147
+ placeholder="0.00"
148
+ />
149
+ </InputGroupSlot>
150
+ <InputGroupSelect value={currency} onValueChange={setCurrency}>
151
+ <SelectItem value="usd">USD</SelectItem>
152
+ <SelectItem value="eur">EUR</SelectItem>
153
+ <SelectItem value="gbp">GBP</SelectItem>
154
+ </InputGroupSelect>
155
+ </InputGroup>
156
+ </Field>
157
+ )
158
+ }
159
+ ```
160
+
161
+ More: `npx @create-ui/cli view input-group` or MCP `get_item_examples_from_registries` with "input-group-demo" / "input-group-example".
162
+
163
+ ## When to use
164
+ InputGroup is the shell for a single value that needs visible chrome: search bars with kbd hints and a submit button, URL fields with an https:// addon, amounts with a trailing currency select, passwords with a built-in show/hide toggle. For plain capture with no affordances use Input (or Textarea for multiline); for one-character-per-slot codes use InputOTP; for increment/decrement use InputStepper.
165
+ ## Gotchas
166
+ - Never put a raw Input or Textarea inside the group; use InputGroupControl (single-line) or InputGroupTextarea (multiline). InputGroupControl strips its own height/padding (h-auto p-0) and relies on InputGroupSlot for size and state styling.
167
+ - Two layers of placement: inline adornments (plain svg icons, InputGroupKbd, InputGroupHelperIcon) go INSIDE InputGroupSlot next to the control; bordered chrome (InputGroupLeadingIcon, InputGroupAddon, InputGroupSelect, InputGroupButton) goes as direct children of the group. The shell auto-draws 1px dividers between direct children.
168
+ - size/invalid/disabled/loading cascade Field -> InputGroup -> every sub-part; set them once on Field. InputGroupSelect goes variant="compact" and InputGroupButton maps the group size to its own scale (xs->md, sm->lg, md->xl) automatically; do not re-set variant/size on them.
169
+ - States do more than recolor: invalid auto-disables InputGroupButton; loading disables InputGroupButton and InputGroupSelect, appends a Spinner inside the slot, and makes InputGroupTextarea readOnly.
170
+ - InputGroupControl type="password" auto-renders a show/hide eye toggle (with aria-pressed); it hides while loading and disables with the group. No extra wiring.
171
+ - InputGroupKbd shows a command-key leading icon by default; pass leadingIcon={null} for plain single-key hints.
@@ -0,0 +1,130 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/input-otp.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/input-otp.md -->
2
+
3
+ # input-otp
4
+
5
+ One-time passcode input with per-character slots; outline/filled variants and rounded/pill/square/underline shapes
6
+
7
+ Install: `npx @create-ui/cli add input-otp`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { InputOTP } from "@/components/ui/input-otp"
13
+ ```
14
+
15
+ Also exported: `InputOTPGroup`, `InputOTPSlot`, `InputOTPSeparator`, `inputOTPSlotVariants`
16
+
17
+ ## InputOTP props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | shape | `rounded \| pill \| square \| underline` | `rounded` |
22
+ | size | `lg \| md \| sm` (Resolution chain: explicit prop ?? wrapping Field's size ?? lg. Do not set it manually inside a Field.) | `lg` |
23
+ | variant | `outline \| filled` | `outline` |
24
+ | containerClassName | `string` (Merged onto the visible flex wrapper (default gap-component-lg). Disabled state auto-adds opacity-50 here.) | - |
25
+ | invalid | `boolean` (Falls back to Field's invalid; flips every slot to data-state=error at once, overriding filled/typing/focused visuals (disabled still wins).) | `false` |
26
+ | children | `ReactNode` | - |
27
+
28
+ Extends `Omit< React.ComponentProps<typeof OTPInput>, "containerClassName" | "size" | "render" | "ref" >`.
29
+
30
+ ## Examples
31
+
32
+ From `input-otp-demo`:
33
+
34
+ ```tsx
35
+ "use client"
36
+
37
+ import { REGEXP_ONLY_DIGITS } from "input-otp"
38
+
39
+ import {
40
+ InputOTP,
41
+ InputOTPGroup,
42
+ InputOTPSeparator,
43
+ InputOTPSlot,
44
+ } from "@/components/ui/input-otp"
45
+
46
+ export default function InputOTPDemo() {
47
+ return (
48
+ <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS}>
49
+ <InputOTPGroup>
50
+ <InputOTPSlot index={0} />
51
+ <InputOTPSlot index={1} />
52
+ <InputOTPSlot index={2} />
53
+ <InputOTPSeparator />
54
+ <InputOTPSlot index={3} />
55
+ <InputOTPSlot index={4} />
56
+ <InputOTPSlot index={5} />
57
+ </InputOTPGroup>
58
+ </InputOTP>
59
+ )
60
+ }
61
+ ```
62
+
63
+ From `input-otp-with-field`:
64
+
65
+ ```tsx
66
+ "use client"
67
+
68
+ import * as React from "react"
69
+ import { REGEXP_ONLY_DIGITS } from "input-otp"
70
+
71
+ import {
72
+ Field,
73
+ FieldContent,
74
+ FieldDescription,
75
+ FieldError,
76
+ FieldLabel,
77
+ } from "@/components/ui/field"
78
+ import {
79
+ InputOTP,
80
+ InputOTPGroup,
81
+ InputOTPSeparator,
82
+ InputOTPSlot,
83
+ } from "@/components/ui/input-otp"
84
+
85
+ export default function InputOTPWithField() {
86
+ const [value, setValue] = React.useState("")
87
+ const invalid = value.length > 0 && value.length < 6
88
+
89
+ return (
90
+ <Field size="md" invalid={invalid}>
91
+ <FieldLabel>Verification code</FieldLabel>
92
+ <FieldContent>
93
+ <InputOTP
94
+ maxLength={6}
95
+ value={value}
96
+ onChange={setValue}
97
+ pattern={REGEXP_ONLY_DIGITS}
98
+ >
99
+ <InputOTPGroup>
100
+ <InputOTPSlot index={0} />
101
+ <InputOTPSlot index={1} />
102
+ <InputOTPSlot index={2} />
103
+ <InputOTPSeparator />
104
+ <InputOTPSlot index={3} />
105
+ <InputOTPSlot index={4} />
106
+ <InputOTPSlot index={5} />
107
+ </InputOTPGroup>
108
+ </InputOTP>
109
+ <FieldDescription>
110
+ Enter the 6-digit code sent to your phone.
111
+ </FieldDescription>
112
+ <FieldError>Please enter all 6 digits.</FieldError>
113
+ </FieldContent>
114
+ </Field>
115
+ )
116
+ }
117
+ ```
118
+
119
+ More: `npx @create-ui/cli view input-otp` or MCP `get_item_examples_from_registries` with "input-otp-demo" / "input-otp-example".
120
+
121
+ ## When to use
122
+ Fixed-length verification codes: 2FA, SMS/email confirmation, recovery codes. One hidden input drives per-character visual slots. Not for variable-length text (use Input), formatted values like card numbers, phone numbers, or dates (CreditCardInput, PhoneInput, DateInput), or bounded numeric values (InputStepper).
123
+
124
+ ## Gotchas
125
+ - Children composition is mandatory; the upstream `render` prop is Omit-ted from the type. Render one `InputOTPSlot` per character with a zero-based `index` covering `maxLength`, wrapped in `InputOTPGroup` (a layout-only div; slots read state from the upstream OTPInputContext).
126
+ - `shape`/`size`/`variant`/`disabled`/`invalid` are set only on the root `InputOTP` and reach slots via internal context. `InputOTPSlot` accepts only div props plus `index`; variant props on it do nothing.
127
+ - Slots are NOT fused like shadcn's. Each slot is a standalone bordered box and `InputOTPGroup` just lays them out with `gap-component-lg`. Do not add shadcn-style `first:rounded-l` / shared-border / divide hacks.
128
+ - Field cascade covers all three of `size`, `disabled`, `invalid` (prop ?? Field ctx ?? default). `<Field invalid>` alone puts the whole OTP in error state; pair it with `FieldError` for the message.
129
+ - `InputOTPSeparator` defaults to the Remix `RiSubtractLine` minus icon and scales its text size from the root size context (default svg stays `size-6`). Pass children to replace it; never import a lucide icon for this.
130
+ - The component sets no input `pattern` itself; examples always pass `pattern={REGEXP_ONLY_DIGITS}` imported from the `input-otp` package to restrict input to digits.
@@ -0,0 +1,120 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/input-stepper.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/input-stepper.md -->
2
+
3
+ # input-stepper
4
+
5
+ Numeric input with increment and decrement buttons; connected or separated variant, min/max/step clamping
6
+
7
+ Install: `npx @create-ui/cli add input-stepper`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { InputStepper } from "@/components/ui/input-stepper"
13
+ ```
14
+
15
+ ## InputStepper props
16
+
17
+ | Prop | Type | Default |
18
+ | --- | --- | --- |
19
+ | variant | `connected \| separated` | - |
20
+ | value | `number` (Clamped to [min, max] on every render in controlled mode; out-of-range state is never displayed) | - |
21
+ | defaultValue | `number` | - |
22
+ | onValueChange | `(value: number) => void` (Receives the clamped number, not an event; fires only when the clamped result differs from the current value) | - |
23
+ | min | `number` | - |
24
+ | max | `number` | - |
25
+ | step | `number` (Drives +/- clicks AND native ArrowUp/ArrowDown stepping; both move by the same amount) | - |
26
+ | size | `xs \| sm \| md` (Resolves explicit prop ?? parent Field size ?? md; the effective default is md, not sm) | - |
27
+ | invalid | `boolean` | - |
28
+ | disabled | `boolean` | - |
29
+ | decrementLabel | `string` | - |
30
+ | incrementLabel | `string` | - |
31
+
32
+ Extends `React.ComponentProps<"input">`.
33
+
34
+ ## Examples
35
+
36
+ From `input-stepper-demo`:
37
+
38
+ ```tsx
39
+ "use client"
40
+
41
+ import * as React from "react"
42
+
43
+ import { InputStepper } from "@/components/ui/input-stepper"
44
+
45
+ export default function InputStepperDemo() {
46
+ const [value, setValue] = React.useState(1)
47
+
48
+ return (
49
+ <div className="w-[240px]">
50
+ <InputStepper
51
+ value={value}
52
+ onValueChange={setValue}
53
+ min={0}
54
+ max={10}
55
+ aria-label="Quantity"
56
+ />
57
+ </div>
58
+ )
59
+ }
60
+ ```
61
+
62
+ From `input-stepper-in-field`:
63
+
64
+ ```tsx
65
+ "use client"
66
+
67
+ import * as React from "react"
68
+
69
+ import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
70
+ import { InputStepper } from "@/components/ui/input-stepper"
71
+
72
+ export default function InputStepperInField() {
73
+ const [quantity, setQuantity] = React.useState(1)
74
+
75
+ return (
76
+ <div className="flex w-[320px] flex-col gap-6">
77
+ <Field size="md">
78
+ <FieldLabel htmlFor="qty">Quantity</FieldLabel>
79
+ <InputStepper
80
+ id="qty"
81
+ value={quantity}
82
+ onValueChange={setQuantity}
83
+ min={1}
84
+ max={10}
85
+ />
86
+ <FieldDescription>
87
+ Inherits size from <code>{'<Field size="md" />'}</code>.
88
+ </FieldDescription>
89
+ </Field>
90
+
91
+ <Field size="sm" invalid>
92
+ <FieldLabel htmlFor="qty-invalid">Quantity (invalid)</FieldLabel>
93
+ <InputStepper id="qty-invalid" defaultValue={3} />
94
+ <FieldDescription>
95
+ Inherits <code>invalid</code> from Field.
96
+ </FieldDescription>
97
+ </Field>
98
+
99
+ <Field size="xs" disabled>
100
+ <FieldLabel htmlFor="qty-disabled">Quantity (disabled)</FieldLabel>
101
+ <InputStepper id="qty-disabled" defaultValue={3} variant="separated" />
102
+ </Field>
103
+ </div>
104
+ )
105
+ }
106
+ ```
107
+
108
+ More: `npx @create-ui/cli view input-stepper` or MCP `get_item_examples_from_registries` with "input-stepper-demo" / "input-stepper-example".
109
+
110
+ ## When to use
111
+ A number-only input flanked by -/+ buttons for bounded counts: cart quantities, seats, tickets. Do NOT use it for free-form or unbounded numeric entry (use Input with type="number"), for picking from a fixed list (Select), or for boolean toggles (Switch/Checkbox).
112
+
113
+ ## Gotchas
114
+ - Closed composite: only `InputStepper` is exported; the buttons, cell, and inner input are internal. Never rebuild it shadcn-style from `Input` + two `Button`s; restyle via `className` on the root or the `data-slot="input-stepper-*"` attributes.
115
+ - The state API is `onValueChange(value: number)`; native `value`/`defaultValue`/`onChange` are Omit-ed from the prop type. `defaultValue` is clamped to `[min, max]` at mount and `value` on every render.
116
+ - The -/+ buttons auto-disable at `min`/`max`, but only while a value is present; with an empty input both stay enabled.
117
+ - `size`/`invalid`/`disabled` resolve as explicit prop ?? parent `Field` context ?? default, so inside a `Field` do not repeat them on the stepper (see input-stepper-in-field). The fallback `"sm"` visible in the source is unreachable; the real default size is `md`.
118
+ - The -/+ buttons are `tabIndex={-1}` and call `preventDefault` on mousedown, so clicking them never moves focus and Tab reaches only the input. This is intentional; do not "fix" the tab order.
119
+ - Clearing the input (uncontrolled) sets the value to `undefined` without firing `onValueChange`; in controlled mode the clear is ignored. From empty, the next +/- click seeds from `clamp(0, min, max)`, not from the last value.
120
+ - Native browser spinners are hidden via CSS, but ArrowUp/ArrowDown still step the native `<input type="number">` by `step`.
@@ -0,0 +1,118 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/input.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/input.md -->
2
+
3
+ # input
4
+
5
+ Single-line text input rendered in a focusable InputShell; size and invalid/disabled/loading state inherit from Field
6
+
7
+ Install: `npx @create-ui/cli add input`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { Input, InputProvider, InputShell } from "@/components/ui/input"
13
+ ```
14
+
15
+ Also exported: `inputVariants`, `inputShellVariants`, `useInputContext`
16
+
17
+ ## Input props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | size | `xs \| sm \| md` (Resolution is prop ?? InputProvider context ?? Field context ?? sm; inside a Field omit it and let the Field's size cascade.) | `sm` |
22
+
23
+ Extends `React.ComponentProps<"input">`.
24
+
25
+ ## InputProvider props
26
+
27
+ | Prop | Type | Default |
28
+ | --- | --- | --- |
29
+ | size | `xs \| sm \| md` (Resolution is prop ?? InputProvider context ?? Field context ?? sm; inside a Field omit it and let the Field's size cascade.) | `md` |
30
+ | invalid | `boolean` | `false` |
31
+ | disabled | `boolean` | `false` |
32
+ | loading | `boolean` | `false` |
33
+ | children | `ReactNode` | - |
34
+
35
+ ## Examples
36
+
37
+ From `input-demo`:
38
+
39
+ ```tsx
40
+ import { Input } from "@/components/ui/input"
41
+
42
+ export default function InputDemo() {
43
+ return (
44
+ <div className="w-100">
45
+ <Input type="email" placeholder="Email" />
46
+ </div>
47
+ )
48
+ }
49
+ ```
50
+
51
+ From `input-states`:
52
+
53
+ ```tsx
54
+ import { Field, FieldLabel } from "@/components/ui/field"
55
+ import { Input } from "@/components/ui/input"
56
+
57
+ export default function InputStates() {
58
+ return (
59
+ <div className="flex w-100 flex-col gap-10 py-4">
60
+ <Field>
61
+ <FieldLabel htmlFor="input-states-default">Default</FieldLabel>
62
+ <Input
63
+ id="input-states-default"
64
+ type="email"
65
+ placeholder="name@example.com"
66
+ />
67
+ </Field>
68
+ <Field invalid>
69
+ <FieldLabel htmlFor="input-states-invalid">Invalid</FieldLabel>
70
+ <Input
71
+ id="input-states-invalid"
72
+ type="email"
73
+ defaultValue="not-an-email"
74
+ />
75
+ </Field>
76
+ <Field disabled>
77
+ <FieldLabel htmlFor="input-states-disabled">Disabled</FieldLabel>
78
+ <Input
79
+ id="input-states-disabled"
80
+ type="email"
81
+ placeholder="name@example.com"
82
+ />
83
+ </Field>
84
+ <Field loading>
85
+ <FieldLabel htmlFor="input-states-loading">Loading</FieldLabel>
86
+ <Input
87
+ id="input-states-loading"
88
+ type="email"
89
+ placeholder="Checking availability…"
90
+ />
91
+ </Field>
92
+ </div>
93
+ )
94
+ }
95
+ ```
96
+
97
+ More: `npx @create-ui/cli view input` or MCP `get_item_examples_from_registries` with "input-demo" / "input-example".
98
+
99
+ ## When to use
100
+ Single-line text values: emails, names, search queries, URLs, file pickers. It is a one-element drop-in (`<Input />` wraps itself in a styled shell) that inherits size/invalid/disabled/loading from a surrounding `Field`. Do NOT use it for multi-line text (`Textarea`), option picking (`Select`), fields with icons/buttons/addons (`InputGroup` + `InputGroupControl`), OTP codes (`InputOTP`), step-controlled numbers (`InputStepper`), or dates/phones/cards (`DateInput` / `PhoneInput` / `CreditCardInput`).
101
+
102
+ ## Gotchas
103
+ - Shell is auto-conditional: standalone `<Input />` wraps itself in `InputProvider` + `InputShell`; when any input context already exists it renders only the bare `<input>`. So in manual composition state props must go on `InputProvider`, not on `Input`, or the shell never sees them:
104
+
105
+ ```tsx
106
+ <InputProvider size="md" invalid>
107
+ <InputShell>
108
+ <Input placeholder="Email" />
109
+ </InputShell>
110
+ </InputProvider>
111
+ ```
112
+
113
+ - Unlike shadcn, the border/focus/disabled visuals are on the shell `<div>`, not the input element. `className` on `Input` cannot change the border or radius; target `InputShell` (or `[data-slot="input-shell"]`) instead. Focus uses `outline-*`, never `ring-*`.
114
+ - `loading` is not an `Input` prop; it arrives from `Field` (or `InputProvider`) context. It silently forces `readOnly` on the input and `pointer-events-none` + `aria-busy` on the shell.
115
+ - For the error treatment prefer `<Field invalid>`. On a standalone `Input`, only a boolean `aria-invalid` is forwarded to the shell; the string form `aria-invalid="true"` sets the attribute on the inner input (red text via `aria-invalid:` CSS) but the shell keeps its normal border.
116
+ - Clicking empty shell space focuses the input via mousedown delegation; clicks on nested interactive elements (input, button, a, [role='button'], etc.) are skipped. Mark custom interactive children with `data-input-control` so the shell does not steal their clicks.
117
+ - Inside `InputGroup` use `InputGroupControl`, not raw `Input`: the control re-renders `Input` with `h-auto p-0` so the group shell owns spacing, and adds the password show/hide toggle for `type="password"`. A raw `Input` there renders bare but keeps its own size padding.
118
+ - Hidden cleanups baked in: browser autofill background is suppressed and the native webkit clear (X) button for `type="search"` is hidden, so add your own clear affordance (e.g. an `InputGroup` button) if one is needed.
@@ -0,0 +1,121 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/label.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/label.md -->
2
+
3
+ # label
4
+
5
+ Form label with companion slots like LabelRequired, LabelOptional, LabelDescription and LabelCount; size follows Field
6
+
7
+ Install: `npx @create-ui/cli add label`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { Label, LabelBlock, LabelMain, LabelIcon, LabelRequired, LabelOptional, LabelDescription, LabelBadgeSlot, LabelInfoSlot, LabelCount } from "@/components/ui/label"
13
+ ```
14
+
15
+ Also exported: `useLabelSize`
16
+
17
+ ## Label props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
22
+
23
+ Extends `React.ComponentProps<typeof LabelPrimitive.Root>`.
24
+
25
+ ## LabelBlock props
26
+
27
+ | Prop | Type | Default |
28
+ | --- | --- | --- |
29
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
30
+ | asChild | `boolean` | `false` |
31
+
32
+ Extends `React.ComponentProps<"div">`.
33
+
34
+ ## LabelIcon props
35
+
36
+ | Prop | Type | Default |
37
+ | --- | --- | --- |
38
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
39
+
40
+ Extends `React.ComponentProps<"span">`.
41
+
42
+ ## LabelRequired props
43
+
44
+ | Prop | Type | Default |
45
+ | --- | --- | --- |
46
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
47
+
48
+ Extends `React.ComponentProps<"span">`.
49
+
50
+ ## LabelOptional props
51
+
52
+ | Prop | Type | Default |
53
+ | --- | --- | --- |
54
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
55
+
56
+ Extends `React.ComponentProps<"span">`.
57
+
58
+ ## LabelDescription props
59
+
60
+ | Prop | Type | Default |
61
+ | --- | --- | --- |
62
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
63
+
64
+ Extends `React.ComponentProps<"p">`.
65
+
66
+ ## LabelInfoSlot props
67
+
68
+ | Prop | Type | Default |
69
+ | --- | --- | --- |
70
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
71
+
72
+ Extends `React.ComponentProps<"span">`.
73
+
74
+ ## LabelCount props
75
+
76
+ | Prop | Type | Default |
77
+ | --- | --- | --- |
78
+ | size | `xs \| sm \| md` (Resolution: explicit prop ?? nearest LabelBlock/Label context ?? surrounding Field ?? sm. Set it once on Field or LabelBlock; never repeat on children) | - |
79
+
80
+ Extends `React.ComponentProps<"span">`.
81
+
82
+ ## Examples
83
+
84
+ From `label-demo`:
85
+
86
+ ```tsx
87
+ import { Field } from "@/components/ui/field"
88
+ import { Input } from "@/components/ui/input"
89
+ import { Label } from "@/components/ui/label"
90
+
91
+ export default function LabelDemo() {
92
+ return (
93
+ <Field className="w-full max-w-xs">
94
+ <Label htmlFor="label-demo">Full name</Label>
95
+ <Input id="label-demo" placeholder="Ada Lovelace" />
96
+ </Field>
97
+ )
98
+ }
99
+ ```
100
+
101
+ More: `npx @create-ui/cli view label` or MCP `get_item_examples_from_registries` with "label-demo" / "label-example".
102
+
103
+ ## When to use
104
+ Caption for a form control (Input, Textarea, Select, Checkbox), with optional slots for an icon, required/optional marker, badge, info tooltip, description, and counter. For the full field stack with error wiring, compose `Field` with `FieldLabel` / `FieldDescription` / `FieldError` instead; for helper text rendered below the control use `FieldDescription`, not `LabelDescription` (which belongs in the label row).
105
+
106
+ ## Gotchas
107
+ - Invalid/disabled looks are not props on Label. They are driven entirely by the wrapping `Field`'s `data-invalid` / `data-disabled` group attributes (`group-data-[...]/field`); a standalone Label cannot show those states.
108
+ - `Label` and `LabelBlock` both re-provide the resolved size to nested slots via context, so `LabelIcon`, `LabelRequired`, `LabelCount`, etc. auto-match. Setting `size` on each slot is redundant and fights the cascade.
109
+ - `LabelIcon` and `LabelRequired` are `aria-hidden` decoration: a `LabelRequired` asterisk does not make the field required, so still set `required` on the control. `LabelOptional` is NOT `aria-hidden`; its "(Optional)" text is announced.
110
+ - Rich rows have a fixed composition: `LabelDescription` is a sibling of `Label` inside `LabelMain`, never a child of `Label`; `LabelCount` sits as `LabelBlock`'s trailing child, outside `LabelMain`.
111
+
112
+ ```tsx
113
+ <LabelBlock>
114
+ <LabelMain>
115
+ <Label htmlFor="bio"><LabelIcon>...</LabelIcon>Bio<LabelRequired /></Label>
116
+ <LabelDescription>Shown on your profile.</LabelDescription>
117
+ </LabelMain>
118
+ <LabelCount>0/300</LabelCount>
119
+ </LabelBlock>
120
+ ```
121
+ - This is not shadcn's one-element Label: no `peer-disabled` styling, no CVA. State styling cascades from `Field`'s group attributes, and slots replace ad-hoc spans.