@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,164 @@
1
+ <!-- GENERATED FILE - do not edit. Source: registry/ui/dropdown-menu.tsx. Regenerate with `pnpm skill:build`. Curated notes: apps/v4/scripts/skill-reference/notes/dropdown-menu.md -->
2
+
3
+ # dropdown-menu
4
+
5
+ Radix action menu opened from a trigger; size xs/sm/md cascades to items, items support selected check marks
6
+
7
+ Install: `npx @create-ui/cli add dropdown-menu`
8
+
9
+ ## Import
10
+
11
+ ```tsx
12
+ import { DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from "@/components/ui/dropdown-menu"
13
+ ```
14
+
15
+ Also exported: `MENU_CONTENT_RADIUS`, `MENU_ITEM_CONTENT_GAP_CLASSES`, `MENU_ITEM_SIZE_CLASSES`, `MENU_LABEL_SIZE_CLASSES`
16
+
17
+ ## DropdownMenu props
18
+
19
+ | Prop | Type | Default |
20
+ | --- | --- | --- |
21
+ | size | `xs \| sm \| md` | `sm` |
22
+
23
+ Extends `React.ComponentProps<typeof DropdownMenuPrimitive.Root>`.
24
+
25
+ ## DropdownMenuItem props
26
+
27
+ | Prop | Type | Default |
28
+ | --- | --- | --- |
29
+ | selected | `boolean` (marks the active value: data-selected attr, body text color, trailing primary-tinted check) | - |
30
+ | showCheck | `boolean` (renders the trailing check glyph only, without selected styling or primary tint) | - |
31
+
32
+ Extends `React.ComponentProps<typeof DropdownMenuPrimitive.Item>`.
33
+
34
+ ## Examples
35
+
36
+ From `dropdown-menu-demo`:
37
+
38
+ ```tsx
39
+ "use client"
40
+
41
+ import { Button } from "@/components/ui/button"
42
+ import {
43
+ DropdownMenu,
44
+ DropdownMenuContent,
45
+ DropdownMenuGroup,
46
+ DropdownMenuItem,
47
+ DropdownMenuLabel,
48
+ DropdownMenuSeparator,
49
+ DropdownMenuTrigger,
50
+ } from "@/components/ui/dropdown-menu"
51
+
52
+ export default function DropdownMenuDemo() {
53
+ return (
54
+ <DropdownMenu>
55
+ <DropdownMenuTrigger asChild>
56
+ <Button
57
+ variant="neutral-solid"
58
+ appearance="outline"
59
+ size="sm"
60
+ className="w-fit"
61
+ >
62
+ Open
63
+ </Button>
64
+ </DropdownMenuTrigger>
65
+ <DropdownMenuContent>
66
+ <DropdownMenuGroup>
67
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
68
+ <DropdownMenuItem>Profile</DropdownMenuItem>
69
+ <DropdownMenuItem>Billing</DropdownMenuItem>
70
+ <DropdownMenuItem>Settings</DropdownMenuItem>
71
+ </DropdownMenuGroup>
72
+ <DropdownMenuSeparator />
73
+ <DropdownMenuGroup>
74
+ <DropdownMenuItem>GitHub</DropdownMenuItem>
75
+ <DropdownMenuItem>Support</DropdownMenuItem>
76
+ <DropdownMenuItem disabled>API</DropdownMenuItem>
77
+ </DropdownMenuGroup>
78
+ </DropdownMenuContent>
79
+ </DropdownMenu>
80
+ )
81
+ }
82
+ ```
83
+
84
+ From `dropdown-menu-with-avatar`:
85
+
86
+ ```tsx
87
+ "use client"
88
+
89
+ import {
90
+ RiBankCardLine,
91
+ RiCheckboxCircleLine,
92
+ RiLogoutBoxLine,
93
+ RiNotificationLine,
94
+ } from "@create-ui/assets/icons"
95
+
96
+ import { Avatar, AvatarImage } from "@/components/ui/avatar"
97
+ import { Button } from "@/components/ui/button"
98
+ import {
99
+ DropdownMenu,
100
+ DropdownMenuContent,
101
+ DropdownMenuGroup,
102
+ DropdownMenuItem,
103
+ DropdownMenuSeparator,
104
+ DropdownMenuTrigger,
105
+ } from "@/components/ui/dropdown-menu"
106
+
107
+ export default function DropdownMenuWithAvatar() {
108
+ return (
109
+ <DropdownMenu>
110
+ <DropdownMenuTrigger asChild>
111
+ <Button
112
+ variant="neutral-solid"
113
+ appearance="ghost"
114
+ size="xl"
115
+ shape="pill"
116
+ iconOnly
117
+ aria-label="Open account menu"
118
+ >
119
+ <Avatar size="lg">
120
+ <AvatarImage
121
+ src="https://createui.co/avatars/luca-moretti.webp"
122
+ alt="Luca Moretti"
123
+ />
124
+ </Avatar>
125
+ </Button>
126
+ </DropdownMenuTrigger>
127
+ <DropdownMenuContent align="end">
128
+ <DropdownMenuGroup>
129
+ <DropdownMenuItem>
130
+ <RiCheckboxCircleLine />
131
+ Account
132
+ </DropdownMenuItem>
133
+ <DropdownMenuItem>
134
+ <RiBankCardLine />
135
+ Billing
136
+ </DropdownMenuItem>
137
+ <DropdownMenuItem>
138
+ <RiNotificationLine />
139
+ Notifications
140
+ </DropdownMenuItem>
141
+ </DropdownMenuGroup>
142
+ <DropdownMenuSeparator />
143
+ <DropdownMenuItem>
144
+ <RiLogoutBoxLine />
145
+ Sign Out
146
+ </DropdownMenuItem>
147
+ </DropdownMenuContent>
148
+ </DropdownMenu>
149
+ )
150
+ }
151
+ ```
152
+
153
+ More: `npx @create-ui/cli view dropdown-menu` or MCP `get_item_examples_from_registries` with "dropdown-menu-demo" / "dropdown-menu-example".
154
+
155
+ ## When to use
156
+ DropdownMenu is a trigger-attached action menu for account controls, row actions, and overflow commands; attach via `DropdownMenuTrigger asChild` wrapping a `Button`. Do not use it to bind a form value (use `Select`) and there is no popover component for arbitrary non-menu content - keep menus to menu items.
157
+ ## Gotchas
158
+ - Smaller surface than shadcn: there is no `DropdownMenuCheckboxItem`, `RadioGroup`/`RadioItem`, `Sub*`, or `Shortcut`; importing those names fails. Active-value menus use plain `DropdownMenuItem` with `selected`/`showCheck`.
159
+ - `size` lives only on the `DropdownMenu` root and cascades via context to content radius, item height, label, and icon size; `DropdownMenuContent`/`Item`/`Label` accept no size prop. `Content` has a Field-context fallback, but it is unreachable because the menu context always supplies a size, so a surrounding `Field` never resizes the menu.
160
+ - Item children are auto-laid-out: bare string/number children get wrapped in `px-1` spans, and icons are auto-sized per menu size via `[&_svg]:size-*`. Pass a bare icon then text; do not add size classes to icons or wrap icon + text yourself.
161
+ - With `asChild`, the item clones the child (e.g. `<a>` or router `Link`), keeps its props (href, target), but replaces its children with the rebuilt label-span + check layout; put icon + text directly inside the child, no extra wrappers.
162
+ - `DropdownMenuContent` portals itself (no `DropdownMenuPortal` needed) and defaults `align="start"`, not Radix's `"center"`; pass `align="end"` for trigger-right menus like avatar/account.
163
+ - `DropdownMenuGroup` is an unstyled semantic passthrough; the visible break between groups comes from `DropdownMenuSeparator`, not the group.
164
+ - Avatar-in-button triggers: an iconOnly Button is 48px (size-12) at size="xl" while Avatar xl is 56px (size-14); the button's overflow-hidden crops the avatar and clips its stroke. Pair the avatar one size DOWN from the button (Button xl + Avatar lg). If the trigger avatar carries an AvatarText fallback, also give it a variant (e.g. weak-neutral) so the initials get a background.
@@ -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.