@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,186 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/field.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/field.md -->
2
+
3
+ # field
4
+
5
+ Form field wrapper that owns the xs/sm/md size cascade; Input, Select and Textarea inherit size and state via context
6
+
7
+ Install: `npx @create-ui/cli add field`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { Field, FieldLabel, FieldTitle, FieldContent, FieldDescription, FieldError, FieldFooter, FieldGroup, FieldHelper, FieldLegend, FieldSeparator, FieldSet } from "@/components/ui/field"
13
+ ```
14
+
15
+ Also exported: `LabelDescription`, `fieldVariants`, `fieldLabelVariants`, `fieldTitleVariants`, `fieldDescriptionVariants`, `fieldHelperVariants`, `fieldErrorVariants`, `fieldFooterVariants`, `fieldLegendVariants`, `useFieldContext`, `useOptionalFieldContext`
16
+
17
+ ## Field props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
22
+ | orientation | `vertical \| horizontal \| responsive` (horizontal puts the label beside the control (settings rows); responsive only inlines inside a FieldGroup) | `vertical` |
23
+ | invalid | `boolean` | - |
24
+ | disabled | `boolean` | - |
25
+ | loading | `boolean` | - |
26
+
27
+ Extends `React.ComponentProps<"div">`.
28
+
29
+ ## FieldTitle props
30
+
31
+ | Prop | Type | Default |
32
+ | --- | --- | --- |
33
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
34
+
35
+ Extends `React.ComponentProps<"div">`.
36
+
37
+ ## FieldDescription props
38
+
39
+ | Prop | Type | Default |
40
+ | --- | --- | --- |
41
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
42
+
43
+ Extends `React.ComponentProps<"p">`.
44
+
45
+ ## FieldError props
46
+
47
+ | Prop | Type | Default |
48
+ | --- | --- | --- |
49
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
50
+ | errors | `Array<{ message?: string } \| undefined>` (deduped by message; bulleted list when >1; renders nothing when empty) | - |
51
+
52
+ Extends `React.ComponentProps<"div">`.
53
+
54
+ ## FieldFooter props
55
+
56
+ | Prop | Type | Default |
57
+ | --- | --- | --- |
58
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
59
+
60
+ Extends `React.ComponentProps<"div">`.
61
+
62
+ ## FieldHelper props
63
+
64
+ | Prop | Type | Default |
65
+ | --- | --- | --- |
66
+ | size | `xs \| sm \| md` (cascades via context to Input/Select/Textarea/labels; set it ONCE here) | `sm` |
67
+ | tone | `neutral \| error` (auto-defaults to error when the Field is invalid) | `neutral` |
68
+ | icon | `ReactNode` (the only Field part that takes its icon as a prop, not a child slot) | - |
69
+
70
+ Extends `React.ComponentProps<"div">`.
71
+
72
+ ## FieldLegend props
73
+
74
+ | Prop | Type | Default |
75
+ | --- | --- | --- |
76
+ | variant | `legend \| label` (label downsizes the legend to match a default (sm) FieldLabel; FieldLegend ignores Field size context) | `legend` |
77
+
78
+ Extends `React.ComponentProps<"legend">`.
79
+
80
+ ## FieldSeparator props
81
+
82
+ | Prop | Type | Default |
83
+ | --- | --- | --- |
84
+ | children | `ReactNode` | - |
85
+
86
+ Extends `React.ComponentProps<"div">`.
87
+
88
+ ## Examples
89
+
90
+ From `field-demo`:
91
+
92
+ ```tsx
93
+ import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
94
+ import { Input } from "@/components/ui/input"
95
+
96
+ export default function FieldDemo() {
97
+ return (
98
+ <Field className="w-full max-w-sm">
99
+ <FieldLabel htmlFor="field-demo-email">Email Address</FieldLabel>
100
+ <Input id="field-demo-email" type="email" placeholder="you@example.com" />
101
+ <FieldDescription>
102
+ We&apos;ll never share your email with anyone.
103
+ </FieldDescription>
104
+ </Field>
105
+ )
106
+ }
107
+ ```
108
+
109
+ From `field-composition`:
110
+
111
+ ```tsx
112
+ import {
113
+ Field,
114
+ FieldContent,
115
+ FieldDescription,
116
+ FieldGroup,
117
+ FieldLabel,
118
+ } from "@/components/ui/field"
119
+ import { Input } from "@/components/ui/input"
120
+ import {
121
+ Select,
122
+ SelectContent,
123
+ SelectGroup,
124
+ SelectItem,
125
+ SelectTrigger,
126
+ SelectValue,
127
+ } from "@/components/ui/select"
128
+ import { Switch } from "@/components/ui/switch"
129
+ import { Textarea } from "@/components/ui/textarea"
130
+
131
+ export default function FieldComposition() {
132
+ return (
133
+ <FieldGroup className="w-full max-w-sm">
134
+ <Field size="md">
135
+ <FieldLabel htmlFor="field-compose-name">Full Name</FieldLabel>
136
+ <Input id="field-compose-name" placeholder="Jane Doe" />
137
+ </Field>
138
+ <Field size="md">
139
+ <FieldLabel htmlFor="field-compose-country">Country</FieldLabel>
140
+ <Select>
141
+ <SelectTrigger id="field-compose-country">
142
+ <SelectValue placeholder="Select your country" />
143
+ </SelectTrigger>
144
+ <SelectContent>
145
+ <SelectGroup>
146
+ <SelectItem value="us">United States</SelectItem>
147
+ <SelectItem value="uk">United Kingdom</SelectItem>
148
+ <SelectItem value="ca">Canada</SelectItem>
149
+ </SelectGroup>
150
+ </SelectContent>
151
+ </Select>
152
+ </Field>
153
+ <Field size="md">
154
+ <FieldLabel htmlFor="field-compose-bio">Bio</FieldLabel>
155
+ <Textarea id="field-compose-bio" placeholder="A few sentences" />
156
+ </Field>
157
+ <Field size="md" orientation="horizontal">
158
+ <FieldContent>
159
+ <FieldLabel htmlFor="field-compose-marketing">
160
+ Marketing Emails
161
+ </FieldLabel>
162
+ <FieldDescription>
163
+ Receive product news and occasional offers.
164
+ </FieldDescription>
165
+ </FieldContent>
166
+ <Switch id="field-compose-marketing" />
167
+ </Field>
168
+ </FieldGroup>
169
+ )
170
+ }
171
+ ```
172
+
173
+ More: `npx @create-ui/cli view field` or MCP `get_item_examples_from_registries` with "field-demo" / "field-example".
174
+
175
+ ## When to use
176
+
177
+ Layout and context wrapper for every labeled form control: forms are `FieldGroup` > `Field`(s), never raw divs with `space-y-*`. The control inside is `Input`/`Select`/`Textarea`/`Checkbox`/`Switch`; a multi-option group that is one logical control should be `RadioGroup` or `CheckboxGroup` instead. Group related fields with `FieldSet` + `FieldLegend`, not a heading div.
178
+
179
+ ## Gotchas
180
+
181
+ - Set `size`/`invalid`/`disabled`/`loading` once on `Field`; nested controls and `Field*` parts resolve explicit prop ?? context ?? default - never re-set them on children. `Field` also derives state from `data-invalid`/`data-disabled`/`data-loading` attributes when the boolean props are absent.
182
+ - `orientation="responsive"` switches via a container query that only `FieldGroup` provides (`@container/field-group`); a responsive `Field` without a `FieldGroup` ancestor stays stacked forever.
183
+ - Horizontal checkbox/switch rows: stack `FieldLabel` + `FieldDescription` inside `FieldContent` as a DIRECT child of `Field` - the alignment switch keys off `has-[>[data-slot=field-content]]`. Rich choice cards use `Label` + `LabelDescription` inside `LabelMain` there, not `FieldLabel` + `FieldDescription`.
184
+ - Render `FieldError` unconditionally; it returns null when it has no `children` and no `errors`, and `children` take precedence over `errors`. It ships with `role="alert"`.
185
+ - `FieldTitle` renders a `<div>` with no `htmlFor` association, but it shares `data-slot="field-label"`, so horizontal layout treats it like a label; use it for non-labelable controls such as a segmented control.
186
+ - Vertical (default) Field forces every direct child to full width via [&>*]:w-full; self-start does NOT stop the stretch. For intrinsic-width controls (SegmentedControl, a lone Button), use orientation="horizontal" or wrap the control in a plain div.
@@ -0,0 +1,110 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/info-tooltip.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/info-tooltip.md -->
2
+
3
+ # info-tooltip
4
+
5
+ Tooltip with a built-in info icon trigger for field hints; pass variant/size on the root for the simplified API
6
+
7
+ Install: `npx @create-ui/cli add info-tooltip`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { InfoTooltip, InfoTooltipContent, InfoTooltipProvider, InfoTooltipTrigger } from "@/components/ui/info-tooltip"
13
+ ```
14
+
15
+ Also exported: `infoTooltipContentVariants`
16
+
17
+ ## InfoTooltip props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | variant | `primary \| neutral \| inverse \| danger \| info` | - |
22
+ | size | `sm \| md \| lg` | - |
23
+ | side | `top \| bottom \| left \| right` | - |
24
+ | align | `start \| center \| end` | - |
25
+ | showArrow | `boolean` (When false, sideOffset is auto-increased by 7 so the gap matches the arrow version) | - |
26
+ | className | `string` | - |
27
+
28
+ Extends `React.ComponentProps< typeof TooltipPrimitive.Root >`.
29
+
30
+ ## InfoTooltipContent props
31
+
32
+ | Prop | Type | Default |
33
+ | --- | --- | --- |
34
+ | variant | `primary \| neutral \| inverse \| danger \| info` | `primary` |
35
+ | size | `sm \| md \| lg` | `sm` |
36
+ | children | `ReactNode` | - |
37
+ | className | `string` | - |
38
+ | showArrow | `boolean` (When false, sideOffset is auto-increased by 7 so the gap matches the arrow version) | `true` |
39
+ | side | `top \| bottom \| left \| right` | `bottom` |
40
+ | align | `start \| center \| end` | `center` |
41
+ | sideOffset | `number` | `2.5` |
42
+ | alignOffset | `number` (Auto-resolves for align start/end to -12 (sm/md) or -16 (lg); center gets 0) | - |
43
+
44
+ Extends `React.ComponentProps<typeof TooltipPrimitive.Content>`.
45
+
46
+ ## InfoTooltipTrigger props
47
+
48
+ | Prop | Type | Default |
49
+ | --- | --- | --- |
50
+ | children | `ReactNode` | - |
51
+ | asChild | `boolean` | - |
52
+ | variant | `primary \| neutral \| inverse \| danger \| info` | - |
53
+ | size | `sm \| md \| lg` | - |
54
+ | className | `string` | - |
55
+
56
+ Extends `React.ComponentProps<typeof TooltipPrimitive.Trigger>`.
57
+
58
+ ## Examples
59
+
60
+ From `label-info-tooltip`:
61
+
62
+ ```tsx
63
+ import { RiKey2Line } from "@create-ui/assets/icons"
64
+
65
+ import { Field } from "@/components/ui/field"
66
+ import { InfoTooltip } from "@/components/ui/info-tooltip"
67
+ import { Input } from "@/components/ui/input"
68
+ import { Label, LabelIcon, LabelInfoSlot } from "@/components/ui/label"
69
+
70
+ export default function LabelInfoTooltip() {
71
+ return (
72
+ <Field className="w-full max-w-xs">
73
+ <Label htmlFor="label-info">
74
+ <LabelIcon>
75
+ <RiKey2Line />
76
+ </LabelIcon>
77
+ API token
78
+ <LabelInfoSlot>
79
+ <InfoTooltip variant="inverse" size="sm" side="top">
80
+ Used to authenticate API requests. Keep it secret, treat it like a
81
+ password, and rotate it right away if it ever leaks or shows up in a
82
+ commit.
83
+ </InfoTooltip>
84
+ </LabelInfoSlot>
85
+ </Label>
86
+ <Input id="label-info" placeholder="sk-…" />
87
+ </Field>
88
+ )
89
+ }
90
+ ```
91
+
92
+ More: `npx @create-ui/cli view info-tooltip` or MCP `get_item_examples_from_registries` with "info-tooltip-demo" / "info-tooltip-example".
93
+
94
+ ## When to use
95
+ A "what is this?" helper with a built-in info-circle icon trigger, typically next to a field label (canonical placement: inside `LabelInfoSlot` within `Label`, see label-info-tooltip). Do NOT use it for hover hints on arbitrary elements like buttons; that is `Tooltip`. There is no popover component for click-to-open rich content - surface that content inline.
96
+
97
+ ## Gotchas
98
+ - The root has two modes. Setting `variant` OR `size` on `InfoTooltip` activates the simplified API: children become the tooltip TEXT and the icon trigger plus content are auto-rendered. With neither prop set it is a bare Radix Root: compose `InfoTooltipTrigger` + `InfoTooltipContent` yourself, and `side`/`align`/`showArrow`/`className` on the root do nothing.
99
+ - In composed mode there is no context cascade: pass the same `variant`/`size` to BOTH `InfoTooltipTrigger` (icon color/size) and `InfoTooltipContent` (bubble styling). The arrow fill is derived by Content from its own `variant`.
100
+ - `InfoTooltipTrigger` with no children renders a built-in inline info SVG; passing children replaces it entirely and the trigger's `variant`/`size` stop doing anything. The trigger always carries the `group` class, so custom children can style via `group-hover:` and `group-data-[state=open]:`.
101
+ - Placement defaults to bottom (shadcn/Radix tooltips default to top). An AI trained on shadcn will also reach for `TooltipProvider` + `Trigger asChild` + `Content`; the intended common form is the one-liner:
102
+
103
+ ```tsx
104
+ <InfoTooltip variant="inverse" size="sm" side="top">
105
+ Helper text
106
+ </InfoTooltip>
107
+ ```
108
+
109
+ - It does not read Field context; set `size` explicitly even inside a `Field`/`Label`.
110
+ - The icon is hardcoded inline in the component, not imported from `@create-ui/assets/icons`; do not "fix" it to a Remix icon.
@@ -0,0 +1,146 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/inline-alert.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/inline-alert.md -->
2
+
3
+ # inline-alert
4
+
5
+ Dismissible callout for in-page messages; seven variants by four appearances with horizontal or vertical layout
6
+
7
+ Install: `npx @create-ui/cli add inline-alert`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { InlineAlert, InlineAlertIcon, InlineAlertContent, InlineAlertHeading, InlineAlertTitle, InlineAlertDescription, InlineAlertActions, InlineAlertClose } from "@/components/ui/inline-alert"
13
+ ```
14
+
15
+ Also exported: `inlineAlertVariants`, `useInlineAlertContext`
16
+
17
+ ## InlineAlert props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | variant | `primary \| neutral \| danger \| success \| warning \| info \| away` | `primary` |
22
+ | appearance | `solid \| soft \| outline \| default` (default = neutral card (border + shadow; variant tints only the icon); soft = tinted fill; solid = filled high-emphasis; outline = tinted text + colored border) | `default` |
23
+ | layout | `horizontal \| vertical` (horizontal nowraps the title and clamps description to 2 lines; vertical clamps at 5 - use vertical for longer copy) | `horizontal` |
24
+ | onDismiss | `() => void` (fires when the 300ms exit transition ends, not on close click) | - |
25
+
26
+ Extends `React.ComponentProps<"div">`.
27
+
28
+ ## Examples
29
+
30
+ From `inline-alert-demo`:
31
+
32
+ ```tsx
33
+ import { RiInformationFill } from "@create-ui/assets/icons"
34
+
35
+ import {
36
+ InlineAlert,
37
+ InlineAlertContent,
38
+ InlineAlertDescription,
39
+ InlineAlertHeading,
40
+ InlineAlertIcon,
41
+ InlineAlertTitle,
42
+ } from "@/components/ui/inline-alert"
43
+
44
+ export default function InlineAlertDemo() {
45
+ return (
46
+ <InlineAlert>
47
+ <InlineAlertIcon>
48
+ <RiInformationFill />
49
+ </InlineAlertIcon>
50
+ <InlineAlertContent>
51
+ <InlineAlertHeading>
52
+ <InlineAlertTitle>Heads up</InlineAlertTitle>
53
+ <InlineAlertDescription>
54
+ Your changes have been saved to the draft.
55
+ </InlineAlertDescription>
56
+ </InlineAlertHeading>
57
+ </InlineAlertContent>
58
+ </InlineAlert>
59
+ )
60
+ }
61
+ ```
62
+
63
+ From `inline-alert-dismissible`:
64
+
65
+ ```tsx
66
+ "use client"
67
+
68
+ import * as React from "react"
69
+ import { RiCheckboxCircleFill } from "@create-ui/assets/icons"
70
+
71
+ import { Button } from "@/components/ui/button"
72
+ import {
73
+ InlineAlert,
74
+ InlineAlertClose,
75
+ InlineAlertContent,
76
+ InlineAlertDescription,
77
+ InlineAlertHeading,
78
+ InlineAlertIcon,
79
+ InlineAlertTitle,
80
+ } from "@/components/ui/inline-alert"
81
+
82
+ export default function InlineAlertDismissible() {
83
+ const [visible, setVisible] = React.useState(true)
84
+
85
+ if (!visible) {
86
+ return (
87
+ <Button
88
+ variant="neutral-light"
89
+ appearance="outline"
90
+ size="md"
91
+ onClick={() => setVisible(true)}
92
+ >
93
+ Show alert again
94
+ </Button>
95
+ )
96
+ }
97
+
98
+ return (
99
+ <InlineAlert variant="success" onDismiss={() => setVisible(false)}>
100
+ <InlineAlertIcon>
101
+ <RiCheckboxCircleFill />
102
+ </InlineAlertIcon>
103
+ <InlineAlertContent>
104
+ <InlineAlertHeading>
105
+ <InlineAlertTitle>Saved</InlineAlertTitle>
106
+ <InlineAlertDescription>
107
+ Your settings are up to date. Dismiss this banner to remove it from
108
+ the page.
109
+ </InlineAlertDescription>
110
+ </InlineAlertHeading>
111
+ </InlineAlertContent>
112
+ <InlineAlertClose />
113
+ </InlineAlert>
114
+ )
115
+ }
116
+ ```
117
+
118
+ More: `npx @create-ui/cli view inline-alert` or MCP `get_item_examples_from_registries` with "inline-alert-demo" / "inline-alert-example".
119
+
120
+ ## When to use
121
+
122
+ In-flow status callouts anchored to content: form-level validation summaries, plan notices, saved confirmations. There is no page-banner component; build a top-of-page announcement from semantic-token markup rather than stretching an InlineAlert. Ephemeral screen-level feedback is `Toast`; per-field validation is `Field` error/helper text.
123
+
124
+ ## Gotchas
125
+
126
+ - Nesting is strict and deeper than shadcn's flat Alert: `InlineAlertTitle` + `InlineAlertDescription` go inside `InlineAlertHeading`, which sits next to `InlineAlertActions` inside `InlineAlertContent`. In horizontal layout Content is a flex row, so an unwrapped Title/Description render side by side instead of stacked.
127
+
128
+ ```tsx
129
+ <InlineAlert variant="warning" appearance="soft" onDismiss={removeFromState}>
130
+ <InlineAlertIcon><RiErrorWarningFill /></InlineAlertIcon>
131
+ <InlineAlertContent>
132
+ <InlineAlertHeading>
133
+ <InlineAlertTitle>Storage almost full</InlineAlertTitle>
134
+ <InlineAlertDescription>Upgrade to keep receiving uploads.</InlineAlertDescription>
135
+ </InlineAlertHeading>
136
+ <InlineAlertActions>{/* Button / TextLink */}</InlineAlertActions>
137
+ </InlineAlertContent>
138
+ <InlineAlertClose />
139
+ </InlineAlert>
140
+ ```
141
+
142
+ - `InlineAlertClose` always renders absolutely at the alert's top-right corner (the root is its only positioned ancestor), and the root auto-reserves clearance for it (`pr-12` horizontal, title right-padding vertical). Keep it a direct child of the root; nesting it inside `InlineAlertActions` does not put it in flow, it still jumps to the corner.
143
+ - Dismissal is self-contained: Close triggers a fade/scale exit, then the component unmounts itself (returns null). Sync external state in `onDismiss`, not in your own Close `onClick`, or the exit transition is cut off.
144
+ - `InlineAlertClose` auto-adapts its CloseButton to context (inverse on solid appearance, neutral otherwise); leave its variant unset.
145
+ - `InlineAlertIcon` sizes (`[&_svg]:size-5`) and colors the glyph from variant/appearance context; pass a bare `Ri*` icon with no size or color classes.
146
+ - Unlike shadcn's Alert, the default variant is `primary`, so an unconfigured alert's icon reads brand-tinted, not gray; use `variant="neutral"` for a plain note.
@@ -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.