@create-ui/cli 0.5.8 → 0.6.0

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 (72) 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.d.ts +360 -360
  8. package/dist/index.js +26 -26
  9. package/dist/index.js.map +1 -1
  10. package/dist/mcp/index.js +1 -1
  11. package/dist/registry/index.d.ts +2 -2
  12. package/dist/registry/index.js +1 -1
  13. package/dist/schema/index.d.ts +715 -715
  14. package/dist/skills/createui/SKILL.md +199 -177
  15. package/dist/skills/createui/agents/openai.yml +1 -1
  16. package/dist/skills/createui/cli.md +42 -42
  17. package/dist/skills/createui/customization.md +20 -15
  18. package/dist/skills/createui/evals/evals.json +68 -5
  19. package/dist/skills/createui/mcp.md +14 -5
  20. package/dist/skills/createui/reference/accordion.md +127 -0
  21. package/dist/skills/createui/reference/app-store-badge.md +88 -0
  22. package/dist/skills/createui/reference/aspect-ratio.md +52 -0
  23. package/dist/skills/createui/reference/avatar.md +230 -0
  24. package/dist/skills/createui/reference/badge.md +110 -0
  25. package/dist/skills/createui/reference/breadcrumb.md +153 -0
  26. package/dist/skills/createui/reference/button-group.md +116 -0
  27. package/dist/skills/createui/reference/button.md +104 -0
  28. package/dist/skills/createui/reference/checkbox-group.md +118 -0
  29. package/dist/skills/createui/reference/checkbox.md +79 -0
  30. package/dist/skills/createui/reference/chip.md +115 -0
  31. package/dist/skills/createui/reference/close-button.md +83 -0
  32. package/dist/skills/createui/reference/country-flag.md +109 -0
  33. package/dist/skills/createui/reference/credit-card-input.md +76 -0
  34. package/dist/skills/createui/reference/date-input.md +71 -0
  35. package/dist/skills/createui/reference/dropdown-menu.md +164 -0
  36. package/dist/skills/createui/reference/field.md +186 -0
  37. package/dist/skills/createui/reference/info-tooltip.md +110 -0
  38. package/dist/skills/createui/reference/inline-alert.md +146 -0
  39. package/dist/skills/createui/reference/input-group.md +171 -0
  40. package/dist/skills/createui/reference/input-otp.md +130 -0
  41. package/dist/skills/createui/reference/input-stepper.md +120 -0
  42. package/dist/skills/createui/reference/input.md +118 -0
  43. package/dist/skills/createui/reference/label.md +121 -0
  44. package/dist/skills/createui/reference/pagination.md +157 -0
  45. package/dist/skills/createui/reference/phone-input.md +77 -0
  46. package/dist/skills/createui/reference/progress.md +158 -0
  47. package/dist/skills/createui/reference/radio-group.md +133 -0
  48. package/dist/skills/createui/reference/radio.md +79 -0
  49. package/dist/skills/createui/reference/scroll-area.md +212 -0
  50. package/dist/skills/createui/reference/segmented-control.md +146 -0
  51. package/dist/skills/createui/reference/select.md +204 -0
  52. package/dist/skills/createui/reference/separator.md +99 -0
  53. package/dist/skills/createui/reference/social-login-button.md +130 -0
  54. package/dist/skills/createui/reference/spinner.md +68 -0
  55. package/dist/skills/createui/reference/status-badge.md +89 -0
  56. package/dist/skills/createui/reference/switch-group.md +122 -0
  57. package/dist/skills/createui/reference/switch.md +75 -0
  58. package/dist/skills/createui/reference/tab-menu.md +165 -0
  59. package/dist/skills/createui/reference/text-link.md +84 -0
  60. package/dist/skills/createui/reference/textarea.md +50 -0
  61. package/dist/skills/createui/reference/toast.md +162 -0
  62. package/dist/skills/createui/reference/tooltip.md +63 -0
  63. package/dist/skills/createui/rules/composition.md +41 -25
  64. package/dist/skills/createui/rules/design.md +266 -0
  65. package/dist/skills/createui/rules/forms.md +44 -15
  66. package/dist/skills/createui/rules/icons.md +64 -18
  67. package/dist/skills/createui/rules/styling.md +53 -14
  68. package/dist/utils/index.js +1 -1
  69. package/package.json +1 -1
  70. package/dist/chunk-M5DYT2NE.js +0 -64
  71. package/dist/chunk-M5DYT2NE.js.map +0 -1
  72. package/dist/chunk-NQFMXHMH.js.map +0 -1
