@l3mpire/ui 2.5.1
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 +211 -0
- package/USAGE.md +1025 -0
- package/dist/index.d.mts +584 -0
- package/dist/index.d.ts +584 -0
- package/dist/index.js +4339 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4256 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +80 -0
- package/src/styles/globals.css +524 -0
package/USAGE.md
ADDED
|
@@ -0,0 +1,1025 @@
|
|
|
1
|
+
# lemDS — Usage Guide
|
|
2
|
+
|
|
3
|
+
Reference for developers and AI agents consuming the `@l3mpire/ui` and `@l3mpire/icons` packages.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
// 1. Import global styles (once, at app entry)
|
|
11
|
+
import "@l3mpire/ui/globals.css";
|
|
12
|
+
|
|
13
|
+
// 2. Import components
|
|
14
|
+
import { Button, Badge, TextInput } from "@l3mpire/ui";
|
|
15
|
+
|
|
16
|
+
// 3. Import icons (always both variants)
|
|
17
|
+
import { faHomeSolid, faHomeOutline } from "@l3mpire/icons";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Icons
|
|
23
|
+
|
|
24
|
+
### Naming convention
|
|
25
|
+
|
|
26
|
+
Every icon has **two variants**, always suffixed:
|
|
27
|
+
|
|
28
|
+
| Variant | Suffix | Source package |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| Outline (regular) | `faXxxOutline` | `@fortawesome/pro-regular-svg-icons` v7 |
|
|
31
|
+
| Solid (filled) | `faXxxSolid` | `@fortawesome/pro-solid-svg-icons` v7 |
|
|
32
|
+
|
|
33
|
+
**No unsuffixed icon names.** Always import both when you need switching.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { Icon, faHomeOutline, faHomeSolid } from "@l3mpire/icons";
|
|
37
|
+
|
|
38
|
+
// Simple usage — pick one variant
|
|
39
|
+
<Icon icon={faHomeSolid} size="md" />
|
|
40
|
+
|
|
41
|
+
// Switchable usage — pass both, toggle with `solid`
|
|
42
|
+
<Icon icon={faHomeOutline} solidIcon={faHomeSolid} solid={isActive} size="sm" />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Icon sizes
|
|
46
|
+
|
|
47
|
+
| `size` prop | Rendered size |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `"xs"` | 12px |
|
|
50
|
+
| `"sm"` | 14px |
|
|
51
|
+
| `"md"` | 16px |
|
|
52
|
+
| `"lg"` | 20px |
|
|
53
|
+
| `"xl"` | 24px |
|
|
54
|
+
|
|
55
|
+
### Available icons
|
|
56
|
+
|
|
57
|
+
All icons come in `Outline` + `Solid` pairs:
|
|
58
|
+
|
|
59
|
+
`faCheck`, `faXmark`, `faPlus`, `faMinus`, `faPen`, `faTrash`, `faTrashCan`, `faMagnifyingGlass`, `faChevronDown`, `faChevronUp`, `faChevronLeft`, `faChevronRight`, `faArrowLeft`, `faArrowRight`, `faArrowUp`, `faArrowDown`, `faEllipsis`, `faEllipsisVertical`, `faSpinner`, `faCircleNotch`, `faTriangleExclamation`, `faCircleExclamation`, `faCircleCheck`, `faCircleInfo`, `faCircleXmark`, `faBell`, `faGear`, `faUser`, `faUsers`, `faEnvelope`, `faPaperPlane`, `faLink`, `faCopy`, `faDownload`, `faUpload`, `faFilter`, `faSort`, `faStar`, `faHeart`, `faEye`, `faEyeSlash`, `faLock`, `faUnlock`, `faCalendar`, `faClock`, `faHome`, `faFolder`, `faFile`, `faBookmark`, `faComment`, `faMessage`, `faSquarePlus`, `faSquareCheck`, `faPenToSquare`, `faPaperPlaneTop`, `faAddressBook`, `faBuildings`, `faChartLineUp`, `faInbox`, `faPhone`, `faVideo`, `faCoin`, `faStars`, `faArrowLeftFromLine`, `faGripDotsVertical`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Spacing
|
|
64
|
+
|
|
65
|
+
Use design token spacing classes — never arbitrary pixel values.
|
|
66
|
+
|
|
67
|
+
| Class | Value |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `p-2xs` / `gap-2xs` | 2px |
|
|
70
|
+
| `p-xs` / `gap-xs` | 4px |
|
|
71
|
+
| `p-sm` / `gap-sm` | 6px |
|
|
72
|
+
| `p-base` / `gap-base` | 8px |
|
|
73
|
+
| `p-md` / `gap-md` | 12px |
|
|
74
|
+
| `p-lg` / `gap-lg` | 16px |
|
|
75
|
+
| `p-xl` / `gap-xl` | 20px |
|
|
76
|
+
| `p-2xl` / `gap-2xl` | 24px |
|
|
77
|
+
| `p-3xl` / `gap-3xl` | 32px |
|
|
78
|
+
| `p-4xl` / `gap-4xl` | 40px |
|
|
79
|
+
| `p-5xl` / `gap-5xl` | 48px |
|
|
80
|
+
|
|
81
|
+
Works with all Tailwind spacing prefixes: `p-`, `px-`, `py-`, `m-`, `mx-`, `my-`, `gap-`, `space-x-`, `space-y-`, `w-`, `h-`, `top-`, `left-`, etc.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Border Radius
|
|
86
|
+
|
|
87
|
+
| Class | Value |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `rounded-none` | 0 |
|
|
90
|
+
| `rounded-2xs` | 2px |
|
|
91
|
+
| `rounded-xs` | 4px |
|
|
92
|
+
| `rounded-sm` | 6px |
|
|
93
|
+
| `rounded-base` | 8px |
|
|
94
|
+
| `rounded-md` | 12px |
|
|
95
|
+
| `rounded-lg` | 16px |
|
|
96
|
+
| `rounded-xl` | 20px |
|
|
97
|
+
| `rounded-full` | 9999px |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Typography
|
|
102
|
+
|
|
103
|
+
### Tailwind classes
|
|
104
|
+
|
|
105
|
+
| Class | Size |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `text-xxs` | 10px |
|
|
108
|
+
| `text-xs` | 12px |
|
|
109
|
+
| `text-sm` | 14px |
|
|
110
|
+
| `text-base` | 16px |
|
|
111
|
+
| `text-md` | 18px |
|
|
112
|
+
| `text-lg` | 20px |
|
|
113
|
+
| `text-xl` | 24px |
|
|
114
|
+
|
|
115
|
+
**Line heights:** `leading-2xs` (14px), `leading-xs` (16px), `leading-sm` (20px), `leading-base` (24px), `leading-md` (28px), `leading-lg` (32px)
|
|
116
|
+
|
|
117
|
+
**Font weights:** `font-regular` (400), `font-medium` (500), `font-bold` (700)
|
|
118
|
+
|
|
119
|
+
### Typography component
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { Typography } from "@l3mpire/ui";
|
|
123
|
+
|
|
124
|
+
<Typography variant="h1">Heading 1</Typography>
|
|
125
|
+
<Typography variant="md" weight="medium">Body text</Typography>
|
|
126
|
+
<Typography variant="sm" weight="regular">Small text</Typography>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Variants:** `h1`, `h2`, `h3`, `lg`, `md`, `sm`, `xs`
|
|
130
|
+
**Weights:** `regular`, `medium`, `bold`
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Shadows
|
|
135
|
+
|
|
136
|
+
| Class | Usage |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `shadow-sm` | Subtle elevation |
|
|
139
|
+
| `shadow-md` | Cards, dropdowns |
|
|
140
|
+
| `shadow-lg` | Modals, popovers |
|
|
141
|
+
| `shadow-focus-ring` | Focus state ring (3px blue) |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Dark Mode
|
|
146
|
+
|
|
147
|
+
Activate with `data-theme="dark"` on any ancestor:
|
|
148
|
+
|
|
149
|
+
```html
|
|
150
|
+
<div data-theme="dark">
|
|
151
|
+
<!-- All descendants render in dark mode -->
|
|
152
|
+
</div>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
All component tokens automatically switch between light and dark values.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Components
|
|
160
|
+
|
|
161
|
+
### Button
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { Button } from "@l3mpire/ui";
|
|
165
|
+
import { faPaperPlaneOutline } from "@l3mpire/icons";
|
|
166
|
+
|
|
167
|
+
<Button appearance="solid" intent="brand" size="md">
|
|
168
|
+
Send
|
|
169
|
+
</Button>
|
|
170
|
+
|
|
171
|
+
<Button appearance="outlined" intent="neutral" size="sm" leftIcon={faPaperPlaneOutline}>
|
|
172
|
+
Send
|
|
173
|
+
</Button>
|
|
174
|
+
|
|
175
|
+
<Button appearance="ghost" intent="alert" size="lg" loading>
|
|
176
|
+
Deleting...
|
|
177
|
+
</Button>
|
|
178
|
+
|
|
179
|
+
<Button appearance="solid" intent="brand" size="md" iconOnly leftIcon={faPaperPlaneOutline} />
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Prop | Values |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `appearance` | `"solid"`, `"outlined"`, `"ghost"` |
|
|
185
|
+
| `intent` | `"brand"`, `"neutral"`, `"alert"` |
|
|
186
|
+
| `size` | `"sm"`, `"md"`, `"lg"` |
|
|
187
|
+
| `leftIcon` | `IconDefinition` |
|
|
188
|
+
| `rightIcon` | `IconDefinition` |
|
|
189
|
+
| `iconOnly` | `boolean` |
|
|
190
|
+
| `loading` | `boolean` |
|
|
191
|
+
| `disabled` | `boolean` |
|
|
192
|
+
| `asChild` | `boolean` (render as child element) |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Badge
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
import { Badge } from "@l3mpire/ui";
|
|
200
|
+
import { faStarOutline } from "@l3mpire/icons";
|
|
201
|
+
|
|
202
|
+
<Badge variant="solid" type="primary">New</Badge>
|
|
203
|
+
<Badge variant="light" type="success" size="sm">Active</Badge>
|
|
204
|
+
<Badge variant="outlined" type="critical" icon={faStarOutline}>99</Badge>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
| Prop | Values |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `variant` | `"solid"`, `"light"`, `"outlined"` |
|
|
210
|
+
| `type` | `"primary"`, `"success"`, `"critical"`, `"warning"`, `"neutral"` |
|
|
211
|
+
| `size` | `"sm"`, `"md"`, `"lg"` |
|
|
212
|
+
| `icon` | `IconDefinition` (optional) |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### Tag
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { Tag } from "@l3mpire/ui";
|
|
220
|
+
import { faPaperPlaneOutline } from "@l3mpire/icons";
|
|
221
|
+
|
|
222
|
+
<Tag variant="brand">Label</Tag>
|
|
223
|
+
<Tag variant="neutral" icon={faPaperPlaneOutline} onClose={() => {}}>
|
|
224
|
+
Campaign
|
|
225
|
+
</Tag>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Prop | Values |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `variant` | `"brand"`, `"neutral"` |
|
|
231
|
+
| `size` | `"sm"`, `"md"` |
|
|
232
|
+
| `icon` | `IconDefinition` |
|
|
233
|
+
| `onClose` | `() => void` (shows remove button when provided) |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### Link
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { Link } from "@l3mpire/ui";
|
|
241
|
+
import { faArrowRightSolid } from "@l3mpire/icons";
|
|
242
|
+
|
|
243
|
+
<Link intent="brand" rightIcon={faArrowRightSolid}>Learn more</Link>
|
|
244
|
+
<Link intent="neutral" size="sm">Settings</Link>
|
|
245
|
+
<Link intent="alert">Delete account</Link>
|
|
246
|
+
<Link intent="success">Confirmed</Link>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Prop | Values |
|
|
250
|
+
|---|---|
|
|
251
|
+
| `intent` | `"neutral"`, `"brand"`, `"alert"`, `"success"`, `"warning"` |
|
|
252
|
+
| `size` | `"sm"`, `"md"` |
|
|
253
|
+
| `leftIcon` | `IconDefinition` |
|
|
254
|
+
| `rightIcon` | `IconDefinition` |
|
|
255
|
+
| `disabled` | `boolean` |
|
|
256
|
+
| `asChild` | `boolean` |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### TextInput
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import { TextInput } from "@l3mpire/ui";
|
|
264
|
+
import { faMagnifyingGlassSolid, faEnvelopeSolid } from "@l3mpire/icons";
|
|
265
|
+
|
|
266
|
+
<TextInput label="Email" placeholder="you@example.com" iconLeft={faEnvelopeSolid} />
|
|
267
|
+
<TextInput label="Search" iconLeft={faMagnifyingGlassSolid} onClear={() => {}} />
|
|
268
|
+
<TextInput label="Name" error errorMessage="This field is required" />
|
|
269
|
+
<TextInput label="Add item" hasButton onButtonClick={() => {}} />
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
| Prop | Values |
|
|
273
|
+
|---|---|
|
|
274
|
+
| `size` | `"sm"`, `"md"` |
|
|
275
|
+
| `label` | `string` |
|
|
276
|
+
| `error` | `boolean` |
|
|
277
|
+
| `errorMessage` | `string` (shown below input when `error` is true) |
|
|
278
|
+
| `success` | `boolean` |
|
|
279
|
+
| `iconLeft` | `IconDefinition` |
|
|
280
|
+
| `iconRight` | `IconDefinition` |
|
|
281
|
+
| `onClear` | `() => void` (shows clear button when provided) |
|
|
282
|
+
| `hasButton` | `boolean` |
|
|
283
|
+
| `buttonIcon` | `IconDefinition` |
|
|
284
|
+
| `onButtonClick` | `() => void` |
|
|
285
|
+
| `disabled` | `boolean` |
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### TextArea
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { TextArea } from "@l3mpire/ui";
|
|
293
|
+
|
|
294
|
+
<TextArea label="Message" placeholder="Type here..." />
|
|
295
|
+
<TextArea label="Bio" error errorMessage="Too long" characterLimit="200" />
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
| Prop | Values |
|
|
299
|
+
|---|---|
|
|
300
|
+
| `label` | `string` |
|
|
301
|
+
| `error` | `boolean` |
|
|
302
|
+
| `errorMessage` | `string` |
|
|
303
|
+
| `success` | `boolean` |
|
|
304
|
+
| `characterLimit` | `string` (shows counter) |
|
|
305
|
+
| `disabled` | `boolean` |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### Checkbox
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { Checkbox } from "@l3mpire/ui";
|
|
313
|
+
|
|
314
|
+
<Checkbox label="Accept terms" />
|
|
315
|
+
<Checkbox label="Disabled" disabled />
|
|
316
|
+
<Checkbox label="Pre-checked" defaultChecked />
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
| Prop | Values |
|
|
320
|
+
|---|---|
|
|
321
|
+
| `label` | `string` |
|
|
322
|
+
| `checked` | `boolean` (controlled) |
|
|
323
|
+
| `defaultChecked` | `boolean` (uncontrolled) |
|
|
324
|
+
| `onCheckedChange` | `(checked: boolean) => void` |
|
|
325
|
+
| `disabled` | `boolean` |
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### Switch
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
import { Switch } from "@l3mpire/ui";
|
|
333
|
+
|
|
334
|
+
<Switch label="Notifications" />
|
|
335
|
+
<Switch label="Disabled" disabled />
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
| Prop | Values |
|
|
339
|
+
|---|---|
|
|
340
|
+
| `label` | `string` |
|
|
341
|
+
| `checked` | `boolean` (controlled) |
|
|
342
|
+
| `defaultChecked` | `boolean` (uncontrolled) |
|
|
343
|
+
| `onCheckedChange` | `(checked: boolean) => void` |
|
|
344
|
+
| `disabled` | `boolean` |
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
### Select
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
import { Select } from "@l3mpire/ui";
|
|
352
|
+
|
|
353
|
+
<Select
|
|
354
|
+
label="Country"
|
|
355
|
+
placeholder="Choose..."
|
|
356
|
+
size="md"
|
|
357
|
+
>
|
|
358
|
+
{/* DropdownMenu content inside */}
|
|
359
|
+
</Select>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
| Prop | Values |
|
|
363
|
+
|---|---|
|
|
364
|
+
| `size` | `"sm"`, `"md"` |
|
|
365
|
+
| `label` | `string` |
|
|
366
|
+
| `placeholder` | `string` |
|
|
367
|
+
| `value` | `string` |
|
|
368
|
+
| `error` | `boolean` |
|
|
369
|
+
| `errorMessage` | `string` |
|
|
370
|
+
| `icon` | `IconDefinition` |
|
|
371
|
+
| `isOpen` | `boolean` (controlled) |
|
|
372
|
+
| `onOpenChange` | `(open: boolean) => void` |
|
|
373
|
+
| `disabled` | `boolean` |
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
### DropdownMenu
|
|
378
|
+
|
|
379
|
+
Static/presentational dropdown list:
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
import {
|
|
383
|
+
DropdownMenu,
|
|
384
|
+
DropdownMenuList,
|
|
385
|
+
DropdownMenuItem,
|
|
386
|
+
DropdownMenuHeading,
|
|
387
|
+
DropdownMenuClear,
|
|
388
|
+
} from "@l3mpire/ui";
|
|
389
|
+
|
|
390
|
+
<DropdownMenu>
|
|
391
|
+
<DropdownMenuList>
|
|
392
|
+
<DropdownMenuHeading>Section</DropdownMenuHeading>
|
|
393
|
+
<DropdownMenuItem icon={faGearSolid} label="Settings" />
|
|
394
|
+
<DropdownMenuItem label="Profile" selected />
|
|
395
|
+
<DropdownMenuClear label="Clear all" />
|
|
396
|
+
</DropdownMenuList>
|
|
397
|
+
</DropdownMenu>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Interactive Radix-powered dropdown:
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
import {
|
|
404
|
+
DropdownMenuRoot,
|
|
405
|
+
DropdownMenuTrigger,
|
|
406
|
+
DropdownMenuContent,
|
|
407
|
+
DropdownMenuRadixItem,
|
|
408
|
+
} from "@l3mpire/ui";
|
|
409
|
+
|
|
410
|
+
<DropdownMenuRoot>
|
|
411
|
+
<DropdownMenuTrigger asChild>
|
|
412
|
+
<Button>Open</Button>
|
|
413
|
+
</DropdownMenuTrigger>
|
|
414
|
+
<DropdownMenuContent>
|
|
415
|
+
<DropdownMenuRadixItem label="Option 1" />
|
|
416
|
+
<DropdownMenuRadixItem label="Option 2" />
|
|
417
|
+
</DropdownMenuContent>
|
|
418
|
+
</DropdownMenuRoot>
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
### Tooltip
|
|
424
|
+
|
|
425
|
+
```tsx
|
|
426
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "@l3mpire/ui";
|
|
427
|
+
|
|
428
|
+
<TooltipProvider>
|
|
429
|
+
<Tooltip>
|
|
430
|
+
<TooltipTrigger asChild>
|
|
431
|
+
<Button>Hover me</Button>
|
|
432
|
+
</TooltipTrigger>
|
|
433
|
+
<TooltipContent type="default" side="top">
|
|
434
|
+
Tooltip text
|
|
435
|
+
</TooltipContent>
|
|
436
|
+
</Tooltip>
|
|
437
|
+
</TooltipProvider>
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
| Prop (TooltipContent) | Values |
|
|
441
|
+
|---|---|
|
|
442
|
+
| `type` | `"default"`, `"invert"` |
|
|
443
|
+
| `side` | `"top"`, `"right"`, `"bottom"`, `"left"` |
|
|
444
|
+
| `hasArrow` | `boolean` (default: true) |
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### Toast
|
|
449
|
+
|
|
450
|
+
```tsx
|
|
451
|
+
import { Toast } from "@l3mpire/ui";
|
|
452
|
+
|
|
453
|
+
<Toast type="success" title="Saved!" subtitle="Your changes have been saved." />
|
|
454
|
+
<Toast type="alert" title="Error" subtitle="Something went wrong." onClose={() => {}} />
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
| Prop | Values |
|
|
458
|
+
|---|---|
|
|
459
|
+
| `type` | `"info"`, `"success"`, `"alert"`, `"warning"` |
|
|
460
|
+
| `title` | `React.ReactNode` (required) |
|
|
461
|
+
| `subtitle` | `React.ReactNode` |
|
|
462
|
+
| `onClose` | `() => void` (shows close button when provided) |
|
|
463
|
+
| `actions` | `React.ReactNode` (action buttons) |
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### InfoMessage
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
import { InfoMessage } from "@l3mpire/ui";
|
|
471
|
+
|
|
472
|
+
<InfoMessage type="info" title="Heads up" description="This is informational." />
|
|
473
|
+
<InfoMessage type="warning" title="Warning" description="Check your settings." onClose={() => {}} />
|
|
474
|
+
<InfoMessage
|
|
475
|
+
type="success"
|
|
476
|
+
title="Done!"
|
|
477
|
+
description="Your account was created."
|
|
478
|
+
linkLabel="View dashboard"
|
|
479
|
+
linkHref="/dashboard"
|
|
480
|
+
/>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
| Prop | Values |
|
|
484
|
+
|---|---|
|
|
485
|
+
| `type` | `"info"`, `"success"`, `"alert"`, `"warning"`, `"empty"` |
|
|
486
|
+
| `title` | `React.ReactNode` (required) |
|
|
487
|
+
| `description` | `React.ReactNode` |
|
|
488
|
+
| `onClose` | `() => void` (shows close button when provided) |
|
|
489
|
+
| `action` | `React.ReactNode` (e.g., a Button) |
|
|
490
|
+
| `linkLabel` | `string` (shows a semantically-colored link) |
|
|
491
|
+
| `linkHref` | `string` |
|
|
492
|
+
| `onLinkClick` | `() => void` |
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### Avatar
|
|
497
|
+
|
|
498
|
+
```tsx
|
|
499
|
+
import { Avatar } from "@l3mpire/ui";
|
|
500
|
+
|
|
501
|
+
<Avatar size="md" src="https://example.com/photo.jpg" initials="AD" />
|
|
502
|
+
<Avatar size="sm" initials="PY" />
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
| Prop | Values |
|
|
506
|
+
|---|---|
|
|
507
|
+
| `size` | `"sm"`, `"md"`, `"lg"`, `"xl"` |
|
|
508
|
+
| `shape` | `"rounded"`, `"squared"` |
|
|
509
|
+
| `src` | `string` (image URL) |
|
|
510
|
+
| `alt` | `string` |
|
|
511
|
+
| `initials` | `string` (fallback when no image, default: "??") |
|
|
512
|
+
| `badge` | `React.ReactNode` (only visible at `xl` size) |
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
### SearchBar
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
import { SearchBar } from "@l3mpire/ui";
|
|
520
|
+
|
|
521
|
+
<SearchBar placeholder="Search for anything" hasShortcut />
|
|
522
|
+
<SearchBar variant="grey" size="sm" onClear={() => {}} />
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
| Prop | Values |
|
|
526
|
+
|---|---|
|
|
527
|
+
| `variant` | `"white"`, `"grey"` |
|
|
528
|
+
| `size` | `"sm"`, `"md"` |
|
|
529
|
+
| `hasShortcut` | `boolean` (shows ⌘K badge) |
|
|
530
|
+
| `placeholder` | `string` |
|
|
531
|
+
| `onClear` | `() => void` (shows clear button when provided) |
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
### InputLabel
|
|
536
|
+
|
|
537
|
+
```tsx
|
|
538
|
+
import { InputLabel } from "@l3mpire/ui";
|
|
539
|
+
|
|
540
|
+
<InputLabel label="Email" />
|
|
541
|
+
<InputLabel label="Bio" type="optional" />
|
|
542
|
+
<InputLabel label="Name" type="info" infoTooltip="Your full name" />
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
| Prop | Values |
|
|
546
|
+
|---|---|
|
|
547
|
+
| `type` | `"default"`, `"optional"`, `"mandatory"`, `"info"` |
|
|
548
|
+
| `disabled` | `boolean` |
|
|
549
|
+
| `infoIcon` | `IconDefinition` |
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
### Sidebar
|
|
554
|
+
|
|
555
|
+
```tsx
|
|
556
|
+
import {
|
|
557
|
+
Sidebar,
|
|
558
|
+
SidebarSection,
|
|
559
|
+
SidebarFooter,
|
|
560
|
+
SidebarHeadingItem,
|
|
561
|
+
SidebarItem,
|
|
562
|
+
} from "@l3mpire/ui";
|
|
563
|
+
import { faHomeOutline, faHomeSolid } from "@l3mpire/icons";
|
|
564
|
+
|
|
565
|
+
<Sidebar isCollapsed={false}>
|
|
566
|
+
<SidebarItem icon={faHomeOutline} solidIcon={faHomeSolid} label="Home" />
|
|
567
|
+
|
|
568
|
+
<SidebarSection>
|
|
569
|
+
<SidebarHeadingItem label="Section Title" />
|
|
570
|
+
<SidebarItem icon={faGearOutline} solidIcon={faGearSolid} label="Settings" />
|
|
571
|
+
</SidebarSection>
|
|
572
|
+
|
|
573
|
+
<SidebarFooter>
|
|
574
|
+
<SidebarItem icon={faUserOutline} solidIcon={faUserSolid} label="Profile" />
|
|
575
|
+
</SidebarFooter>
|
|
576
|
+
</Sidebar>
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
`SidebarItem` auto-detects collapsed state from `Sidebar` context. Icons switch from outline to solid on hover and when `state="active"`.
|
|
580
|
+
|
|
581
|
+
| Prop (SidebarItem) | Values |
|
|
582
|
+
|---|---|
|
|
583
|
+
| `icon` | `IconDefinition` (outline variant) |
|
|
584
|
+
| `solidIcon` | `IconDefinition` (solid variant) |
|
|
585
|
+
| `label` | `string` |
|
|
586
|
+
| `state` | `"default"`, `"hover"`, `"active"` |
|
|
587
|
+
| `hasBadge` | `boolean` |
|
|
588
|
+
| `badgeCount` | `string` |
|
|
589
|
+
| `hasSubItems` | `boolean` |
|
|
590
|
+
| `isNew` | `boolean` |
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
### Tabs
|
|
595
|
+
|
|
596
|
+
```tsx
|
|
597
|
+
import { Tabs, TabList, TabTrigger, TabContent } from "@l3mpire/ui";
|
|
598
|
+
|
|
599
|
+
<Tabs defaultValue="tab1">
|
|
600
|
+
<TabList>
|
|
601
|
+
<TabTrigger value="tab1">Tab 1</TabTrigger>
|
|
602
|
+
<TabTrigger value="tab2" badge="3">Tab 2</TabTrigger>
|
|
603
|
+
</TabList>
|
|
604
|
+
<TabContent value="tab1">Content 1</TabContent>
|
|
605
|
+
<TabContent value="tab2">Content 2</TabContent>
|
|
606
|
+
</Tabs>
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
| Prop (TabTrigger) | Values |
|
|
610
|
+
|---|---|
|
|
611
|
+
| `value` | `string` (required) |
|
|
612
|
+
| `badge` | `string` (count badge) |
|
|
613
|
+
| `disabled` | `boolean` |
|
|
614
|
+
|
|
615
|
+
| Prop (TabList) | Values |
|
|
616
|
+
|---|---|
|
|
617
|
+
| `hasOffset` | `boolean` (adds left padding) |
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
### BrowserTab
|
|
622
|
+
|
|
623
|
+
```tsx
|
|
624
|
+
import { BrowserTab, BrowserTabItem } from "@l3mpire/ui";
|
|
625
|
+
|
|
626
|
+
<BrowserTab activeTabId="1" onTabSelect={(id) => {}}>
|
|
627
|
+
<BrowserTabItem id="1" label="Page 1" onClose={(id) => {}} />
|
|
628
|
+
<BrowserTabItem id="2" label="Page 2" onClose={(id) => {}} />
|
|
629
|
+
</BrowserTab>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
| Prop (BrowserTab) | Values |
|
|
633
|
+
|---|---|
|
|
634
|
+
| `activeTabId` | `string` |
|
|
635
|
+
| `onTabSelect` | `(id: string) => void` |
|
|
636
|
+
| `onNewTab` | `() => void` (shows + button) |
|
|
637
|
+
| `onReorder` | `(ids: string[]) => void` |
|
|
638
|
+
|
|
639
|
+
| Prop (BrowserTabItem) | Values |
|
|
640
|
+
|---|---|
|
|
641
|
+
| `id` | `string` (required) |
|
|
642
|
+
| `label` | `string` |
|
|
643
|
+
| `icon` | `IconDefinition` |
|
|
644
|
+
| `onClose` | `(id: string) => void` |
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
### Modal
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
import {
|
|
652
|
+
Modal, ModalTrigger, ModalContent,
|
|
653
|
+
ModalHeader, ModalTitle, ModalDescription,
|
|
654
|
+
ModalBody, ModalFooter, ModalClose,
|
|
655
|
+
Button,
|
|
656
|
+
} from "@l3mpire/ui";
|
|
657
|
+
|
|
658
|
+
<Modal>
|
|
659
|
+
<ModalTrigger asChild>
|
|
660
|
+
<Button appearance="solid" intent="brand" size="md">Open</Button>
|
|
661
|
+
</ModalTrigger>
|
|
662
|
+
<ModalContent size="md">
|
|
663
|
+
<ModalHeader onClose={() => {}}>
|
|
664
|
+
<ModalTitle>Title</ModalTitle>
|
|
665
|
+
<ModalDescription>Optional description</ModalDescription>
|
|
666
|
+
</ModalHeader>
|
|
667
|
+
<ModalBody>Content goes here</ModalBody>
|
|
668
|
+
<ModalFooter>
|
|
669
|
+
<ModalClose asChild>
|
|
670
|
+
<Button appearance="ghost" intent="brand" size="md">Cancel</Button>
|
|
671
|
+
</ModalClose>
|
|
672
|
+
<Button appearance="solid" intent="brand" size="md">Confirm</Button>
|
|
673
|
+
</ModalFooter>
|
|
674
|
+
</ModalContent>
|
|
675
|
+
</Modal>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
| Prop (ModalContent) | Values |
|
|
679
|
+
|---|---|
|
|
680
|
+
| `size` | `"sm"` (500px), `"md"` (800px), `"lg"` (1100px), `"full"` (100% − 32px) |
|
|
681
|
+
|
|
682
|
+
| Prop (ModalHeader) | Values |
|
|
683
|
+
|---|---|
|
|
684
|
+
| `showBorder` | `boolean` (default: true) |
|
|
685
|
+
| `onClose` | `() => void` (shows close button when provided) |
|
|
686
|
+
|
|
687
|
+
| Prop (ModalFooter) | Values |
|
|
688
|
+
|---|---|
|
|
689
|
+
| `showBorder` | `boolean` (default: true) |
|
|
690
|
+
| `infoMessage` | `string` (shows info icon + text on the left) |
|
|
691
|
+
|
|
692
|
+
**Sub-components:** `Modal`, `ModalTrigger`, `ModalContent`, `ModalHeader`, `ModalTitle`, `ModalDescription`, `ModalBody`, `ModalFooter`, `ModalClose`
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
### Dialog
|
|
697
|
+
|
|
698
|
+
Pre-composed confirmation dialog (Modal SM without header border). Supports `brand` and `alert` intents.
|
|
699
|
+
|
|
700
|
+
```tsx
|
|
701
|
+
import { Dialog, Button } from "@l3mpire/ui";
|
|
702
|
+
|
|
703
|
+
const [open, setOpen] = React.useState(false);
|
|
704
|
+
|
|
705
|
+
<Button onClick={() => setOpen(true)}>Delete</Button>
|
|
706
|
+
|
|
707
|
+
<Dialog
|
|
708
|
+
open={open}
|
|
709
|
+
onOpenChange={setOpen}
|
|
710
|
+
title="Delete Item"
|
|
711
|
+
description="This action cannot be undone."
|
|
712
|
+
intent="alert"
|
|
713
|
+
primaryLabel="Delete"
|
|
714
|
+
cancelLabel="Cancel"
|
|
715
|
+
onPrimaryAction={() => { deleteItem(); setOpen(false); }}
|
|
716
|
+
/>
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
| Prop | Values |
|
|
720
|
+
|---|---|
|
|
721
|
+
| `open` | `boolean` (controlled) |
|
|
722
|
+
| `onOpenChange` | `(open: boolean) => void` |
|
|
723
|
+
| `title` | `string` (required) |
|
|
724
|
+
| `description` | `string` |
|
|
725
|
+
| `intent` | `"brand"`, `"alert"` |
|
|
726
|
+
| `primaryLabel` | `string` (default: "Confirm") |
|
|
727
|
+
| `onPrimaryAction` | `() => void` |
|
|
728
|
+
| `primaryDisabled` | `boolean` |
|
|
729
|
+
| `cancelLabel` | `string` (default: "Cancel") |
|
|
730
|
+
| `onCancel` | `() => void` |
|
|
731
|
+
| `secondaryLabel` | `string` (shows third button) |
|
|
732
|
+
| `onSecondaryAction` | `() => void` |
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
### SidePanel
|
|
737
|
+
|
|
738
|
+
Full-height panel that slides in from the right. Reuses `ModalHeader`, `ModalBody`, `ModalFooter` for composition.
|
|
739
|
+
|
|
740
|
+
```tsx
|
|
741
|
+
import {
|
|
742
|
+
SidePanel, SidePanelTrigger, SidePanelContent,
|
|
743
|
+
ModalHeader, ModalTitle, ModalDescription,
|
|
744
|
+
ModalBody, ModalFooter, ModalClose,
|
|
745
|
+
Button,
|
|
746
|
+
} from "@l3mpire/ui";
|
|
747
|
+
|
|
748
|
+
<SidePanel>
|
|
749
|
+
<SidePanelTrigger asChild>
|
|
750
|
+
<Button appearance="solid" intent="brand" size="md">Open</Button>
|
|
751
|
+
</SidePanelTrigger>
|
|
752
|
+
<SidePanelContent>
|
|
753
|
+
<ModalHeader onClose={() => {}}>
|
|
754
|
+
<ModalTitle>Title</ModalTitle>
|
|
755
|
+
<ModalDescription>Description</ModalDescription>
|
|
756
|
+
</ModalHeader>
|
|
757
|
+
<ModalBody>Content</ModalBody>
|
|
758
|
+
<ModalFooter>
|
|
759
|
+
<ModalClose asChild>
|
|
760
|
+
<Button appearance="ghost" intent="brand" size="md">Cancel</Button>
|
|
761
|
+
</ModalClose>
|
|
762
|
+
<Button appearance="solid" intent="brand" size="md">Save</Button>
|
|
763
|
+
</ModalFooter>
|
|
764
|
+
</SidePanelContent>
|
|
765
|
+
</SidePanel>
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
| Prop (SidePanelContent) | Values |
|
|
769
|
+
|---|---|
|
|
770
|
+
| `overlay` | `boolean` (default: true — shows dimmed overlay) |
|
|
771
|
+
| `className` | Override positioning (e.g., `"absolute inset-y-0 right-0"` for container-relative) |
|
|
772
|
+
|
|
773
|
+
Header and footer are optional — compose with `ModalHeader`, `ModalBody`, `ModalFooter` as needed.
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
777
|
+
### UserMenu
|
|
778
|
+
|
|
779
|
+
```tsx
|
|
780
|
+
import { UserMenu, UserMenuInfoRow, UserMenuSection } from "@l3mpire/ui";
|
|
781
|
+
|
|
782
|
+
<UserMenu>
|
|
783
|
+
<UserMenuInfoRow
|
|
784
|
+
name="John Doe"
|
|
785
|
+
email="john@example.com"
|
|
786
|
+
avatarSrc="https://..."
|
|
787
|
+
/>
|
|
788
|
+
<UserMenuSection>
|
|
789
|
+
<DropdownMenuItem icon={faGearSolid} label="Settings" />
|
|
790
|
+
<DropdownMenuItem icon={faArrowRightSolid} label="Sign out" />
|
|
791
|
+
</UserMenuSection>
|
|
792
|
+
</UserMenu>
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
### ProductLogo
|
|
798
|
+
|
|
799
|
+
Renders product logos for lemlist, lemwarm, and lemcal. Supports icon-only or full logotype (icon + text) modes. Automatically switches between light and dark SVGs based on `data-theme`.
|
|
800
|
+
|
|
801
|
+
```tsx
|
|
802
|
+
import { ProductLogo } from "@l3mpire/ui";
|
|
803
|
+
|
|
804
|
+
// Full logotype (icon + text)
|
|
805
|
+
<ProductLogo product="lemlist" size="lg" hasText />
|
|
806
|
+
|
|
807
|
+
// Icon only
|
|
808
|
+
<ProductLogo product="lemcal" size="md" hasText={false} />
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
| Prop | Values |
|
|
812
|
+
|---|---|
|
|
813
|
+
| `product` | `"lemlist"`, `"lemwarm"`, `"lemcal"` |
|
|
814
|
+
| `size` | `"sm"` (20px), `"md"` (28px), `"lg"` (32px), `"xl"` (40px, icon-only) |
|
|
815
|
+
| `hasText` | `boolean` — `true` = logotype, `false` = icon only |
|
|
816
|
+
|
|
817
|
+
**Notes:**
|
|
818
|
+
- `xl` size is icon-only regardless of `hasText`
|
|
819
|
+
- Automatically detects dark mode via `data-theme="dark"` attribute
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
### Table (Low-Level)
|
|
824
|
+
|
|
825
|
+
```tsx
|
|
826
|
+
import {
|
|
827
|
+
Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
|
|
828
|
+
} from "@l3mpire/ui";
|
|
829
|
+
|
|
830
|
+
<Table>
|
|
831
|
+
<TableHeader>
|
|
832
|
+
<TableRow>
|
|
833
|
+
<TableHead>Name</TableHead>
|
|
834
|
+
<TableHead>Email</TableHead>
|
|
835
|
+
</TableRow>
|
|
836
|
+
</TableHeader>
|
|
837
|
+
<TableBody>
|
|
838
|
+
<TableRow>
|
|
839
|
+
<TableCell>John</TableCell>
|
|
840
|
+
<TableCell>john@example.com</TableCell>
|
|
841
|
+
</TableRow>
|
|
842
|
+
</TableBody>
|
|
843
|
+
</Table>
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
---
|
|
847
|
+
|
|
848
|
+
### DataTable
|
|
849
|
+
|
|
850
|
+
Data-driven table powered by TanStack Table. Wraps the low-level `Table` primitives with opt-in features.
|
|
851
|
+
|
|
852
|
+
```tsx
|
|
853
|
+
import { DataTable, DataTablePagination, type ColumnDef } from "@l3mpire/ui";
|
|
854
|
+
|
|
855
|
+
const columns: ColumnDef<Person>[] = [
|
|
856
|
+
{ accessorKey: "name", header: "Name" },
|
|
857
|
+
{ accessorKey: "email", header: "Email" },
|
|
858
|
+
];
|
|
859
|
+
|
|
860
|
+
<DataTable
|
|
861
|
+
columns={columns}
|
|
862
|
+
data={people}
|
|
863
|
+
enableSorting
|
|
864
|
+
enablePagination
|
|
865
|
+
enableColumnResizing
|
|
866
|
+
bordered
|
|
867
|
+
>
|
|
868
|
+
{(table) => <DataTablePagination table={table} />}
|
|
869
|
+
</DataTable>
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
| Prop | Default | Description |
|
|
873
|
+
|---|---|---|
|
|
874
|
+
| `columns` | *required* | TanStack Table column definitions |
|
|
875
|
+
| `data` | *required* | Array of row data |
|
|
876
|
+
| `enableSorting` | `false` | Client-side column sorting |
|
|
877
|
+
| `enableFiltering` | `false` | Client-side column filtering with popover |
|
|
878
|
+
| `enablePagination` | `false` | Client-side pagination |
|
|
879
|
+
| `enableRowSelection` | `false` | Row selection via checkbox |
|
|
880
|
+
| `enableColumnVisibility` | `false` | Toggle column visibility |
|
|
881
|
+
| `enableColumnPinning` | `false` | Pin columns left/right |
|
|
882
|
+
| `enableColumnResizing` | `false` | Drag to resize columns |
|
|
883
|
+
| `enableColumnDrag` | `false` | Drag to reorder columns |
|
|
884
|
+
| `bordered` | `false` | Border-top on header (full-width layouts) |
|
|
885
|
+
| `emptyState` | — | `ReactNode` shown when `data` is empty |
|
|
886
|
+
| `sorting` | — | Controlled sorting state |
|
|
887
|
+
| `onSortingChange` | — | Controlled sorting callback |
|
|
888
|
+
| `columnFilters` | — | Controlled filter state |
|
|
889
|
+
| `onColumnFiltersChange` | — | Controlled filter callback |
|
|
890
|
+
| `rowSelection` | — | Controlled selection state |
|
|
891
|
+
| `onRowSelectionChange` | — | Controlled selection callback |
|
|
892
|
+
| `children` | — | Render prop `(table) => ReactNode` for pagination |
|
|
893
|
+
|
|
894
|
+
#### Column Meta
|
|
895
|
+
|
|
896
|
+
Use `meta` on column definitions for extended features:
|
|
897
|
+
|
|
898
|
+
```tsx
|
|
899
|
+
const columns: ColumnDef<Item>[] = [
|
|
900
|
+
{
|
|
901
|
+
accessorKey: "name",
|
|
902
|
+
header: "Name",
|
|
903
|
+
meta: {
|
|
904
|
+
icon: faUserOutline, // Leading icon in header
|
|
905
|
+
enableDrag: true, // Draggable (requires enableColumnDrag)
|
|
906
|
+
filterType: "string", // Filter popover type: "string" | "number" | "date" | "select"
|
|
907
|
+
filterOptions: ["A", "B"], // Options for "select" filter type
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
];
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
#### Cell Renderers
|
|
914
|
+
|
|
915
|
+
Pre-built cell components for common patterns:
|
|
916
|
+
|
|
917
|
+
```tsx
|
|
918
|
+
import {
|
|
919
|
+
AvatarCell, StatusCell, NumberCell, DateCell,
|
|
920
|
+
EmailCell, LinkCell, ButtonCell, EditableCell, RowActions,
|
|
921
|
+
} from "@l3mpire/ui";
|
|
922
|
+
|
|
923
|
+
// In column definitions:
|
|
924
|
+
{ cell: ({ row }) => <AvatarCell name={row.original.name} src={row.original.avatar} /> }
|
|
925
|
+
{ cell: ({ row }) => <StatusCell status="active" /> }
|
|
926
|
+
{ cell: ({ row }) => <NumberCell value={row.original.amount} /> }
|
|
927
|
+
{ cell: ({ row }) => <DateCell value={row.original.date} /> }
|
|
928
|
+
{ cell: ({ row }) => <EmailCell value={row.original.email} /> }
|
|
929
|
+
{ cell: ({ row }) => <EditableCell value={row.original.name} onSave={(v) => {}} /> }
|
|
930
|
+
{ cell: ({ row }) => <RowActions actions={[{ label: "Edit", onClick: () => {} }]} /> }
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
---
|
|
934
|
+
|
|
935
|
+
### EmptyState
|
|
936
|
+
|
|
937
|
+
```tsx
|
|
938
|
+
import { EmptyState } from "@l3mpire/ui";
|
|
939
|
+
import { faUsersSolid } from "@l3mpire/icons";
|
|
940
|
+
|
|
941
|
+
<EmptyState
|
|
942
|
+
icon={faUsersSolid}
|
|
943
|
+
title="No results"
|
|
944
|
+
description="Try a different search query."
|
|
945
|
+
size="md"
|
|
946
|
+
/>
|
|
947
|
+
|
|
948
|
+
<EmptyState
|
|
949
|
+
icon={faUsersSolid}
|
|
950
|
+
title="No contacts yet"
|
|
951
|
+
size="lg"
|
|
952
|
+
action={<Button appearance="solid" intent="brand" size="md">Add contact</Button>}
|
|
953
|
+
/>
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
| Prop | Values |
|
|
957
|
+
|---|---|
|
|
958
|
+
| `icon` | `IconDefinition` |
|
|
959
|
+
| `title` | `string` (required) |
|
|
960
|
+
| `description` | `string` |
|
|
961
|
+
| `size` | `"sm"`, `"md"`, `"lg"` |
|
|
962
|
+
| `action` | `ReactNode` (e.g., a Button) |
|
|
963
|
+
|
|
964
|
+
---
|
|
965
|
+
|
|
966
|
+
## Size Availability
|
|
967
|
+
|
|
968
|
+
| Component | sm | md | lg | xl |
|
|
969
|
+
|---|---|---|---|---|
|
|
970
|
+
| Button | x | x | x | |
|
|
971
|
+
| Badge | x | x | x | |
|
|
972
|
+
| Tag | x | x | | |
|
|
973
|
+
| Link | x | x | | |
|
|
974
|
+
| TextInput | x | x | | |
|
|
975
|
+
| Select | x | x | | |
|
|
976
|
+
| SearchBar | x | x | | |
|
|
977
|
+
| Avatar | x | x | x | x |
|
|
978
|
+
| Modal | x | x | x | full |
|
|
979
|
+
| EmptyState | x | x | x | |
|
|
980
|
+
|
|
981
|
+
---
|
|
982
|
+
|
|
983
|
+
## Color Token Patterns
|
|
984
|
+
|
|
985
|
+
Component colors follow this convention:
|
|
986
|
+
|
|
987
|
+
```
|
|
988
|
+
Token CSS var: --comp-{component}-{variant}-{property}
|
|
989
|
+
Theme class: {component}-{variant}-{property} (comp- prefix dropped)
|
|
990
|
+
Tailwind usage: bg-{component}-{variant}-{property}
|
|
991
|
+
text-{component}-{variant}-{property}
|
|
992
|
+
border-{component}-{variant}-{property}
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
Examples:
|
|
996
|
+
- `bg-badge-solid-primary-bg` → badge solid primary background
|
|
997
|
+
- `text-toast-title` → toast title text color
|
|
998
|
+
- `border-text-input-border-default` → text input default border
|
|
999
|
+
|
|
1000
|
+
---
|
|
1001
|
+
|
|
1002
|
+
## Utility: `cn()`
|
|
1003
|
+
|
|
1004
|
+
Merge Tailwind classes safely (handles conflicts):
|
|
1005
|
+
|
|
1006
|
+
```tsx
|
|
1007
|
+
import { cn } from "@l3mpire/ui";
|
|
1008
|
+
|
|
1009
|
+
<div className={cn("p-base text-sm", isActive && "bg-primary", className)} />
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
## Build Order
|
|
1015
|
+
|
|
1016
|
+
```
|
|
1017
|
+
tokens → icons → ui → storybook
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
```bash
|
|
1021
|
+
pnpm --filter @l3mpire/tokens build
|
|
1022
|
+
pnpm --filter @l3mpire/icons build
|
|
1023
|
+
pnpm --filter @l3mpire/ui build
|
|
1024
|
+
pnpm --filter @l3mpire/storybook dev # launches Storybook
|
|
1025
|
+
```
|