@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 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