@hilum/ui 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -4
- package/dist/chunk-J2QQDUF4.js +204 -0
- package/dist/chunk-J2QQDUF4.js.map +1 -0
- package/dist/create-theme.d.ts +27 -0
- package/dist/create-theme.js +172 -0
- package/dist/create-theme.js.map +1 -0
- package/dist/index.d.ts +21 -8
- package/dist/index.js +393 -381
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +59 -50
- package/dist/tokens.d.ts +46 -38
- package/dist/tokens.js +1 -191
- package/dist/tokens.js.map +1 -1
- package/llms.txt +1514 -0
- package/package.json +11 -7
- package/src/components/accordion.tsx +5 -5
- package/src/components/action-panel.tsx +6 -6
- package/src/components/activity-feed.tsx +4 -4
- package/src/components/alert-dialog.tsx +3 -3
- package/src/components/alert.tsx +4 -4
- package/src/components/avatar-stack.tsx +2 -2
- package/src/components/avatar.tsx +2 -2
- package/src/components/badge.tsx +6 -5
- package/src/components/breadcrumb.tsx +5 -5
- package/src/components/button-group.tsx +4 -4
- package/src/components/button.tsx +6 -5
- package/src/components/calendar.tsx +7 -7
- package/src/components/card-heading.tsx +3 -3
- package/src/components/card.tsx +3 -3
- package/src/components/chart.tsx +11 -11
- package/src/components/checkbox.tsx +1 -1
- package/src/components/color-input.tsx +7 -7
- package/src/components/color-picker.tsx +5 -5
- package/src/components/combobox.tsx +10 -10
- package/src/components/command-palette.tsx +11 -11
- package/src/components/command.tsx +13 -13
- package/src/components/context-menu.tsx +15 -16
- package/src/components/data-table.tsx +6 -6
- package/src/components/date-picker.tsx +9 -4
- package/src/components/description-list.tsx +8 -8
- package/src/components/dialog.tsx +3 -3
- package/src/components/drawer.tsx +5 -5
- package/src/components/dropdown-menu.tsx +15 -16
- package/src/components/empty-state.tsx +3 -3
- package/src/components/field.tsx +13 -6
- package/src/components/grid-list.tsx +12 -12
- package/src/components/hover-card.tsx +1 -1
- package/src/components/input-group.tsx +8 -8
- package/src/components/input-number.tsx +7 -7
- package/src/components/input-otp.tsx +3 -3
- package/src/components/input.tsx +5 -4
- package/src/components/kbd.tsx +1 -1
- package/src/components/label.tsx +1 -1
- package/src/components/menubar.tsx +21 -22
- package/src/components/native-select.tsx +4 -4
- package/src/components/navigation-menu.tsx +10 -10
- package/src/components/notification.tsx +10 -10
- package/src/components/page-heading.tsx +8 -8
- package/src/components/pagination.tsx +1 -1
- package/src/components/progress.tsx +1 -1
- package/src/components/property-row.tsx +1 -1
- package/src/components/radio-card.tsx +6 -6
- package/src/components/radio-group.tsx +3 -3
- package/src/components/resizable.tsx +3 -3
- package/src/components/scroll-area.tsx +1 -1
- package/src/components/section-heading.tsx +3 -3
- package/src/components/select.tsx +11 -11
- package/src/components/separator.tsx +1 -1
- package/src/components/sheet.tsx +3 -3
- package/src/components/sidebar.tsx +19 -19
- package/src/components/skeleton.tsx +1 -1
- package/src/components/slider.tsx +1 -1
- package/src/components/sonner.tsx +5 -5
- package/src/components/stacked-list.tsx +4 -4
- package/src/components/stat-card.tsx +6 -6
- package/src/components/steps.tsx +13 -12
- package/src/components/switch.tsx +1 -1
- package/src/components/table.tsx +9 -9
- package/src/components/tabs.tsx +2 -2
- package/src/components/textarea.tsx +4 -4
- package/src/components/toggle.tsx +8 -8
- package/src/components/tooltip.tsx +1 -1
- package/src/index.ts +3 -2
- package/src/tokens/tokens.ts +54 -40
- package/src/components/__tests__/data.test.tsx +0 -180
- package/src/components/__tests__/disclosure.test.tsx +0 -198
- package/src/components/__tests__/display.test.tsx +0 -262
- package/src/components/__tests__/feedback.test.tsx +0 -138
- package/src/components/__tests__/form.test.tsx +0 -297
- package/src/components/__tests__/layout.test.tsx +0 -388
- package/src/components/__tests__/overlay.test.tsx +0 -90
- package/src/components/__tests__/primitives.test.tsx +0 -248
package/llms.txt
ADDED
|
@@ -0,0 +1,1514 @@
|
|
|
1
|
+
# @hilum/ui — Design System
|
|
2
|
+
|
|
3
|
+
> Production-ready React design system with 74 components, OKLCH-based per-product theming, and CSS-variable-backed design tokens. Works in client-rendered and prerendered React apps, plus Electron. Tailwind v4 + Radix UI primitives.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @hilum/ui
|
|
9
|
+
# or: npm install @hilum/ui | yarn add @hilum/ui
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Peer dependencies: `react@^19`, `react-dom@^19`, `tailwindcss@^4`
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
```css
|
|
17
|
+
/* globals.css */
|
|
18
|
+
@import "tailwindcss";
|
|
19
|
+
@import "@hilum/ui/tokens.css";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
That single import registers all design tokens as CSS custom properties and Tailwind v4 utilities (`bg-brand-primary`, `text-taupe-900`, `shadow-natural`, etc.).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Theming
|
|
27
|
+
|
|
28
|
+
Every product gets its own primary and secondary brand colors. Pass two hex values — `createTheme` generates a full 11-shade OKLCH palette and returns a CSS override string.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { ThemeProvider } from "@hilum/ui/create-theme"
|
|
32
|
+
|
|
33
|
+
// Wrap your app root — re-applies automatically when props change
|
|
34
|
+
export function App() {
|
|
35
|
+
return (
|
|
36
|
+
<ThemeProvider primary="#0066FF" secondary="#FF9900">
|
|
37
|
+
<Router />
|
|
38
|
+
</ThemeProvider>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Theming API
|
|
44
|
+
|
|
45
|
+
| Export | Description |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `createTheme({ primary, secondary })` | Pure function. Returns `{ css, palette }`. Works in Node (build scripts) and browser. |
|
|
48
|
+
| `applyTheme({ primary, secondary })` | Injects `<style>` into `document.head`. Returns cleanup fn. Browser/Electron only. |
|
|
49
|
+
| `<ThemeProvider primary secondary>` | React component. Calls `applyTheme` in `useEffect`. |
|
|
50
|
+
|
|
51
|
+
### ThemeConfig
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Description |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `primary` | `string` | Hex color. Anchored at palette-500; 11 shades generated. |
|
|
56
|
+
| `secondary` | `string` | Hex color. Same structure. |
|
|
57
|
+
|
|
58
|
+
### ThemeResult
|
|
59
|
+
|
|
60
|
+
| Field | Type | Description |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `css` | `string` | Complete CSS override. Inject via `<style>` or write to a file. |
|
|
63
|
+
| `palette.primary` | `Record<string,string>` | `{ "50": "#f2f7ff", …, "950": "#000723" }` |
|
|
64
|
+
| `palette.secondary` | `Record<string,string>` | Same for secondary. |
|
|
65
|
+
|
|
66
|
+
### CSS variables overridden
|
|
67
|
+
|
|
68
|
+
- `--color-brand-primary` / `--color-brand-secondary` — affects all `bg-brand-*` utilities
|
|
69
|
+
- `--primary`, `--primary-foreground`
|
|
70
|
+
- `--accent`, `--accent-foreground`
|
|
71
|
+
- `--ring`
|
|
72
|
+
- `--warning`, `--warning-foreground`
|
|
73
|
+
- `--color-primary-{50…950}` / `--color-secondary-{50…950}` — palette vars for product CSS
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Design Tokens
|
|
78
|
+
|
|
79
|
+
### Colors
|
|
80
|
+
|
|
81
|
+
**Brand:**
|
|
82
|
+
- `bg-brand-primary` → `#C100F1` (vivid purple) — primary buttons, CTAs, focus rings
|
|
83
|
+
- `bg-brand-secondary` → `#FFF5BF` (pale lemon) — warning surfaces, secondary CTAs
|
|
84
|
+
|
|
85
|
+
**Purple scale** (`bg-purple-{50..950}`): built from `#C100F1` anchor at 500
|
|
86
|
+
**Butter scale** (`bg-butter-{50..950}`): built from `#FFF5BF` anchor at 200
|
|
87
|
+
**Taupe scale** (`bg-taupe-{50..950}`): neutral spine for text, borders, structure
|
|
88
|
+
|
|
89
|
+
**Semantic CSS vars** (use in custom CSS, never raw hex):
|
|
90
|
+
- `--background`, `--foreground` — page bg/text
|
|
91
|
+
- `--primary`, `--primary-foreground` — primary interactive color + its text
|
|
92
|
+
- `--secondary`, `--secondary-foreground` — secondary surfaces
|
|
93
|
+
- `--muted`, `--muted-foreground` — subdued surfaces and text
|
|
94
|
+
- `--accent`, `--accent-foreground` — hover tints
|
|
95
|
+
- `--border`, `--input` — borders and input backgrounds
|
|
96
|
+
- `--ring` — focus ring
|
|
97
|
+
- `--destructive`, `--destructive-foreground` — errors
|
|
98
|
+
- `--warning`, `--warning-foreground` — warnings
|
|
99
|
+
|
|
100
|
+
### Typography
|
|
101
|
+
|
|
102
|
+
Use as Tailwind utilities (e.g. `className="display"`):
|
|
103
|
+
|
|
104
|
+
| Class | Font | Size | Weight | Usage |
|
|
105
|
+
|---|---|---|---|---|
|
|
106
|
+
| `display-xl` | Instrument Serif | 3rem | 400 | Hero H1 |
|
|
107
|
+
| `display` | Instrument Serif | 2.25rem | 400 | Page H1 |
|
|
108
|
+
| `heading-xl` | Instrument Serif | 1.875rem | 400 | Section headings |
|
|
109
|
+
| `heading` | Instrument Serif | 1.5rem | 400 | Card titles |
|
|
110
|
+
| `subheading` | Inter | 1.25rem | 400 | Subheadings |
|
|
111
|
+
| `body-lg` | Inter | 1rem | 400 | Large body text |
|
|
112
|
+
| `body` | Inter | 0.875rem | 400 | Default body |
|
|
113
|
+
| `caption` | Inter | 0.75rem | 400 | Metadata, helper text |
|
|
114
|
+
| `label` | Inter | 0.75rem | 600 | Section labels (uppercase) |
|
|
115
|
+
| `caption-xs` | Inter | 0.625rem | 400 | Tiny metadata |
|
|
116
|
+
|
|
117
|
+
### Shadows
|
|
118
|
+
|
|
119
|
+
- `shadow-natural` — cards, default elevation
|
|
120
|
+
- `shadow-elevated` — modals, floating panels
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Components
|
|
125
|
+
|
|
126
|
+
All components are imported from `@hilum/ui`.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### Button
|
|
131
|
+
|
|
132
|
+
Triggers actions. Supports variants, sizes, icons, and disabled/loading states.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { Button } from "@hilum/ui"
|
|
136
|
+
|
|
137
|
+
// Variants
|
|
138
|
+
<Button>Default</Button>
|
|
139
|
+
<Button variant="brand">Brand</Button>
|
|
140
|
+
<Button variant="outline">Outline</Button>
|
|
141
|
+
<Button variant="ghost">Ghost</Button>
|
|
142
|
+
<Button variant="secondary">Secondary</Button>
|
|
143
|
+
<Button variant="destructive">Destructive</Button>
|
|
144
|
+
<Button variant="link">Link</Button>
|
|
145
|
+
|
|
146
|
+
// Sizes
|
|
147
|
+
<Button size="xs">Extra Small</Button>
|
|
148
|
+
<Button size="sm">Small</Button>
|
|
149
|
+
<Button size="lg">Large</Button>
|
|
150
|
+
<Button size="icon"><Plus /></Button>
|
|
151
|
+
|
|
152
|
+
// Pill shape
|
|
153
|
+
<Button className="rounded-full">Get started</Button>
|
|
154
|
+
|
|
155
|
+
// Loading
|
|
156
|
+
<Button><Loader2 className="animate-spin" size={15} /> Saving...</Button>
|
|
157
|
+
|
|
158
|
+
// As child (polymorphic)
|
|
159
|
+
<Button asChild><a href="/path">Link button</a></Button>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Props: `variant`, `size`, `asChild`, `disabled`, plus all `<button>` props.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### Badge
|
|
167
|
+
|
|
168
|
+
Compact labels for status, categories, and metadata.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { Badge } from "@hilum/ui"
|
|
172
|
+
|
|
173
|
+
<Badge>Default</Badge>
|
|
174
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
175
|
+
<Badge variant="outline">Outline</Badge>
|
|
176
|
+
<Badge variant="brand">Brand</Badge>
|
|
177
|
+
<Badge variant="success">Success</Badge>
|
|
178
|
+
<Badge variant="warning">Warning</Badge>
|
|
179
|
+
<Badge variant="destructive">Error</Badge>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Props: `variant`.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### Input
|
|
187
|
+
|
|
188
|
+
Text input field. Styled with taupe palette and brand focus ring.
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { Input } from "@hilum/ui"
|
|
192
|
+
|
|
193
|
+
<Input placeholder="Email address" />
|
|
194
|
+
<Input type="password" />
|
|
195
|
+
<Input disabled value="Read-only" />
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Accepts all `<input>` props.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### Textarea
|
|
203
|
+
|
|
204
|
+
Multi-line text input.
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
import { Textarea } from "@hilum/ui"
|
|
208
|
+
|
|
209
|
+
<Textarea placeholder="Describe your issue..." rows={4} />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Accepts all `<textarea>` props.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### Label
|
|
217
|
+
|
|
218
|
+
Accessible label for form fields. Pairs with any input via `htmlFor`.
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { Label } from "@hilum/ui"
|
|
222
|
+
|
|
223
|
+
<Label htmlFor="email">Email address</Label>
|
|
224
|
+
<Input id="email" type="email" />
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
### Field
|
|
230
|
+
|
|
231
|
+
Composed form field: label + input + helper/error text.
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
import { Field } from "@hilum/ui"
|
|
235
|
+
|
|
236
|
+
<Field label="Email" hint="We'll never share your email.">
|
|
237
|
+
<Input placeholder="you@example.com" />
|
|
238
|
+
</Field>
|
|
239
|
+
|
|
240
|
+
<Field label="Username" error="Username is already taken">
|
|
241
|
+
<Input value="john" />
|
|
242
|
+
</Field>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Props: `label`, `hint`, `error`, `required`, `children`.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### Select
|
|
250
|
+
|
|
251
|
+
Dropdown selection backed by Radix UI.
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@hilum/ui"
|
|
255
|
+
|
|
256
|
+
<Select>
|
|
257
|
+
<SelectTrigger>
|
|
258
|
+
<SelectValue placeholder="Pick a fruit" />
|
|
259
|
+
</SelectTrigger>
|
|
260
|
+
<SelectContent>
|
|
261
|
+
<SelectItem value="apple">Apple</SelectItem>
|
|
262
|
+
<SelectItem value="banana">Banana</SelectItem>
|
|
263
|
+
<SelectItem value="mango">Mango</SelectItem>
|
|
264
|
+
</SelectContent>
|
|
265
|
+
</Select>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Combobox
|
|
271
|
+
|
|
272
|
+
Searchable select with filterable options.
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
import { Combobox } from "@hilum/ui"
|
|
276
|
+
|
|
277
|
+
<Combobox
|
|
278
|
+
options={[
|
|
279
|
+
{ value: "react", label: "React" },
|
|
280
|
+
{ value: "vue", label: "Vue" },
|
|
281
|
+
{ value: "svelte", label: "Svelte" },
|
|
282
|
+
]}
|
|
283
|
+
placeholder="Select framework..."
|
|
284
|
+
value={value}
|
|
285
|
+
onValueChange={setValue}
|
|
286
|
+
/>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Props: `options`, `value`, `onValueChange`, `placeholder`, `disabled`.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
### Dialog
|
|
294
|
+
|
|
295
|
+
Modal overlay with header, content, and footer.
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
import {
|
|
299
|
+
Dialog, DialogTrigger, DialogContent,
|
|
300
|
+
DialogHeader, DialogTitle, DialogDescription, DialogFooter,
|
|
301
|
+
} from "@hilum/ui"
|
|
302
|
+
|
|
303
|
+
<Dialog>
|
|
304
|
+
<DialogTrigger asChild>
|
|
305
|
+
<Button>Open dialog</Button>
|
|
306
|
+
</DialogTrigger>
|
|
307
|
+
<DialogContent>
|
|
308
|
+
<DialogHeader>
|
|
309
|
+
<DialogTitle>Confirm deletion</DialogTitle>
|
|
310
|
+
<DialogDescription>This action cannot be undone.</DialogDescription>
|
|
311
|
+
</DialogHeader>
|
|
312
|
+
<DialogFooter>
|
|
313
|
+
<Button variant="outline">Cancel</Button>
|
|
314
|
+
<Button variant="destructive">Delete</Button>
|
|
315
|
+
</DialogFooter>
|
|
316
|
+
</DialogContent>
|
|
317
|
+
</Dialog>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### Sheet
|
|
323
|
+
|
|
324
|
+
Slide-in panel from any edge of the screen.
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
import {
|
|
328
|
+
Sheet, SheetTrigger, SheetContent,
|
|
329
|
+
SheetHeader, SheetTitle, SheetDescription,
|
|
330
|
+
} from "@hilum/ui"
|
|
331
|
+
|
|
332
|
+
<Sheet>
|
|
333
|
+
<SheetTrigger asChild><Button>Open sheet</Button></SheetTrigger>
|
|
334
|
+
<SheetContent side="right"> {/* side: "top" | "right" | "bottom" | "left" */}
|
|
335
|
+
<SheetHeader>
|
|
336
|
+
<SheetTitle>Edit profile</SheetTitle>
|
|
337
|
+
<SheetDescription>Make changes to your profile here.</SheetDescription>
|
|
338
|
+
</SheetHeader>
|
|
339
|
+
{/* content */}
|
|
340
|
+
</SheetContent>
|
|
341
|
+
</Sheet>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
### Drawer
|
|
347
|
+
|
|
348
|
+
Bottom drawer for mobile-friendly overlays.
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle } from "@hilum/ui"
|
|
352
|
+
|
|
353
|
+
<Drawer>
|
|
354
|
+
<DrawerTrigger asChild><Button>Open drawer</Button></DrawerTrigger>
|
|
355
|
+
<DrawerContent>
|
|
356
|
+
<DrawerHeader>
|
|
357
|
+
<DrawerTitle>Filters</DrawerTitle>
|
|
358
|
+
</DrawerHeader>
|
|
359
|
+
{/* content */}
|
|
360
|
+
</DrawerContent>
|
|
361
|
+
</Drawer>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### Popover
|
|
367
|
+
|
|
368
|
+
Floating content anchored to a trigger element.
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
import { Popover, PopoverTrigger, PopoverContent } from "@hilum/ui"
|
|
372
|
+
|
|
373
|
+
<Popover>
|
|
374
|
+
<PopoverTrigger asChild><Button variant="outline">Open</Button></PopoverTrigger>
|
|
375
|
+
<PopoverContent>
|
|
376
|
+
<p className="body">Popover content here.</p>
|
|
377
|
+
</PopoverContent>
|
|
378
|
+
</Popover>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### Tooltip
|
|
384
|
+
|
|
385
|
+
Short contextual hint on hover/focus.
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "@hilum/ui"
|
|
389
|
+
|
|
390
|
+
<TooltipProvider>
|
|
391
|
+
<Tooltip>
|
|
392
|
+
<TooltipTrigger asChild><Button size="icon"><Settings /></Button></TooltipTrigger>
|
|
393
|
+
<TooltipContent>Settings</TooltipContent>
|
|
394
|
+
</Tooltip>
|
|
395
|
+
</TooltipProvider>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Wrap app root with `<TooltipProvider>` once.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
### Dropdown Menu
|
|
403
|
+
|
|
404
|
+
Context menu for actions attached to a trigger button.
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
import {
|
|
408
|
+
DropdownMenu, DropdownMenuTrigger, DropdownMenuContent,
|
|
409
|
+
DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel,
|
|
410
|
+
} from "@hilum/ui"
|
|
411
|
+
|
|
412
|
+
<DropdownMenu>
|
|
413
|
+
<DropdownMenuTrigger asChild><Button variant="outline">Actions</Button></DropdownMenuTrigger>
|
|
414
|
+
<DropdownMenuContent>
|
|
415
|
+
<DropdownMenuLabel>My account</DropdownMenuLabel>
|
|
416
|
+
<DropdownMenuSeparator />
|
|
417
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
418
|
+
<DropdownMenuItem>Settings</DropdownMenuItem>
|
|
419
|
+
<DropdownMenuSeparator />
|
|
420
|
+
<DropdownMenuItem className="text-destructive">Sign out</DropdownMenuItem>
|
|
421
|
+
</DropdownMenuContent>
|
|
422
|
+
</DropdownMenu>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
### Context Menu
|
|
428
|
+
|
|
429
|
+
Right-click / long-press menu.
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import {
|
|
433
|
+
ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem,
|
|
434
|
+
} from "@hilum/ui"
|
|
435
|
+
|
|
436
|
+
<ContextMenu>
|
|
437
|
+
<ContextMenuTrigger>Right-click me</ContextMenuTrigger>
|
|
438
|
+
<ContextMenuContent>
|
|
439
|
+
<ContextMenuItem>Copy</ContextMenuItem>
|
|
440
|
+
<ContextMenuItem>Paste</ContextMenuItem>
|
|
441
|
+
<ContextMenuItem className="text-destructive">Delete</ContextMenuItem>
|
|
442
|
+
</ContextMenuContent>
|
|
443
|
+
</ContextMenu>
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### Card
|
|
449
|
+
|
|
450
|
+
Versatile surface container.
|
|
451
|
+
|
|
452
|
+
```tsx
|
|
453
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@hilum/ui"
|
|
454
|
+
|
|
455
|
+
<Card>
|
|
456
|
+
<CardHeader>
|
|
457
|
+
<CardTitle className="subheading">Card title</CardTitle>
|
|
458
|
+
<CardDescription className="body">Supporting text.</CardDescription>
|
|
459
|
+
</CardHeader>
|
|
460
|
+
<CardContent>
|
|
461
|
+
<p className="body text-taupe-500">Content goes here.</p>
|
|
462
|
+
</CardContent>
|
|
463
|
+
<CardFooter>
|
|
464
|
+
<Button>Action</Button>
|
|
465
|
+
</CardFooter>
|
|
466
|
+
</Card>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Variants: `default` (white with natural shadow), `muted` (taupe-50).
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
### Tabs
|
|
474
|
+
|
|
475
|
+
Horizontal tab navigation with content panels.
|
|
476
|
+
|
|
477
|
+
```tsx
|
|
478
|
+
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@hilum/ui"
|
|
479
|
+
|
|
480
|
+
<Tabs defaultValue="overview">
|
|
481
|
+
<TabsList>
|
|
482
|
+
<TabsTrigger value="overview">Overview</TabsTrigger>
|
|
483
|
+
<TabsTrigger value="settings">Settings</TabsTrigger>
|
|
484
|
+
<TabsTrigger value="billing">Billing</TabsTrigger>
|
|
485
|
+
</TabsList>
|
|
486
|
+
<TabsContent value="overview">Overview content</TabsContent>
|
|
487
|
+
<TabsContent value="settings">Settings content</TabsContent>
|
|
488
|
+
<TabsContent value="billing">Billing content</TabsContent>
|
|
489
|
+
</Tabs>
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
### Accordion
|
|
495
|
+
|
|
496
|
+
Collapsible content sections.
|
|
497
|
+
|
|
498
|
+
```tsx
|
|
499
|
+
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "@hilum/ui"
|
|
500
|
+
|
|
501
|
+
<Accordion type="single" collapsible>
|
|
502
|
+
<AccordionItem value="item-1">
|
|
503
|
+
<AccordionTrigger>Is it accessible?</AccordionTrigger>
|
|
504
|
+
<AccordionContent>Yes. It adheres to WAI-ARIA.</AccordionContent>
|
|
505
|
+
</AccordionItem>
|
|
506
|
+
<AccordionItem value="item-2">
|
|
507
|
+
<AccordionTrigger>Is it styled?</AccordionTrigger>
|
|
508
|
+
<AccordionContent>Yes. Comes with default styles.</AccordionContent>
|
|
509
|
+
</AccordionItem>
|
|
510
|
+
</Accordion>
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
`type`: `"single"` | `"multiple"`. `collapsible`: allow closing when single.
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
### Avatar
|
|
518
|
+
|
|
519
|
+
User profile image with fallback initials.
|
|
520
|
+
|
|
521
|
+
```tsx
|
|
522
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@hilum/ui"
|
|
523
|
+
|
|
524
|
+
<Avatar>
|
|
525
|
+
<AvatarImage src="https://example.com/photo.jpg" alt="Jane Doe" />
|
|
526
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
527
|
+
</Avatar>
|
|
528
|
+
|
|
529
|
+
// Sizes: xs, sm, default, lg, xl
|
|
530
|
+
<Avatar size="sm"><AvatarFallback>AB</AvatarFallback></Avatar>
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
### Avatar Stack
|
|
536
|
+
|
|
537
|
+
Overlapping row of avatars with overflow count.
|
|
538
|
+
|
|
539
|
+
```tsx
|
|
540
|
+
import { AvatarStack, Avatar, AvatarFallback } from "@hilum/ui"
|
|
541
|
+
|
|
542
|
+
<AvatarStack>
|
|
543
|
+
<Avatar><AvatarFallback>AB</AvatarFallback></Avatar>
|
|
544
|
+
<Avatar><AvatarFallback>CD</AvatarFallback></Avatar>
|
|
545
|
+
<Avatar><AvatarFallback>EF</AvatarFallback></Avatar>
|
|
546
|
+
</AvatarStack>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
### Checkbox
|
|
552
|
+
|
|
553
|
+
Binary selection with accessible label.
|
|
554
|
+
|
|
555
|
+
```tsx
|
|
556
|
+
import { Checkbox } from "@hilum/ui"
|
|
557
|
+
|
|
558
|
+
<div className="flex items-center gap-2">
|
|
559
|
+
<Checkbox id="terms" checked={checked} onCheckedChange={setChecked} />
|
|
560
|
+
<Label htmlFor="terms">Accept terms and conditions</Label>
|
|
561
|
+
</div>
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
### Switch
|
|
567
|
+
|
|
568
|
+
Toggle between two states.
|
|
569
|
+
|
|
570
|
+
```tsx
|
|
571
|
+
import { Switch } from "@hilum/ui"
|
|
572
|
+
|
|
573
|
+
<Switch checked={enabled} onCheckedChange={setEnabled} />
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
### Slider
|
|
579
|
+
|
|
580
|
+
Range input for selecting a numeric value.
|
|
581
|
+
|
|
582
|
+
```tsx
|
|
583
|
+
import { Slider } from "@hilum/ui"
|
|
584
|
+
|
|
585
|
+
<Slider
|
|
586
|
+
min={0}
|
|
587
|
+
max={100}
|
|
588
|
+
step={1}
|
|
589
|
+
value={[volume]}
|
|
590
|
+
onValueChange={([v]) => setVolume(v)}
|
|
591
|
+
/>
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
### Radio Group
|
|
597
|
+
|
|
598
|
+
Single-selection from a group of options.
|
|
599
|
+
|
|
600
|
+
```tsx
|
|
601
|
+
import { RadioGroup, RadioGroupItem } from "@hilum/ui"
|
|
602
|
+
|
|
603
|
+
<RadioGroup value={plan} onValueChange={setPlan}>
|
|
604
|
+
<div className="flex items-center gap-2">
|
|
605
|
+
<RadioGroupItem value="starter" id="starter" />
|
|
606
|
+
<Label htmlFor="starter">Starter</Label>
|
|
607
|
+
</div>
|
|
608
|
+
<div className="flex items-center gap-2">
|
|
609
|
+
<RadioGroupItem value="pro" id="pro" />
|
|
610
|
+
<Label htmlFor="pro">Pro</Label>
|
|
611
|
+
</div>
|
|
612
|
+
</RadioGroup>
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
### Progress
|
|
618
|
+
|
|
619
|
+
Linear progress indicator.
|
|
620
|
+
|
|
621
|
+
```tsx
|
|
622
|
+
import { Progress } from "@hilum/ui"
|
|
623
|
+
|
|
624
|
+
<Progress value={72} /> // 0–100
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
### Skeleton
|
|
630
|
+
|
|
631
|
+
Loading placeholder that matches content layout.
|
|
632
|
+
|
|
633
|
+
```tsx
|
|
634
|
+
import { Skeleton } from "@hilum/ui"
|
|
635
|
+
|
|
636
|
+
<Skeleton className="h-4 w-48 rounded" />
|
|
637
|
+
<Skeleton className="h-32 w-full rounded-xl" />
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
### Spinner
|
|
643
|
+
|
|
644
|
+
Animated loading indicator.
|
|
645
|
+
|
|
646
|
+
```tsx
|
|
647
|
+
import { Spinner } from "@hilum/ui"
|
|
648
|
+
|
|
649
|
+
<Spinner />
|
|
650
|
+
<Spinner size="sm" />
|
|
651
|
+
<Spinner size="lg" />
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
### Separator
|
|
657
|
+
|
|
658
|
+
Horizontal or vertical divider line.
|
|
659
|
+
|
|
660
|
+
```tsx
|
|
661
|
+
import { Separator } from "@hilum/ui"
|
|
662
|
+
|
|
663
|
+
<Separator />
|
|
664
|
+
<Separator orientation="vertical" className="h-8" />
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
### Breadcrumb
|
|
670
|
+
|
|
671
|
+
Navigation hierarchy indicator.
|
|
672
|
+
|
|
673
|
+
```tsx
|
|
674
|
+
import {
|
|
675
|
+
Breadcrumb, BreadcrumbList, BreadcrumbItem,
|
|
676
|
+
BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator,
|
|
677
|
+
} from "@hilum/ui"
|
|
678
|
+
|
|
679
|
+
<Breadcrumb>
|
|
680
|
+
<BreadcrumbList>
|
|
681
|
+
<BreadcrumbItem><BreadcrumbLink href="/">Home</BreadcrumbLink></BreadcrumbItem>
|
|
682
|
+
<BreadcrumbSeparator />
|
|
683
|
+
<BreadcrumbItem><BreadcrumbLink href="/docs">Docs</BreadcrumbLink></BreadcrumbItem>
|
|
684
|
+
<BreadcrumbSeparator />
|
|
685
|
+
<BreadcrumbItem><BreadcrumbPage>Button</BreadcrumbPage></BreadcrumbItem>
|
|
686
|
+
</BreadcrumbList>
|
|
687
|
+
</Breadcrumb>
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
---
|
|
691
|
+
|
|
692
|
+
### Pagination
|
|
693
|
+
|
|
694
|
+
Page navigation for data lists.
|
|
695
|
+
|
|
696
|
+
```tsx
|
|
697
|
+
import {
|
|
698
|
+
Pagination, PaginationContent, PaginationItem,
|
|
699
|
+
PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis,
|
|
700
|
+
} from "@hilum/ui"
|
|
701
|
+
|
|
702
|
+
<Pagination>
|
|
703
|
+
<PaginationContent>
|
|
704
|
+
<PaginationItem><PaginationPrevious href="#" /></PaginationItem>
|
|
705
|
+
<PaginationItem><PaginationLink href="#">1</PaginationLink></PaginationItem>
|
|
706
|
+
<PaginationItem><PaginationEllipsis /></PaginationItem>
|
|
707
|
+
<PaginationItem><PaginationLink href="#" isActive>5</PaginationLink></PaginationItem>
|
|
708
|
+
<PaginationItem><PaginationNext href="#" /></PaginationItem>
|
|
709
|
+
</PaginationContent>
|
|
710
|
+
</Pagination>
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
### Table
|
|
716
|
+
|
|
717
|
+
Data table with header, body, and footer.
|
|
718
|
+
|
|
719
|
+
```tsx
|
|
720
|
+
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableCaption } from "@hilum/ui"
|
|
721
|
+
|
|
722
|
+
<Table>
|
|
723
|
+
<TableHeader>
|
|
724
|
+
<TableRow>
|
|
725
|
+
<TableHead>Name</TableHead>
|
|
726
|
+
<TableHead>Status</TableHead>
|
|
727
|
+
<TableHead className="text-right">Amount</TableHead>
|
|
728
|
+
</TableRow>
|
|
729
|
+
</TableHeader>
|
|
730
|
+
<TableBody>
|
|
731
|
+
<TableRow>
|
|
732
|
+
<TableCell className="font-medium">Alice</TableCell>
|
|
733
|
+
<TableCell><Badge variant="success">Active</Badge></TableCell>
|
|
734
|
+
<TableCell className="text-right">$250</TableCell>
|
|
735
|
+
</TableRow>
|
|
736
|
+
</TableBody>
|
|
737
|
+
</Table>
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
---
|
|
741
|
+
|
|
742
|
+
### Data Table
|
|
743
|
+
|
|
744
|
+
Full-featured table with sorting, filtering, pagination via `@tanstack/react-table`.
|
|
745
|
+
|
|
746
|
+
```tsx
|
|
747
|
+
import { DataTable } from "@hilum/ui"
|
|
748
|
+
import { ColumnDef } from "@tanstack/react-table"
|
|
749
|
+
|
|
750
|
+
const columns: ColumnDef<User>[] = [
|
|
751
|
+
{ accessorKey: "name", header: "Name" },
|
|
752
|
+
{ accessorKey: "email", header: "Email" },
|
|
753
|
+
{ accessorKey: "role", header: "Role" },
|
|
754
|
+
]
|
|
755
|
+
|
|
756
|
+
<DataTable columns={columns} data={users} />
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
### Calendar
|
|
762
|
+
|
|
763
|
+
Date picker calendar grid.
|
|
764
|
+
|
|
765
|
+
```tsx
|
|
766
|
+
import { Calendar } from "@hilum/ui"
|
|
767
|
+
|
|
768
|
+
<Calendar
|
|
769
|
+
mode="single"
|
|
770
|
+
selected={date}
|
|
771
|
+
onSelect={setDate}
|
|
772
|
+
/>
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
Modes: `"single"` | `"multiple"` | `"range"`. Powered by `react-day-picker`.
|
|
776
|
+
|
|
777
|
+
---
|
|
778
|
+
|
|
779
|
+
### Date Picker
|
|
780
|
+
|
|
781
|
+
Calendar in a popover triggered by a button.
|
|
782
|
+
|
|
783
|
+
```tsx
|
|
784
|
+
import { DatePicker } from "@hilum/ui"
|
|
785
|
+
|
|
786
|
+
<DatePicker value={date} onChange={setDate} placeholder="Pick a date" />
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
### Command
|
|
792
|
+
|
|
793
|
+
Command palette / search interface.
|
|
794
|
+
|
|
795
|
+
```tsx
|
|
796
|
+
import {
|
|
797
|
+
Command, CommandInput, CommandList,
|
|
798
|
+
CommandEmpty, CommandGroup, CommandItem, CommandSeparator,
|
|
799
|
+
} from "@hilum/ui"
|
|
800
|
+
|
|
801
|
+
<Command>
|
|
802
|
+
<CommandInput placeholder="Search..." />
|
|
803
|
+
<CommandList>
|
|
804
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
805
|
+
<CommandGroup heading="Actions">
|
|
806
|
+
<CommandItem>New file</CommandItem>
|
|
807
|
+
<CommandItem>New folder</CommandItem>
|
|
808
|
+
</CommandGroup>
|
|
809
|
+
<CommandSeparator />
|
|
810
|
+
<CommandGroup heading="Navigation">
|
|
811
|
+
<CommandItem>Dashboard</CommandItem>
|
|
812
|
+
</CommandGroup>
|
|
813
|
+
</CommandList>
|
|
814
|
+
</Command>
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
### Navigation Menu
|
|
820
|
+
|
|
821
|
+
Horizontal nav with mega-menu dropdowns.
|
|
822
|
+
|
|
823
|
+
```tsx
|
|
824
|
+
import {
|
|
825
|
+
NavigationMenu, NavigationMenuList, NavigationMenuItem,
|
|
826
|
+
NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink,
|
|
827
|
+
} from "@hilum/ui"
|
|
828
|
+
|
|
829
|
+
<NavigationMenu>
|
|
830
|
+
<NavigationMenuList>
|
|
831
|
+
<NavigationMenuItem>
|
|
832
|
+
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
|
|
833
|
+
<NavigationMenuContent>
|
|
834
|
+
{/* Grid of links */}
|
|
835
|
+
</NavigationMenuContent>
|
|
836
|
+
</NavigationMenuItem>
|
|
837
|
+
<NavigationMenuItem>
|
|
838
|
+
<NavigationMenuLink href="/pricing">Pricing</NavigationMenuLink>
|
|
839
|
+
</NavigationMenuItem>
|
|
840
|
+
</NavigationMenuList>
|
|
841
|
+
</NavigationMenu>
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
---
|
|
845
|
+
|
|
846
|
+
### Menubar
|
|
847
|
+
|
|
848
|
+
Application-style horizontal menu bar.
|
|
849
|
+
|
|
850
|
+
```tsx
|
|
851
|
+
import {
|
|
852
|
+
Menubar, MenubarMenu, MenubarTrigger, MenubarContent,
|
|
853
|
+
MenubarItem, MenubarSeparator, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem,
|
|
854
|
+
} from "@hilum/ui"
|
|
855
|
+
|
|
856
|
+
<Menubar>
|
|
857
|
+
<MenubarMenu>
|
|
858
|
+
<MenubarTrigger>File</MenubarTrigger>
|
|
859
|
+
<MenubarContent>
|
|
860
|
+
<MenubarItem>New File <MenubarShortcut>⌘N</MenubarShortcut></MenubarItem>
|
|
861
|
+
<MenubarSeparator />
|
|
862
|
+
<MenubarItem>Save <MenubarShortcut>⌘S</MenubarShortcut></MenubarItem>
|
|
863
|
+
</MenubarContent>
|
|
864
|
+
</MenubarMenu>
|
|
865
|
+
</Menubar>
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
---
|
|
869
|
+
|
|
870
|
+
### Sidebar
|
|
871
|
+
|
|
872
|
+
Full application sidebar with navigation groups, collapsible sections, and sticky header/footer.
|
|
873
|
+
|
|
874
|
+
```tsx
|
|
875
|
+
import {
|
|
876
|
+
SidebarProvider, Sidebar, SidebarHeader, SidebarContent,
|
|
877
|
+
SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuItem,
|
|
878
|
+
SidebarMenuButton, SidebarFooter,
|
|
879
|
+
} from "@hilum/ui"
|
|
880
|
+
|
|
881
|
+
<SidebarProvider>
|
|
882
|
+
<Sidebar>
|
|
883
|
+
<SidebarHeader>Logo / brand</SidebarHeader>
|
|
884
|
+
<SidebarContent>
|
|
885
|
+
<SidebarGroup>
|
|
886
|
+
<SidebarGroupLabel>Navigation</SidebarGroupLabel>
|
|
887
|
+
<SidebarMenu>
|
|
888
|
+
<SidebarMenuItem>
|
|
889
|
+
<SidebarMenuButton asChild>
|
|
890
|
+
<a href="/dashboard">Dashboard</a>
|
|
891
|
+
</SidebarMenuButton>
|
|
892
|
+
</SidebarMenuItem>
|
|
893
|
+
</SidebarMenu>
|
|
894
|
+
</SidebarGroup>
|
|
895
|
+
</SidebarContent>
|
|
896
|
+
<SidebarFooter>Footer content</SidebarFooter>
|
|
897
|
+
</Sidebar>
|
|
898
|
+
<main>{/* page content */}</main>
|
|
899
|
+
</SidebarProvider>
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
### Chart
|
|
905
|
+
|
|
906
|
+
Recharts-based data visualizations (line, bar, area, pie, radar, radial).
|
|
907
|
+
|
|
908
|
+
```tsx
|
|
909
|
+
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@hilum/ui"
|
|
910
|
+
import { LineChart, Line, XAxis, YAxis, CartesianGrid } from "recharts"
|
|
911
|
+
|
|
912
|
+
const config = {
|
|
913
|
+
revenue: { label: "Revenue", color: "var(--color-brand-primary)" },
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
<ChartContainer config={config} className="h-64">
|
|
917
|
+
<LineChart data={data}>
|
|
918
|
+
<CartesianGrid strokeDasharray="3 3" stroke="var(--color-taupe-100)" />
|
|
919
|
+
<XAxis dataKey="month" />
|
|
920
|
+
<YAxis />
|
|
921
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
922
|
+
<Line type="monotone" dataKey="revenue" stroke="var(--chart-1)" />
|
|
923
|
+
</LineChart>
|
|
924
|
+
</ChartContainer>
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
---
|
|
928
|
+
|
|
929
|
+
### Carousel
|
|
930
|
+
|
|
931
|
+
Horizontal scrolling carousel.
|
|
932
|
+
|
|
933
|
+
```tsx
|
|
934
|
+
import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "@hilum/ui"
|
|
935
|
+
|
|
936
|
+
<Carousel>
|
|
937
|
+
<CarouselContent>
|
|
938
|
+
<CarouselItem><Card>Slide 1</Card></CarouselItem>
|
|
939
|
+
<CarouselItem><Card>Slide 2</Card></CarouselItem>
|
|
940
|
+
<CarouselItem><Card>Slide 3</Card></CarouselItem>
|
|
941
|
+
</CarouselContent>
|
|
942
|
+
<CarouselPrevious />
|
|
943
|
+
<CarouselNext />
|
|
944
|
+
</Carousel>
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
---
|
|
948
|
+
|
|
949
|
+
### Hover Card
|
|
950
|
+
|
|
951
|
+
Rich preview card that appears on hover.
|
|
952
|
+
|
|
953
|
+
```tsx
|
|
954
|
+
import { HoverCard, HoverCardTrigger, HoverCardContent } from "@hilum/ui"
|
|
955
|
+
|
|
956
|
+
<HoverCard>
|
|
957
|
+
<HoverCardTrigger asChild>
|
|
958
|
+
<a href="#">@hilum_labs</a>
|
|
959
|
+
</HoverCardTrigger>
|
|
960
|
+
<HoverCardContent>
|
|
961
|
+
<p className="body font-medium">Hilum Labs</p>
|
|
962
|
+
<p className="caption text-taupe-400">Building the future of education.</p>
|
|
963
|
+
</HoverCardContent>
|
|
964
|
+
</HoverCard>
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
---
|
|
968
|
+
|
|
969
|
+
### Collapsible
|
|
970
|
+
|
|
971
|
+
Show/hide any content section.
|
|
972
|
+
|
|
973
|
+
```tsx
|
|
974
|
+
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@hilum/ui"
|
|
975
|
+
|
|
976
|
+
<Collapsible open={open} onOpenChange={setOpen}>
|
|
977
|
+
<CollapsibleTrigger asChild>
|
|
978
|
+
<Button variant="ghost">Advanced options <ChevronDown size={14} /></Button>
|
|
979
|
+
</CollapsibleTrigger>
|
|
980
|
+
<CollapsibleContent>
|
|
981
|
+
{/* hidden content */}
|
|
982
|
+
</CollapsibleContent>
|
|
983
|
+
</Collapsible>
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
---
|
|
987
|
+
|
|
988
|
+
### Resizable
|
|
989
|
+
|
|
990
|
+
Draggable panels for split layouts.
|
|
991
|
+
|
|
992
|
+
```tsx
|
|
993
|
+
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@hilum/ui"
|
|
994
|
+
|
|
995
|
+
<ResizablePanelGroup direction="horizontal" className="h-64 rounded-xl border">
|
|
996
|
+
<ResizablePanel defaultSize={30}>Left</ResizablePanel>
|
|
997
|
+
<ResizableHandle />
|
|
998
|
+
<ResizablePanel>Right</ResizablePanel>
|
|
999
|
+
</ResizablePanelGroup>
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
---
|
|
1003
|
+
|
|
1004
|
+
### Scroll Area
|
|
1005
|
+
|
|
1006
|
+
Custom scrollbar for overflow containers.
|
|
1007
|
+
|
|
1008
|
+
```tsx
|
|
1009
|
+
import { ScrollArea } from "@hilum/ui"
|
|
1010
|
+
|
|
1011
|
+
<ScrollArea className="h-48 w-full">
|
|
1012
|
+
{/* long content */}
|
|
1013
|
+
</ScrollArea>
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
---
|
|
1017
|
+
|
|
1018
|
+
### Kbd
|
|
1019
|
+
|
|
1020
|
+
Keyboard shortcut display.
|
|
1021
|
+
|
|
1022
|
+
```tsx
|
|
1023
|
+
import { Kbd } from "@hilum/ui"
|
|
1024
|
+
|
|
1025
|
+
<p className="body">Press <Kbd>⌘</Kbd> + <Kbd>K</Kbd> to open the command palette.</p>
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
---
|
|
1029
|
+
|
|
1030
|
+
### Alert
|
|
1031
|
+
|
|
1032
|
+
Contextual feedback for user actions or system states.
|
|
1033
|
+
|
|
1034
|
+
```tsx
|
|
1035
|
+
import { Alert, AlertTitle, AlertDescription } from "@hilum/ui"
|
|
1036
|
+
import { Terminal } from "lucide-react"
|
|
1037
|
+
|
|
1038
|
+
<Alert>
|
|
1039
|
+
<Terminal size={16} />
|
|
1040
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
1041
|
+
<AlertDescription>You can add components and dependencies to your app.</AlertDescription>
|
|
1042
|
+
</Alert>
|
|
1043
|
+
|
|
1044
|
+
<Alert variant="destructive">
|
|
1045
|
+
<AlertTitle>Error</AlertTitle>
|
|
1046
|
+
<AlertDescription>Something went wrong. Please try again.</AlertDescription>
|
|
1047
|
+
</Alert>
|
|
1048
|
+
```
|
|
1049
|
+
|
|
1050
|
+
---
|
|
1051
|
+
|
|
1052
|
+
### Alert Dialog
|
|
1053
|
+
|
|
1054
|
+
Modal that requires user confirmation before a destructive action.
|
|
1055
|
+
|
|
1056
|
+
```tsx
|
|
1057
|
+
import {
|
|
1058
|
+
AlertDialog, AlertDialogTrigger, AlertDialogContent,
|
|
1059
|
+
AlertDialogHeader, AlertDialogTitle, AlertDialogDescription,
|
|
1060
|
+
AlertDialogFooter, AlertDialogCancel, AlertDialogAction,
|
|
1061
|
+
} from "@hilum/ui"
|
|
1062
|
+
|
|
1063
|
+
<AlertDialog>
|
|
1064
|
+
<AlertDialogTrigger asChild><Button variant="destructive">Delete</Button></AlertDialogTrigger>
|
|
1065
|
+
<AlertDialogContent>
|
|
1066
|
+
<AlertDialogHeader>
|
|
1067
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
1068
|
+
<AlertDialogDescription>This action cannot be undone.</AlertDialogDescription>
|
|
1069
|
+
</AlertDialogHeader>
|
|
1070
|
+
<AlertDialogFooter>
|
|
1071
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
1072
|
+
<AlertDialogAction>Continue</AlertDialogAction>
|
|
1073
|
+
</AlertDialogFooter>
|
|
1074
|
+
</AlertDialogContent>
|
|
1075
|
+
</AlertDialog>
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
---
|
|
1079
|
+
|
|
1080
|
+
### Sonner (Toast)
|
|
1081
|
+
|
|
1082
|
+
Non-blocking notification toasts. Requires `<Toaster />` in app root.
|
|
1083
|
+
|
|
1084
|
+
```tsx
|
|
1085
|
+
// App.tsx
|
|
1086
|
+
import { Toaster } from "@hilum/ui"
|
|
1087
|
+
<Toaster />
|
|
1088
|
+
|
|
1089
|
+
// Anywhere in the app
|
|
1090
|
+
import { toast } from "sonner"
|
|
1091
|
+
|
|
1092
|
+
toast("Event has been created")
|
|
1093
|
+
toast.success("Profile saved successfully")
|
|
1094
|
+
toast.error("Something went wrong")
|
|
1095
|
+
toast.loading("Uploading...")
|
|
1096
|
+
toast.promise(uploadFn(), {
|
|
1097
|
+
loading: "Uploading...",
|
|
1098
|
+
success: "Done!",
|
|
1099
|
+
error: "Upload failed",
|
|
1100
|
+
})
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
---
|
|
1104
|
+
|
|
1105
|
+
### Input OTP
|
|
1106
|
+
|
|
1107
|
+
One-time password / PIN code input.
|
|
1108
|
+
|
|
1109
|
+
```tsx
|
|
1110
|
+
import { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from "@hilum/ui"
|
|
1111
|
+
|
|
1112
|
+
<InputOTP maxLength={6} value={otp} onChange={setOtp}>
|
|
1113
|
+
<InputOTPGroup>
|
|
1114
|
+
<InputOTPSlot index={0} />
|
|
1115
|
+
<InputOTPSlot index={1} />
|
|
1116
|
+
<InputOTPSlot index={2} />
|
|
1117
|
+
</InputOTPGroup>
|
|
1118
|
+
<InputOTPSeparator />
|
|
1119
|
+
<InputOTPGroup>
|
|
1120
|
+
<InputOTPSlot index={3} />
|
|
1121
|
+
<InputOTPSlot index={4} />
|
|
1122
|
+
<InputOTPSlot index={5} />
|
|
1123
|
+
</InputOTPGroup>
|
|
1124
|
+
</InputOTP>
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
---
|
|
1128
|
+
|
|
1129
|
+
### Steps
|
|
1130
|
+
|
|
1131
|
+
Step indicator for multi-step flows.
|
|
1132
|
+
|
|
1133
|
+
```tsx
|
|
1134
|
+
import { Steps, Step } from "@hilum/ui"
|
|
1135
|
+
|
|
1136
|
+
<Steps current={1}>
|
|
1137
|
+
<Step label="Account" />
|
|
1138
|
+
<Step label="Profile" />
|
|
1139
|
+
<Step label="Review" />
|
|
1140
|
+
</Steps>
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
Props: `current` (0-indexed), `orientation` (`"horizontal"` | `"vertical"`).
|
|
1144
|
+
|
|
1145
|
+
---
|
|
1146
|
+
|
|
1147
|
+
### Toggle / Toggle Group
|
|
1148
|
+
|
|
1149
|
+
Single or grouped toggle buttons.
|
|
1150
|
+
|
|
1151
|
+
```tsx
|
|
1152
|
+
import { Toggle } from "@hilum/ui"
|
|
1153
|
+
import { Bold, Italic, Underline } from "lucide-react"
|
|
1154
|
+
|
|
1155
|
+
<Toggle pressed={bold} onPressedChange={setBold}><Bold size={14} /></Toggle>
|
|
1156
|
+
|
|
1157
|
+
// Group
|
|
1158
|
+
import { ToggleGroup, ToggleGroupItem } from "@hilum/ui"
|
|
1159
|
+
|
|
1160
|
+
<ToggleGroup type="multiple" value={formatting} onValueChange={setFormatting}>
|
|
1161
|
+
<ToggleGroupItem value="bold"><Bold size={14} /></ToggleGroupItem>
|
|
1162
|
+
<ToggleGroupItem value="italic"><Italic size={14} /></ToggleGroupItem>
|
|
1163
|
+
<ToggleGroupItem value="underline"><Underline size={14} /></ToggleGroupItem>
|
|
1164
|
+
</ToggleGroup>
|
|
1165
|
+
```
|
|
1166
|
+
|
|
1167
|
+
---
|
|
1168
|
+
|
|
1169
|
+
### Aspect Ratio
|
|
1170
|
+
|
|
1171
|
+
Maintains a fixed aspect ratio for any child.
|
|
1172
|
+
|
|
1173
|
+
```tsx
|
|
1174
|
+
import { AspectRatio } from "@hilum/ui"
|
|
1175
|
+
|
|
1176
|
+
<AspectRatio ratio={16 / 9} className="bg-taupe-100 rounded-xl overflow-hidden">
|
|
1177
|
+
<img src="..." className="w-full h-full object-cover" />
|
|
1178
|
+
</AspectRatio>
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
---
|
|
1182
|
+
|
|
1183
|
+
### Button Group
|
|
1184
|
+
|
|
1185
|
+
Groups buttons into a connected row with shared borders.
|
|
1186
|
+
|
|
1187
|
+
```tsx
|
|
1188
|
+
import { ButtonGroup } from "@hilum/ui"
|
|
1189
|
+
|
|
1190
|
+
<ButtonGroup>
|
|
1191
|
+
<Button variant="outline">Bold</Button>
|
|
1192
|
+
<Button variant="outline">Italic</Button>
|
|
1193
|
+
<Button variant="outline">Underline</Button>
|
|
1194
|
+
</ButtonGroup>
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
---
|
|
1198
|
+
|
|
1199
|
+
### Native Select
|
|
1200
|
+
|
|
1201
|
+
Native `<select>` styled to match the design system.
|
|
1202
|
+
|
|
1203
|
+
```tsx
|
|
1204
|
+
import { NativeSelect } from "@hilum/ui"
|
|
1205
|
+
|
|
1206
|
+
<NativeSelect value={country} onChange={e => setCountry(e.target.value)}>
|
|
1207
|
+
<option value="">Select country</option>
|
|
1208
|
+
<option value="us">United States</option>
|
|
1209
|
+
<option value="uk">United Kingdom</option>
|
|
1210
|
+
</NativeSelect>
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
---
|
|
1214
|
+
|
|
1215
|
+
## Molecules
|
|
1216
|
+
|
|
1217
|
+
Composed patterns built from atoms.
|
|
1218
|
+
|
|
1219
|
+
---
|
|
1220
|
+
|
|
1221
|
+
### Field
|
|
1222
|
+
|
|
1223
|
+
Labeled form field with hint and error support. (See Atoms → Field above.)
|
|
1224
|
+
|
|
1225
|
+
---
|
|
1226
|
+
|
|
1227
|
+
### Input Group
|
|
1228
|
+
|
|
1229
|
+
Input with leading/trailing addons (icons, buttons, text).
|
|
1230
|
+
|
|
1231
|
+
```tsx
|
|
1232
|
+
import { InputGroup, InputGroupAddon } from "@hilum/ui"
|
|
1233
|
+
|
|
1234
|
+
<InputGroup>
|
|
1235
|
+
<InputGroupAddon><Mail size={14} className="text-taupe-400" /></InputGroupAddon>
|
|
1236
|
+
<Input placeholder="Email address" />
|
|
1237
|
+
</InputGroup>
|
|
1238
|
+
|
|
1239
|
+
<InputGroup>
|
|
1240
|
+
<Input placeholder="0.00" />
|
|
1241
|
+
<InputGroupAddon>USD</InputGroupAddon>
|
|
1242
|
+
</InputGroup>
|
|
1243
|
+
```
|
|
1244
|
+
|
|
1245
|
+
---
|
|
1246
|
+
|
|
1247
|
+
### Stat Card
|
|
1248
|
+
|
|
1249
|
+
Metric display with label, value, trend, and optional icon.
|
|
1250
|
+
|
|
1251
|
+
```tsx
|
|
1252
|
+
import { StatCard } from "@hilum/ui"
|
|
1253
|
+
import { TrendingUp } from "lucide-react"
|
|
1254
|
+
|
|
1255
|
+
<StatCard
|
|
1256
|
+
label="Total revenue"
|
|
1257
|
+
value="$45,231"
|
|
1258
|
+
change="+20.1%"
|
|
1259
|
+
trend="up"
|
|
1260
|
+
icon={TrendingUp}
|
|
1261
|
+
/>
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
Props: `label`, `value`, `change`, `trend` (`"up"` | `"down"` | `"neutral"`), `icon`.
|
|
1265
|
+
|
|
1266
|
+
---
|
|
1267
|
+
|
|
1268
|
+
### Empty State
|
|
1269
|
+
|
|
1270
|
+
Zero-state UI for empty lists or no-results states.
|
|
1271
|
+
|
|
1272
|
+
```tsx
|
|
1273
|
+
import { EmptyState } from "@hilum/ui"
|
|
1274
|
+
import { FileX } from "lucide-react"
|
|
1275
|
+
|
|
1276
|
+
<EmptyState
|
|
1277
|
+
icon={FileX}
|
|
1278
|
+
title="No documents found"
|
|
1279
|
+
description="Try adjusting your filters or create a new document."
|
|
1280
|
+
action={<Button>New document</Button>}
|
|
1281
|
+
/>
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
---
|
|
1285
|
+
|
|
1286
|
+
### Section Heading
|
|
1287
|
+
|
|
1288
|
+
Labeled section divider with optional action.
|
|
1289
|
+
|
|
1290
|
+
```tsx
|
|
1291
|
+
import { SectionHeading } from "@hilum/ui"
|
|
1292
|
+
|
|
1293
|
+
<SectionHeading title="Recent activity" />
|
|
1294
|
+
<SectionHeading title="Team members" action={<Button size="sm">Invite</Button>} />
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
---
|
|
1298
|
+
|
|
1299
|
+
### Page Heading
|
|
1300
|
+
|
|
1301
|
+
Full-width page header with title, description, breadcrumb, and actions.
|
|
1302
|
+
|
|
1303
|
+
```tsx
|
|
1304
|
+
import { PageHeading } from "@hilum/ui"
|
|
1305
|
+
|
|
1306
|
+
<PageHeading
|
|
1307
|
+
title="Projects"
|
|
1308
|
+
description="Manage your team's active projects."
|
|
1309
|
+
action={<Button>New project</Button>}
|
|
1310
|
+
/>
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
---
|
|
1314
|
+
|
|
1315
|
+
### Card Heading
|
|
1316
|
+
|
|
1317
|
+
Section header inside a card — title, description, and optional right-side action.
|
|
1318
|
+
|
|
1319
|
+
```tsx
|
|
1320
|
+
import { CardHeading } from "@hilum/ui"
|
|
1321
|
+
|
|
1322
|
+
<CardHeading
|
|
1323
|
+
title="Team members"
|
|
1324
|
+
description="Invite and manage access."
|
|
1325
|
+
action={<Button size="sm" variant="outline">Invite</Button>}
|
|
1326
|
+
/>
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
---
|
|
1330
|
+
|
|
1331
|
+
### Activity Feed
|
|
1332
|
+
|
|
1333
|
+
Vertical timeline of events.
|
|
1334
|
+
|
|
1335
|
+
```tsx
|
|
1336
|
+
import { ActivityFeed, ActivityFeedItem } from "@hilum/ui"
|
|
1337
|
+
import { GitCommit } from "lucide-react"
|
|
1338
|
+
|
|
1339
|
+
<ActivityFeed>
|
|
1340
|
+
<ActivityFeedItem
|
|
1341
|
+
icon={GitCommit}
|
|
1342
|
+
title="Merged pull request #42"
|
|
1343
|
+
description="main ← feat/theming"
|
|
1344
|
+
timestamp="2 hours ago"
|
|
1345
|
+
/>
|
|
1346
|
+
</ActivityFeed>
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
---
|
|
1350
|
+
|
|
1351
|
+
### Stacked List
|
|
1352
|
+
|
|
1353
|
+
Vertical list of items with dividers.
|
|
1354
|
+
|
|
1355
|
+
```tsx
|
|
1356
|
+
import { StackedList, StackedListItem } from "@hilum/ui"
|
|
1357
|
+
|
|
1358
|
+
<StackedList>
|
|
1359
|
+
<StackedListItem
|
|
1360
|
+
primary="Alice Johnson"
|
|
1361
|
+
secondary="alice@example.com"
|
|
1362
|
+
meta="Admin"
|
|
1363
|
+
avatar={<Avatar size="sm"><AvatarFallback>AJ</AvatarFallback></Avatar>}
|
|
1364
|
+
/>
|
|
1365
|
+
</StackedList>
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
---
|
|
1369
|
+
|
|
1370
|
+
### Grid List
|
|
1371
|
+
|
|
1372
|
+
Responsive card grid.
|
|
1373
|
+
|
|
1374
|
+
```tsx
|
|
1375
|
+
import { GridList, GridListItem } from "@hilum/ui"
|
|
1376
|
+
|
|
1377
|
+
<GridList>
|
|
1378
|
+
{items.map(item => (
|
|
1379
|
+
<GridListItem key={item.id} title={item.name} description={item.desc} />
|
|
1380
|
+
))}
|
|
1381
|
+
</GridList>
|
|
1382
|
+
```
|
|
1383
|
+
|
|
1384
|
+
---
|
|
1385
|
+
|
|
1386
|
+
### Description List
|
|
1387
|
+
|
|
1388
|
+
Key–value pairs, typically for detail/profile views.
|
|
1389
|
+
|
|
1390
|
+
```tsx
|
|
1391
|
+
import { DescriptionList, DescriptionListItem } from "@hilum/ui"
|
|
1392
|
+
|
|
1393
|
+
<DescriptionList>
|
|
1394
|
+
<DescriptionListItem label="Full name" value="Alice Johnson" />
|
|
1395
|
+
<DescriptionListItem label="Email" value="alice@example.com" />
|
|
1396
|
+
<DescriptionListItem label="Role" value="Administrator" />
|
|
1397
|
+
</DescriptionList>
|
|
1398
|
+
```
|
|
1399
|
+
|
|
1400
|
+
---
|
|
1401
|
+
|
|
1402
|
+
### Notification
|
|
1403
|
+
|
|
1404
|
+
Single notification item with icon, title, message, and timestamp.
|
|
1405
|
+
|
|
1406
|
+
```tsx
|
|
1407
|
+
import { Notification } from "@hilum/ui"
|
|
1408
|
+
|
|
1409
|
+
<Notification
|
|
1410
|
+
title="New message"
|
|
1411
|
+
description="Alice sent you a message in #general"
|
|
1412
|
+
timestamp="5 minutes ago"
|
|
1413
|
+
unread
|
|
1414
|
+
/>
|
|
1415
|
+
```
|
|
1416
|
+
|
|
1417
|
+
---
|
|
1418
|
+
|
|
1419
|
+
### Media Object
|
|
1420
|
+
|
|
1421
|
+
Horizontal layout: media (image/icon/avatar) + content body.
|
|
1422
|
+
|
|
1423
|
+
```tsx
|
|
1424
|
+
import { MediaObject } from "@hilum/ui"
|
|
1425
|
+
|
|
1426
|
+
<MediaObject
|
|
1427
|
+
media={<Avatar><AvatarFallback>AB</AvatarFallback></Avatar>}
|
|
1428
|
+
title="Alice Brown"
|
|
1429
|
+
description="Sent you a project update for Q3 2025."
|
|
1430
|
+
meta="2h ago"
|
|
1431
|
+
/>
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
---
|
|
1435
|
+
|
|
1436
|
+
### Radio Card
|
|
1437
|
+
|
|
1438
|
+
Selectable card with radio button — used for plan/option selection.
|
|
1439
|
+
|
|
1440
|
+
```tsx
|
|
1441
|
+
import { RadioCard, RadioCardGroup } from "@hilum/ui"
|
|
1442
|
+
|
|
1443
|
+
<RadioCardGroup value={plan} onValueChange={setPlan}>
|
|
1444
|
+
<RadioCard value="starter" title="Starter" description="Up to 5 users" price="$9/mo" />
|
|
1445
|
+
<RadioCard value="pro" title="Pro" description="Up to 50 users" price="$49/mo" />
|
|
1446
|
+
</RadioCardGroup>
|
|
1447
|
+
```
|
|
1448
|
+
|
|
1449
|
+
---
|
|
1450
|
+
|
|
1451
|
+
### Action Panel
|
|
1452
|
+
|
|
1453
|
+
Bordered panel with a title, description, and a call-to-action.
|
|
1454
|
+
|
|
1455
|
+
```tsx
|
|
1456
|
+
import { ActionPanel } from "@hilum/ui"
|
|
1457
|
+
|
|
1458
|
+
<ActionPanel
|
|
1459
|
+
title="Danger zone"
|
|
1460
|
+
description="Deleting your account is permanent and cannot be undone."
|
|
1461
|
+
action={<Button variant="destructive">Delete account</Button>}
|
|
1462
|
+
/>
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1465
|
+
---
|
|
1466
|
+
|
|
1467
|
+
### Command Palette
|
|
1468
|
+
|
|
1469
|
+
Full-screen search overlay, usually opened by ⌘K.
|
|
1470
|
+
|
|
1471
|
+
```tsx
|
|
1472
|
+
import { CommandPalette } from "@hilum/ui"
|
|
1473
|
+
|
|
1474
|
+
// Open state controlled externally
|
|
1475
|
+
<CommandPalette
|
|
1476
|
+
open={open}
|
|
1477
|
+
onOpenChange={setOpen}
|
|
1478
|
+
items={[
|
|
1479
|
+
{ id: "dashboard", label: "Go to Dashboard", href: "/dashboard" },
|
|
1480
|
+
{ id: "settings", label: "Open Settings", href: "/settings" },
|
|
1481
|
+
]}
|
|
1482
|
+
/>
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
---
|
|
1486
|
+
|
|
1487
|
+
## Utilities
|
|
1488
|
+
|
|
1489
|
+
```tsx
|
|
1490
|
+
import { cn } from "@hilum/ui"
|
|
1491
|
+
|
|
1492
|
+
// Tailwind class merge utility (clsx + tailwind-merge)
|
|
1493
|
+
<div className={cn("p-4 rounded-xl", isActive && "bg-brand-primary text-white")} />
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
---
|
|
1497
|
+
|
|
1498
|
+
## Icons
|
|
1499
|
+
|
|
1500
|
+
Curated subset from lucide-react, re-exported for convenience:
|
|
1501
|
+
|
|
1502
|
+
```tsx
|
|
1503
|
+
import { PlusIcon, SearchIcon, SettingsIcon } from "@hilum/ui/icons"
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
---
|
|
1507
|
+
|
|
1508
|
+
## Design decisions
|
|
1509
|
+
|
|
1510
|
+
- **Framework-agnostic React** — works in client-rendered apps, TanStack Start prerendered docs, and Electron
|
|
1511
|
+
- **Tailwind v4** — CSS-variable-backed utilities, runtime-overridable via `createTheme`
|
|
1512
|
+
- **Radix UI primitives** — all interactive components are WAI-ARIA compliant
|
|
1513
|
+
- **Lockstep versioning** — all packages release together
|
|
1514
|
+
- **OKLCH color space** — all generated palettes use perceptually uniform interpolation
|