@@ -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.
@@ -0,0 +1,157 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/pagination.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/pagination.md -->
2
+
3
+ # pagination
4
+
5
+ Page navigation with first/prev/next/last actions and ellipsis; compact or ButtonGroup-backed compact-grouped variant
6
+
7
+ Install: `npx @create-ui/cli add pagination`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { Pagination, PaginationContent, PaginationLink, PaginationFirst, PaginationPrevious, PaginationNext, PaginationLast, PaginationEllipsis } from "@/components/ui/pagination"
13
+ ```
14
+
15
+ ## Pagination props
16
+
17
+ | Prop | Type | Default |
18
+ | --- | --- | --- |
19
+ | variant | `compact \| compact-grouped` (compact-grouped renders PaginationContent as a soft md ButtonGroup (one fused surface); compact renders standalone buttons with gap-1.) | `compact-grouped` |
20
+ | shape | `rounded \| pill` (Settable on the root Pagination only; children have no shape prop and pick it up from context.) | `rounded` |
21
+
22
+ Extends `React.ComponentProps<"nav">`.
23
+
24
+ ## PaginationLink props
25
+
26
+ | Prop | Type | Default |
27
+ | --- | --- | --- |
28
+ | asChild | `boolean` | - |
29
+ | isActive | `boolean` (Writes aria-current=page and data-active; in compact-grouped it maps to ButtonGroupItem active with aria-pressed deliberately stripped.) | - |
30
+
31
+ Extends `React.ComponentProps<"button">`.
32
+
33
+ ## PaginationFirst props
34
+
35
+ | Prop | Type | Default |
36
+ | --- | --- | --- |
37
+ | asChild | `boolean` | - |
38
+
39
+ Extends `React.ComponentProps<"button">`.
40
+
41
+ ## PaginationPrevious props
42
+
43
+ | Prop | Type | Default |
44
+ | --- | --- | --- |
45
+ | asChild | `boolean` | - |
46
+
47
+ Extends `React.ComponentProps<"button">`.
48
+
49
+ ## PaginationNext props
50
+
51
+ | Prop | Type | Default |
52
+ | --- | --- | --- |
53
+ | asChild | `boolean` | - |
54
+
55
+ Extends `React.ComponentProps<"button">`.
56
+
57
+ ## PaginationLast props
58
+
59
+ | Prop | Type | Default |
60
+ | --- | --- | --- |
61
+ | asChild | `boolean` | - |
62
+
63
+ Extends `React.ComponentProps<"button">`.
64
+
65
+ ## Examples
66
+
67
+ From `pagination-demo`:
68
+
69
+ ```tsx
70
+ import {
71
+ Pagination,
72
+ PaginationContent,
73
+ PaginationEllipsis,
74
+ PaginationLink,
75
+ PaginationNext,
76
+ PaginationPrevious,
77
+ } from "@/components/ui/pagination"
78
+
79
+ export default function PaginationDemo() {
80
+ return (
81
+ <Pagination>
82
+ <PaginationContent>
83
+ <PaginationPrevious />
84
+ <PaginationLink>1</PaginationLink>
85
+ <PaginationLink>2</PaginationLink>
86
+ <PaginationLink isActive>3</PaginationLink>
87
+ <PaginationEllipsis />
88
+ <PaginationLink>10</PaginationLink>
89
+ <PaginationNext />
90
+ </PaginationContent>
91
+ </Pagination>
92
+ )
93
+ }
94
+ ```
95
+
96
+ From `pagination-with-link`:
97
+
98
+ ```tsx
99
+ "use client"
100
+
101
+ import {
102
+ Pagination,
103
+ PaginationContent,
104
+ PaginationEllipsis,
105
+ PaginationLink,
106
+ PaginationNext,
107
+ PaginationPrevious,
108
+ } from "@/components/ui/pagination"
109
+
110
+ export default function PaginationWithLink() {
111
+ return (
112
+ <Pagination>
113
+ <PaginationContent>
114
+ <PaginationPrevious asChild>
115
+ <a href="?page=2" />
116
+ </PaginationPrevious>
117
+ <PaginationLink asChild>
118
+ <a href="?page=1">1</a>
119
+ </PaginationLink>
120
+ <PaginationLink asChild>
121
+ <a href="?page=2">2</a>
122
+ </PaginationLink>
123
+ <PaginationLink asChild isActive>
124
+ <a href="?page=3" aria-current="page">
125
+ 3
126
+ </a>
127
+ </PaginationLink>
128
+ <PaginationEllipsis />
129
+ <PaginationLink asChild>
130
+ <a href="?page=10">10</a>
131
+ </PaginationLink>
132
+ <PaginationNext asChild>
133
+ <a href="?page=4" />
134
+ </PaginationNext>
135
+ </PaginationContent>
136
+ </Pagination>
137
+ )
138
+ }
139
+ ```
140
+
141
+ More: `npx @create-ui/cli view pagination` or MCP `get_item_examples_from_registries` with "pagination-demo" / "pagination-example".
142
+
143
+ ## When to use
144
+ Numbered page navigation for long tables, search results, and archives where users jump between page ranges. Do not use it for switching sibling panels in place (use TabMenu), hierarchical trails (use Breadcrumb), or a plain prev/next pair without page numbers (use two Buttons). For a value-picking segmented control, use SegmentedControl or ButtonGroup directly.
145
+
146
+ ## Gotchas
147
+ - There is no PaginationItem wrapper (shadcn habit): controls are direct children of PaginationContent. PaginationContent is mandatory; in the default compact-grouped variant it IS the ButtonGroup, so dropping it loses the fused surface and sizing.
148
+ - PaginationLink renders a `<button type="button">` by default, not an `<a>` like shadcn. For URL navigation use asChild with an anchor or router Link; isActive keeps working because aria-current and active styling are forwarded onto the slotted element (see pagination-with-link).
149
+ - First/Previous/Next/Last inject their default arrow icon even with asChild: pass an empty anchor and the icon plus the built-in "Go to ... page" aria-label are supplied automatically; any children of the slotted element are replaced by the icon. Without asChild, `children` replaces the icon instead.
150
+ ```tsx
151
+ <PaginationNext asChild>
152
+ <a href="?page=4" />
153
+ </PaginationNext>
154
+ ```
155
+ - With asChild, `disabled` is not forwarded as a native attribute; the slotted element gets `aria-disabled` plus `tabIndex={-1}` and pointer-events-none styling, so disabled links stay in the DOM but become inert and unfocusable.
156
+ - No size prop exists anywhere; compact-grouped is hard-wired to ButtonGroup soft/md and compact items to a fixed h-8. Do not try to pass size to the content or items.
157
+ - PaginationEllipsis is presentational (`role="presentation"`, `aria-hidden`) with a built-in sr-only "More pages" hint; `children` only swaps the visible glyph. Render real PaginationLinks for clickable pages (see pagination-controlled for the windowing pattern).