@lsts_tech/ui 2.0.23
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 +459 -0
- package/dist/index.css +1484 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +1041 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +970 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +90 -0
package/README.md
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
# @lsts_tech/ui - Brand-Agnostic Design System
|
|
2
|
+
|
|
3
|
+
A white-label, brand-agnostic UI component library built for multiple brands with full theming support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Brand-Agnostic Architecture**: Switch between brands (LSTS, TLÁO) with a single prop
|
|
8
|
+
- **Full Theming Support**: Light/dark mode with CSS custom properties
|
|
9
|
+
- **Design Tokens**: HSL-based color system for easy customization
|
|
10
|
+
- **Accessible**: WCAG compliant with proper focus states and ARIA attributes
|
|
11
|
+
- **Type-Safe**: Full TypeScript support with proper type exports
|
|
12
|
+
- **Composable**: Built with Radix UI primitives for flexibility
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @lsts_tech/ui
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
### 1. Wrap your app with providers
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { BrandProvider, ThemeProvider } from "@lsts_tech/ui";
|
|
26
|
+
|
|
27
|
+
function App({ children }) {
|
|
28
|
+
return (
|
|
29
|
+
<BrandProvider defaultBrand="lsts">
|
|
30
|
+
<ThemeProvider defaultTheme="system">
|
|
31
|
+
{children}
|
|
32
|
+
</ThemeProvider>
|
|
33
|
+
</BrandProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Import the global styles
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import "@lsts_tech/ui/styles.css";
|
|
42
|
+
// or in your layout.tsx
|
|
43
|
+
import "@lsts_tech/ui";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Configure Tailwind
|
|
47
|
+
|
|
48
|
+
In your `tailwind.config.ts`:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createRequire } from "module";
|
|
52
|
+
const require = createRequire(import.meta.url);
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
darkMode: ["class", "data-theme='dark'"],
|
|
56
|
+
content: [
|
|
57
|
+
// ... your content
|
|
58
|
+
"./node_modules/@lsts_tech/ui/dist/**/*.{js,ts,jsx,tsx}",
|
|
59
|
+
],
|
|
60
|
+
theme: {
|
|
61
|
+
extend: {
|
|
62
|
+
// The UI library provides all theme tokens
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
plugins: [require("tailwindcss-animate")],
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Brand System
|
|
70
|
+
|
|
71
|
+
### Supported Brands
|
|
72
|
+
|
|
73
|
+
- **LSTS** (default): LSTech Solutions - Blue/purple theme
|
|
74
|
+
- **TLÁO**: Warm earth tones - Orange/green theme
|
|
75
|
+
|
|
76
|
+
### Switching Brands
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { useBrand, BrandSwitcher } from "@lsts_tech/ui";
|
|
80
|
+
|
|
81
|
+
// Programmatic switching
|
|
82
|
+
function MyComponent() {
|
|
83
|
+
const { brand, setBrand } = useBrand();
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<button onClick={() => setBrand("tlao")}>
|
|
87
|
+
Switch to TLÁO
|
|
88
|
+
</button>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// UI Component
|
|
93
|
+
function Settings() {
|
|
94
|
+
return <BrandSwitcher variant="cards" showDescription />;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Adding a New Brand
|
|
99
|
+
|
|
100
|
+
To add a new brand (e.g., "acme"):
|
|
101
|
+
|
|
102
|
+
1. Define brand colors in your global CSS:
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
[data-brand="acme"] {
|
|
106
|
+
--brand-primary-hue: 200;
|
|
107
|
+
--brand-primary-sat: 80%;
|
|
108
|
+
--brand-primary-light: 50%;
|
|
109
|
+
|
|
110
|
+
--brand-secondary-hue: 280;
|
|
111
|
+
--brand-secondary-sat: 60%;
|
|
112
|
+
--brand-secondary-light: 40%;
|
|
113
|
+
|
|
114
|
+
--brand-accent-hue: 45;
|
|
115
|
+
--brand-accent-sat: 90%;
|
|
116
|
+
--brand-accent-light: 60%;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
2. Extend the Brand type in your app:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
type Brand = "lsts" | "tlao" | "acme";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
3. Add brand option to the switcher:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
const brandOptions = [
|
|
130
|
+
{ value: "lsts", label: "LSTS", icon: <Building2 /> },
|
|
131
|
+
{ value: "tlao", label: "TLÁO", icon: <Landmark /> },
|
|
132
|
+
{ value: "acme", label: "Acme", icon: <Rocket /> },
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
<BrandSwitcher options={brandOptions} />
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Theme System
|
|
139
|
+
|
|
140
|
+
### Light/Dark Mode
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { useTheme, ThemeSwitcher } from "@lsts_tech/ui";
|
|
144
|
+
|
|
145
|
+
function Header() {
|
|
146
|
+
const { theme, setTheme, resolvedTheme } = useTheme();
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div>
|
|
150
|
+
<span>Current: {resolvedTheme}</span>
|
|
151
|
+
<ThemeSwitcher variant="segmented" />
|
|
152
|
+
</div>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Design Tokens
|
|
158
|
+
|
|
159
|
+
The UI system uses CSS custom properties for all design tokens:
|
|
160
|
+
|
|
161
|
+
```css
|
|
162
|
+
/* Colors */
|
|
163
|
+
--primary: hsl(var(--primary));
|
|
164
|
+
--primary-foreground: hsl(var(--primary-foreground));
|
|
165
|
+
--secondary: hsl(var(--secondary));
|
|
166
|
+
--background: hsl(var(--background));
|
|
167
|
+
--foreground: hsl(var(--foreground));
|
|
168
|
+
|
|
169
|
+
/* Brand Colors */
|
|
170
|
+
--brand-primary: hsl(var(--brand-primary-hue) var(--brand-primary-sat) var(--brand-primary-light));
|
|
171
|
+
--brand-secondary: var(--brand-secondary);
|
|
172
|
+
--brand-accent: var(--brand-accent);
|
|
173
|
+
--brand-gradient: linear-gradient(...);
|
|
174
|
+
|
|
175
|
+
/* Elevation */
|
|
176
|
+
--shadow-elevation-1: ...;
|
|
177
|
+
--shadow-elevation-2: ...;
|
|
178
|
+
--shadow-elevation-3: ...;
|
|
179
|
+
--shadow-elevation-4: ...;
|
|
180
|
+
|
|
181
|
+
/* Radius */
|
|
182
|
+
--radius: 0.5rem;
|
|
183
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
184
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
185
|
+
--radius-lg: var(--radius);
|
|
186
|
+
|
|
187
|
+
/* Spacing */
|
|
188
|
+
--space-1: 0.25rem;
|
|
189
|
+
--space-2: 0.5rem;
|
|
190
|
+
--space-3: 0.75rem;
|
|
191
|
+
--space-4: 1rem;
|
|
192
|
+
/* ... */
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Components
|
|
196
|
+
|
|
197
|
+
### Button
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { Button } from "@lsts_tech/ui";
|
|
201
|
+
|
|
202
|
+
// Variants
|
|
203
|
+
<Button>Default</Button>
|
|
204
|
+
<Button variant="secondary">Secondary</Button>
|
|
205
|
+
<Button variant="outline">Outline</Button>
|
|
206
|
+
<Button variant="ghost">Ghost</Button>
|
|
207
|
+
<Button variant="destructive">Destructive</Button>
|
|
208
|
+
<Button variant="link">Link</Button>
|
|
209
|
+
|
|
210
|
+
// Brand variants
|
|
211
|
+
<Button variant="brand">Brand Primary</Button>
|
|
212
|
+
<Button variant="brand-secondary">Brand Secondary</Button>
|
|
213
|
+
<Button variant="brand-ghost">Brand Ghost</Button>
|
|
214
|
+
|
|
215
|
+
// Sizes
|
|
216
|
+
<Button size="xs">Extra Small</Button>
|
|
217
|
+
<Button size="sm">Small</Button>
|
|
218
|
+
<Button size="default">Default</Button>
|
|
219
|
+
<Button size="lg">Large</Button>
|
|
220
|
+
<Button size="xl">Extra Large</Button>
|
|
221
|
+
<Button size="2xl">2X Large</Button>
|
|
222
|
+
|
|
223
|
+
// Icon buttons
|
|
224
|
+
<Button size="icon" variant="outline">
|
|
225
|
+
<Settings className="h-4 w-4" />
|
|
226
|
+
</Button>
|
|
227
|
+
|
|
228
|
+
// Loading state
|
|
229
|
+
<Button loading>Loading...</Button>
|
|
230
|
+
|
|
231
|
+
// With icons
|
|
232
|
+
<Button leftIcon={<Mail />} leftIcon={<ArrowRight />}>
|
|
233
|
+
Send Email
|
|
234
|
+
</Button>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Card
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@lsts_tech/ui";
|
|
241
|
+
|
|
242
|
+
<Card variant="elevated" radius="lg">
|
|
243
|
+
<CardHeader>
|
|
244
|
+
<CardTitle>Card Title</CardTitle>
|
|
245
|
+
<CardDescription>Card description here</CardDescription>
|
|
246
|
+
</CardHeader>
|
|
247
|
+
<CardContent>
|
|
248
|
+
Content goes here
|
|
249
|
+
</CardContent>
|
|
250
|
+
<CardFooter>
|
|
251
|
+
<Button>Action</Button>
|
|
252
|
+
</CardFooter>
|
|
253
|
+
</Card>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Input
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
import { Input } from "@lsts_tech/ui";
|
|
260
|
+
|
|
261
|
+
// Basic
|
|
262
|
+
<Input placeholder="Enter text..." />
|
|
263
|
+
|
|
264
|
+
// With icons
|
|
265
|
+
<Input
|
|
266
|
+
leftIcon={<Search />}
|
|
267
|
+
rightIcon={<Keyboard />}
|
|
268
|
+
placeholder="Search..."
|
|
269
|
+
/>
|
|
270
|
+
|
|
271
|
+
// States
|
|
272
|
+
<Input state="error" placeholder="Error state" />
|
|
273
|
+
<Input state="success" placeholder="Success state" />
|
|
274
|
+
|
|
275
|
+
// Variants
|
|
276
|
+
<Input variant="filled" placeholder="Filled variant" />
|
|
277
|
+
<Input variant="ghost" placeholder="Ghost variant" />
|
|
278
|
+
<Input variant="brand" placeholder="Brand variant" />
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Badge
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
import { Badge } from "@lsts_tech/ui";
|
|
285
|
+
|
|
286
|
+
// Variants
|
|
287
|
+
<Badge>Default</Badge>
|
|
288
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
289
|
+
<Badge variant="outline">Outline</Badge>
|
|
290
|
+
<Badge variant="ghost">Ghost</Badge>
|
|
291
|
+
<Badge variant="brand">Brand</Badge>
|
|
292
|
+
<Badge variant="success">Success</Badge>
|
|
293
|
+
<Badge variant="warning">Warning</Badge>
|
|
294
|
+
<Badge variant="error">Error</Badge>
|
|
295
|
+
|
|
296
|
+
// Sizes
|
|
297
|
+
<Badge size="sm">Small</Badge>
|
|
298
|
+
<Badge size="default">Default</Badge>
|
|
299
|
+
<Badge size="lg">Large</Badge>
|
|
300
|
+
<Badge size="xl">Extra Large</Badge>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Alert
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
import { Alert } from "@lsts_tech/ui";
|
|
307
|
+
|
|
308
|
+
// Variants
|
|
309
|
+
<Alert title="Success!" variant="success">
|
|
310
|
+
Your changes have been saved.
|
|
311
|
+
</Alert>
|
|
312
|
+
|
|
313
|
+
<Alert title="Warning" variant="warning">
|
|
314
|
+
Please review your settings.
|
|
315
|
+
</Alert>
|
|
316
|
+
|
|
317
|
+
<Alert title="Error" variant="error">
|
|
318
|
+
Something went wrong.
|
|
319
|
+
</Alert>
|
|
320
|
+
|
|
321
|
+
// Dismissible
|
|
322
|
+
<Alert
|
|
323
|
+
title="Info"
|
|
324
|
+
variant="info"
|
|
325
|
+
dismissible
|
|
326
|
+
onDismiss={() => console.log("Dismissed")}
|
|
327
|
+
>
|
|
328
|
+
This alert can be dismissed.
|
|
329
|
+
</Alert>
|
|
330
|
+
|
|
331
|
+
// Brand variant
|
|
332
|
+
<Alert title="Welcome" variant="brand">
|
|
333
|
+
Welcome to LSTS!
|
|
334
|
+
</Alert>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Brand Switcher
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import { BrandSwitcher } from "@lsts_tech/ui";
|
|
341
|
+
|
|
342
|
+
// Button variant
|
|
343
|
+
<BrandSwitcher variant="buttons" size="md" />
|
|
344
|
+
|
|
345
|
+
// Card variant
|
|
346
|
+
<BrandSwitcher variant="cards" showDescription />
|
|
347
|
+
|
|
348
|
+
// Select variant
|
|
349
|
+
<BrandSwitcher variant="select" />
|
|
350
|
+
|
|
351
|
+
// Custom options
|
|
352
|
+
<BrandSwitcher
|
|
353
|
+
options={[
|
|
354
|
+
{ value: "lsts", label: "LSTS", icon: <Building2 />, description: "LSTech Solutions" },
|
|
355
|
+
{ value: "tlao", label: "TLÁO", icon: <Landmark />, description: "TLÁO Project" },
|
|
356
|
+
]}
|
|
357
|
+
/>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Theme Switcher
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { ThemeSwitcher } from "@lsts_tech/ui";
|
|
364
|
+
|
|
365
|
+
// Segmented control (default)
|
|
366
|
+
<ThemeSwitcher variant="segmented" />
|
|
367
|
+
|
|
368
|
+
// Button variant
|
|
369
|
+
<ThemeSwitcher variant="buttons" />
|
|
370
|
+
|
|
371
|
+
// Card variant
|
|
372
|
+
<ThemeSwitcher variant="cards" showLabel />
|
|
373
|
+
|
|
374
|
+
// Select variant
|
|
375
|
+
<ThemeSwitcher variant="select" />
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Customization
|
|
379
|
+
|
|
380
|
+
### Customizing Design Tokens
|
|
381
|
+
|
|
382
|
+
Override CSS variables in your global CSS:
|
|
383
|
+
|
|
384
|
+
```css
|
|
385
|
+
:root {
|
|
386
|
+
/* Override radius */
|
|
387
|
+
--radius: 0.75rem;
|
|
388
|
+
|
|
389
|
+
/* Override shadows */
|
|
390
|
+
--shadow-elevation-1: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
391
|
+
|
|
392
|
+
/* Override spacing */
|
|
393
|
+
--space-4: 1.25rem;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
[data-theme="dark"] {
|
|
397
|
+
/* Dark mode overrides */
|
|
398
|
+
--shadow-elevation-1: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Using Class Variance Authority (CVA)
|
|
403
|
+
|
|
404
|
+
All components support CVA variants for advanced customization:
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
import { buttonVariants } from "@lsts_tech/ui";
|
|
408
|
+
|
|
409
|
+
// Use variants without the component
|
|
410
|
+
<button className={buttonVariants({ variant: "brand", size: "lg" })}>
|
|
411
|
+
Custom Button
|
|
412
|
+
</button>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## API Reference
|
|
416
|
+
|
|
417
|
+
### Providers
|
|
418
|
+
|
|
419
|
+
#### BrandProvider
|
|
420
|
+
|
|
421
|
+
| Prop | Type | Default | Description |
|
|
422
|
+
|------|------|---------|-------------|
|
|
423
|
+
| `defaultBrand` | `Brand` | `"lsts"` | Initial brand value |
|
|
424
|
+
| `brands` | `Brand[]` | `["lsts", "tlao"]` | Available brands |
|
|
425
|
+
| `storageKey` | `string` | `"ui-brand"` | localStorage key |
|
|
426
|
+
|
|
427
|
+
#### ThemeProvider
|
|
428
|
+
|
|
429
|
+
| Prop | Type | Default | Description |
|
|
430
|
+
|------|------|---------|-------------|
|
|
431
|
+
| `defaultTheme` | `Theme` | `"system"` | Initial theme value |
|
|
432
|
+
| `storageKey` | `string` | `"ui-theme"` | localStorage key |
|
|
433
|
+
| `enableSystem` | `boolean` | `true` | Enable system preference |
|
|
434
|
+
| `disableTransitionOnChange` | `boolean` | `false` | Disable transitions on change |
|
|
435
|
+
|
|
436
|
+
### Hooks
|
|
437
|
+
|
|
438
|
+
#### useBrand
|
|
439
|
+
|
|
440
|
+
```ts
|
|
441
|
+
const { brand, setBrand, brands } = useBrand();
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
#### useTheme
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
const { theme, setTheme, resolvedTheme } = useTheme();
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Browser Support
|
|
451
|
+
|
|
452
|
+
- Chrome 88+
|
|
453
|
+
- Firefox 78+
|
|
454
|
+
- Safari 14+
|
|
455
|
+
- Edge 88+
|
|
456
|
+
|
|
457
|
+
## License
|
|
458
|
+
|
|
459
|
+
MIT © LSTech Solutions
|