@codeswayam/ui 1.0.0
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 +597 -0
- package/dist/components/base/avatar.d.ts +7 -0
- package/dist/components/base/avatar.d.ts.map +1 -0
- package/dist/components/base/avatar.js +11 -0
- package/dist/components/base/badge.d.ts +10 -0
- package/dist/components/base/badge.d.ts.map +1 -0
- package/dist/components/base/badge.js +24 -0
- package/dist/components/base/button.d.ts +12 -0
- package/dist/components/base/button.d.ts.map +1 -0
- package/dist/components/base/button.js +33 -0
- package/dist/components/base/card.d.ts +9 -0
- package/dist/components/base/card.d.ts.map +1 -0
- package/dist/components/base/card.js +16 -0
- package/dist/components/base/dropdown-menu.d.ts +28 -0
- package/dist/components/base/dropdown-menu.d.ts.map +1 -0
- package/dist/components/base/dropdown-menu.js +35 -0
- package/dist/components/base/input.d.ts +4 -0
- package/dist/components/base/input.d.ts.map +1 -0
- package/dist/components/base/input.js +8 -0
- package/dist/components/base/label.d.ts +5 -0
- package/dist/components/base/label.d.ts.map +1 -0
- package/dist/components/base/label.js +12 -0
- package/dist/components/layout/GlobalFooter.d.ts +2 -0
- package/dist/components/layout/GlobalFooter.d.ts.map +1 -0
- package/dist/components/layout/GlobalFooter.js +47 -0
- package/dist/components/layout/GlobalNavbar.d.ts +2 -0
- package/dist/components/layout/GlobalNavbar.d.ts.map +1 -0
- package/dist/components/layout/GlobalNavbar.js +65 -0
- package/dist/components/saas/status-badge.d.ts +10 -0
- package/dist/components/saas/status-badge.d.ts.map +1 -0
- package/dist/components/saas/status-badge.js +28 -0
- package/dist/components/saas/user-menu.d.ts +23 -0
- package/dist/components/saas/user-menu.d.ts.map +1 -0
- package/dist/components/saas/user-menu.js +26 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/cn.d.ts +3 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +5 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
# @codeswayam/ui - UI Component Library
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
**@codeswayam/ui** is a comprehensive UI component library built on **Radix UI** and **Tailwind CSS**. It provides reusable, accessible, and well-documented React components used across all CodeSwayam applications. The library ensures consistent design and user experience across the platform.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🎯 Features
|
|
10
|
+
|
|
11
|
+
- **Accessible Components**: Built with Radix UI for accessibility
|
|
12
|
+
- **Tailwind CSS**: Utility-first styling
|
|
13
|
+
- **Type-Safe**: Full TypeScript support
|
|
14
|
+
- **Themeable**: Customizable colors and styles
|
|
15
|
+
- **Responsive**: Mobile-first design
|
|
16
|
+
- **Dark Mode**: Built-in dark mode support
|
|
17
|
+
- **60+ Components**: Comprehensive component library
|
|
18
|
+
- **Well-Documented**: Storybook documentation
|
|
19
|
+
- **Composable**: Easy to extend and customize
|
|
20
|
+
- **Zero Dependencies**: Uses peer dependencies only
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @codeswayam/ui
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🔧 Setup
|
|
33
|
+
|
|
34
|
+
### 1. Install Peer Dependencies
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install react react-dom next tailwindcss
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Configure Tailwind
|
|
41
|
+
|
|
42
|
+
Add to `tailwind.config.ts`:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import type { Config } from 'tailwindcss'
|
|
46
|
+
|
|
47
|
+
const config: Config = {
|
|
48
|
+
content: [
|
|
49
|
+
'./node_modules/@codeswayam/ui/**/*.{js,ts,jsx,tsx}',
|
|
50
|
+
'./app/**/*.{js,ts,jsx,tsx}',
|
|
51
|
+
'./components/**/*.{js,ts,jsx,tsx}'
|
|
52
|
+
],
|
|
53
|
+
theme: {
|
|
54
|
+
extend: {}
|
|
55
|
+
},
|
|
56
|
+
plugins: []
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default config
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Import Styles
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// app/globals.css or your global CSS file
|
|
66
|
+
@import '@codeswayam/ui/globals.css'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 🚀 Basic Usage
|
|
72
|
+
|
|
73
|
+
### Import Components
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import {
|
|
77
|
+
Button,
|
|
78
|
+
Card,
|
|
79
|
+
Input,
|
|
80
|
+
Label,
|
|
81
|
+
Select,
|
|
82
|
+
Dialog,
|
|
83
|
+
Tabs,
|
|
84
|
+
Toast
|
|
85
|
+
} from '@codeswayam/ui'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Using Components
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { Button } from '@codeswayam/ui'
|
|
92
|
+
|
|
93
|
+
export function App() {
|
|
94
|
+
return <Button variant="primary">Click me</Button>
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 📚 Component Library
|
|
101
|
+
|
|
102
|
+
### Layout Components
|
|
103
|
+
|
|
104
|
+
#### Container
|
|
105
|
+
Responsive container with max width
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { Container } from '@codeswayam/ui'
|
|
109
|
+
|
|
110
|
+
<Container>
|
|
111
|
+
<h1>Your content</h1>
|
|
112
|
+
</Container>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Grid
|
|
116
|
+
Responsive grid layout
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { Grid, GridItem } from '@codeswayam/ui'
|
|
120
|
+
|
|
121
|
+
<Grid columns={3} gap={4}>
|
|
122
|
+
<GridItem>Item 1</GridItem>
|
|
123
|
+
<GridItem>Item 2</GridItem>
|
|
124
|
+
<GridItem>Item 3</GridItem>
|
|
125
|
+
</Grid>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Form Components
|
|
129
|
+
|
|
130
|
+
#### Button
|
|
131
|
+
Versatile button component
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { Button } from '@codeswayam/ui'
|
|
135
|
+
|
|
136
|
+
// Variants
|
|
137
|
+
<Button variant="primary">Primary</Button>
|
|
138
|
+
<Button variant="secondary">Secondary</Button>
|
|
139
|
+
<Button variant="outline">Outline</Button>
|
|
140
|
+
<Button variant="ghost">Ghost</Button>
|
|
141
|
+
|
|
142
|
+
// Sizes
|
|
143
|
+
<Button size="sm">Small</Button>
|
|
144
|
+
<Button size="md">Medium</Button>
|
|
145
|
+
<Button size="lg">Large</Button>
|
|
146
|
+
|
|
147
|
+
// States
|
|
148
|
+
<Button disabled>Disabled</Button>
|
|
149
|
+
<Button isLoading>Loading...</Button>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Input
|
|
153
|
+
Text input field
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { Input } from '@codeswayam/ui'
|
|
157
|
+
|
|
158
|
+
<Input
|
|
159
|
+
type=\"email\"
|
|
160
|
+
placeholder=\"Enter email\"
|
|
161
|
+
onChange={(e) => setValue(e.target.value)}
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Label
|
|
166
|
+
Form label component
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
import { Label } from '@codeswayam/ui'
|
|
170
|
+
|
|
171
|
+
<Label htmlFor=\"email\">Email Address</Label>
|
|
172
|
+
<Input id=\"email\" />
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Select
|
|
176
|
+
Dropdown select component
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
import { Select, SelectContent, SelectItem, SelectTrigger } from '@codeswayam/ui'
|
|
180
|
+
|
|
181
|
+
<Select defaultValue=\"option1\">
|
|
182
|
+
<SelectTrigger>
|
|
183
|
+
<span>Choose option</span>
|
|
184
|
+
</SelectTrigger>
|
|
185
|
+
<SelectContent>
|
|
186
|
+
<SelectItem value=\"option1\">Option 1</SelectItem>
|
|
187
|
+
<SelectItem value=\"option2\">Option 2</SelectItem>
|
|
188
|
+
<SelectItem value=\"option3\">Option 3</SelectItem>
|
|
189
|
+
</SelectContent>
|
|
190
|
+
</Select>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### Textarea
|
|
194
|
+
Multi-line text input
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { Textarea } from '@codeswayam/ui'
|
|
198
|
+
|
|
199
|
+
<Textarea
|
|
200
|
+
placeholder=\"Enter message\"
|
|
201
|
+
rows={5}
|
|
202
|
+
onChange={(e) => setValue(e.target.value)}
|
|
203
|
+
/>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Checkbox
|
|
207
|
+
Checkbox input
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
import { Checkbox } from '@codeswayam/ui'
|
|
211
|
+
|
|
212
|
+
<Checkbox
|
|
213
|
+
id=\"terms\"
|
|
214
|
+
onCheckedChange={setTermsAccepted}
|
|
215
|
+
/>
|
|
216
|
+
<Label htmlFor=\"terms\">I agree to terms</Label>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### Radio Group
|
|
220
|
+
Radio button group
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import { Radio, RadioGroup } from '@codeswayam/ui'
|
|
224
|
+
|
|
225
|
+
<RadioGroup defaultValue=\"option1\">
|
|
226
|
+
<div className=\"flex items-center\">
|
|
227
|
+
<Radio value=\"option1\" id=\"option1\" />
|
|
228
|
+
<Label htmlFor=\"option1\">Option 1</Label>
|
|
229
|
+
</div>
|
|
230
|
+
<div className=\"flex items-center\">
|
|
231
|
+
<Radio value=\"option2\" id=\"option2\" />
|
|
232
|
+
<Label htmlFor=\"option2\">Option 2</Label>
|
|
233
|
+
</div>
|
|
234
|
+
</RadioGroup>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Switch
|
|
238
|
+
Toggle switch
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
import { Switch } from '@codeswayam/ui'
|
|
242
|
+
|
|
243
|
+
<Switch
|
|
244
|
+
checked={enabled}
|
|
245
|
+
onCheckedChange={setEnabled}
|
|
246
|
+
/>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Data Display Components
|
|
250
|
+
|
|
251
|
+
#### Card
|
|
252
|
+
Container component for content
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@codeswayam/ui'
|
|
256
|
+
|
|
257
|
+
<Card>
|
|
258
|
+
<CardHeader>
|
|
259
|
+
<CardTitle>Card Title</CardTitle>
|
|
260
|
+
<CardDescription>Description</CardDescription>
|
|
261
|
+
</CardHeader>
|
|
262
|
+
<CardContent>
|
|
263
|
+
Card content here
|
|
264
|
+
</CardContent>
|
|
265
|
+
</Card>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### Badge
|
|
269
|
+
Status/tag badge
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import { Badge } from '@codeswayam/ui'
|
|
273
|
+
|
|
274
|
+
<Badge variant=\"default\">New</Badge>
|
|
275
|
+
<Badge variant=\"success\">Active</Badge>
|
|
276
|
+
<Badge variant=\"warning\">Pending</Badge>
|
|
277
|
+
<Badge variant=\"destructive\">Error</Badge>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Table
|
|
281
|
+
Data table component
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
import {
|
|
285
|
+
Table,
|
|
286
|
+
TableBody,
|
|
287
|
+
TableCell,
|
|
288
|
+
TableHead,
|
|
289
|
+
TableHeader,
|
|
290
|
+
TableRow
|
|
291
|
+
} from '@codeswayam/ui'
|
|
292
|
+
|
|
293
|
+
<Table>
|
|
294
|
+
<TableHeader>
|
|
295
|
+
<TableRow>
|
|
296
|
+
<TableHead>Name</TableHead>
|
|
297
|
+
<TableHead>Email</TableHead>
|
|
298
|
+
</TableRow>
|
|
299
|
+
</TableHeader>
|
|
300
|
+
<TableBody>
|
|
301
|
+
<TableRow>
|
|
302
|
+
<TableCell>John</TableCell>
|
|
303
|
+
<TableCell>john@example.com</TableCell>
|
|
304
|
+
</TableRow>
|
|
305
|
+
</TableBody>
|
|
306
|
+
</Table>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Overlay Components
|
|
310
|
+
|
|
311
|
+
#### Dialog
|
|
312
|
+
Modal dialog
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
import {
|
|
316
|
+
Dialog,
|
|
317
|
+
DialogContent,
|
|
318
|
+
DialogDescription,
|
|
319
|
+
DialogHeader,
|
|
320
|
+
DialogTitle,
|
|
321
|
+
DialogTrigger
|
|
322
|
+
} from '@codeswayam/ui'
|
|
323
|
+
|
|
324
|
+
<Dialog>
|
|
325
|
+
<DialogTrigger>Open Dialog</DialogTrigger>
|
|
326
|
+
<DialogContent>
|
|
327
|
+
<DialogHeader>
|
|
328
|
+
<DialogTitle>Dialog Title</DialogTitle>
|
|
329
|
+
<DialogDescription>Description</DialogDescription>
|
|
330
|
+
</DialogHeader>
|
|
331
|
+
Dialog content
|
|
332
|
+
</DialogContent>
|
|
333
|
+
</Dialog>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### Alert Dialog
|
|
337
|
+
Confirmation dialog
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import {
|
|
341
|
+
AlertDialog,
|
|
342
|
+
AlertDialogAction,
|
|
343
|
+
AlertDialogCancel,
|
|
344
|
+
AlertDialogContent,
|
|
345
|
+
AlertDialogDescription,
|
|
346
|
+
AlertDialogHeader,
|
|
347
|
+
AlertDialogTitle,
|
|
348
|
+
AlertDialogTrigger
|
|
349
|
+
} from '@codeswayam/ui'
|
|
350
|
+
|
|
351
|
+
<AlertDialog>
|
|
352
|
+
<AlertDialogTrigger>Delete</AlertDialogTrigger>
|
|
353
|
+
<AlertDialogContent>
|
|
354
|
+
<AlertDialogHeader>
|
|
355
|
+
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
|
356
|
+
<AlertDialogDescription>
|
|
357
|
+
This action cannot be undone
|
|
358
|
+
</AlertDialogDescription>
|
|
359
|
+
</AlertDialogHeader>
|
|
360
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
361
|
+
<AlertDialogAction>Delete</AlertDialogAction>
|
|
362
|
+
</AlertDialogContent>
|
|
363
|
+
</AlertDialog>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Popover
|
|
367
|
+
Floating content popover
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
import {
|
|
371
|
+
Popover,
|
|
372
|
+
PopoverContent,
|
|
373
|
+
PopoverTrigger
|
|
374
|
+
} from '@codeswayam/ui'
|
|
375
|
+
|
|
376
|
+
<Popover>
|
|
377
|
+
<PopoverTrigger>Open</PopoverTrigger>
|
|
378
|
+
<PopoverContent>
|
|
379
|
+
Popover content
|
|
380
|
+
</PopoverContent>
|
|
381
|
+
</Popover>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### Dropdown Menu
|
|
385
|
+
Dropdown menu
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import {
|
|
389
|
+
DropdownMenu,
|
|
390
|
+
DropdownMenuContent,
|
|
391
|
+
DropdownMenuItem,
|
|
392
|
+
DropdownMenuSeparator,
|
|
393
|
+
DropdownMenuTrigger
|
|
394
|
+
} from '@codeswayam/ui'
|
|
395
|
+
|
|
396
|
+
<DropdownMenu>
|
|
397
|
+
<DropdownMenuTrigger>Menu</DropdownMenuTrigger>
|
|
398
|
+
<DropdownMenuContent>
|
|
399
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
400
|
+
<DropdownMenuSeparator />
|
|
401
|
+
<DropdownMenuItem>Logout</DropdownMenuItem>
|
|
402
|
+
</DropdownMenuContent>
|
|
403
|
+
</DropdownMenu>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Navigation Components
|
|
407
|
+
|
|
408
|
+
#### Tabs
|
|
409
|
+
Tabbed interface
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@codeswayam/ui'
|
|
413
|
+
|
|
414
|
+
<Tabs defaultValue=\"tab1\">
|
|
415
|
+
<TabsList>
|
|
416
|
+
<TabsTrigger value=\"tab1\">Tab 1</TabsTrigger>
|
|
417
|
+
<TabsTrigger value=\"tab2\">Tab 2</TabsTrigger>
|
|
418
|
+
</TabsList>
|
|
419
|
+
<TabsContent value=\"tab1\">Content 1</TabsContent>
|
|
420
|
+
<TabsContent value=\"tab2\">Content 2</TabsContent>
|
|
421
|
+
</Tabs>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Feedback Components
|
|
425
|
+
|
|
426
|
+
#### Toast
|
|
427
|
+
Toast notification
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
import { useToast } from '@codeswayam/ui/hooks'
|
|
431
|
+
|
|
432
|
+
const { toast } = useToast()
|
|
433
|
+
|
|
434
|
+
toast({
|
|
435
|
+
title: 'Success',
|
|
436
|
+
description: 'Operation completed',
|
|
437
|
+
variant: 'default'
|
|
438
|
+
})
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### Progress
|
|
442
|
+
Progress bar
|
|
443
|
+
|
|
444
|
+
```tsx
|
|
445
|
+
import { Progress } from '@codeswayam/ui'
|
|
446
|
+
|
|
447
|
+
<Progress value={65} />
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### Skeleton
|
|
451
|
+
Loading skeleton
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
import { Skeleton } from '@codeswayam/ui'
|
|
455
|
+
|
|
456
|
+
<Skeleton className=\"h-12 w-12 rounded-full\" />
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## 🎨 Styling & Customization
|
|
462
|
+
|
|
463
|
+
### Tailwind CSS Classes
|
|
464
|
+
|
|
465
|
+
```tsx
|
|
466
|
+
<Button className=\"custom-class\">
|
|
467
|
+
Custom Button
|
|
468
|
+
</Button>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Theme Customization
|
|
472
|
+
|
|
473
|
+
```tsx
|
|
474
|
+
// Extend tailwind config
|
|
475
|
+
const config: Config = {
|
|
476
|
+
theme: {
|
|
477
|
+
extend: {
|
|
478
|
+
colors: {
|
|
479
|
+
brand: '#your-color'
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### Dark Mode
|
|
487
|
+
|
|
488
|
+
Components automatically support dark mode:
|
|
489
|
+
|
|
490
|
+
```tsx
|
|
491
|
+
// Enable dark mode in HTML
|
|
492
|
+
<html className=\"dark\">
|
|
493
|
+
<body>...</body>
|
|
494
|
+
</html>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## 🔗 Component Props
|
|
500
|
+
|
|
501
|
+
### Common Props
|
|
502
|
+
|
|
503
|
+
Most components accept:
|
|
504
|
+
- `className` - Tailwind CSS classes
|
|
505
|
+
- `disabled` - Disable component
|
|
506
|
+
- `aria-*` - Accessibility attributes
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## 🧪 Testing
|
|
511
|
+
|
|
512
|
+
```tsx
|
|
513
|
+
import { render, screen } from '@testing-library/react'
|
|
514
|
+
import { Button } from '@codeswayam/ui'
|
|
515
|
+
|
|
516
|
+
test('button renders', () => {
|
|
517
|
+
render(<Button>Click me</Button>)
|
|
518
|
+
expect(screen.getByRole('button')).toBeInTheDocument()
|
|
519
|
+
})
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## 📖 Storybook
|
|
525
|
+
|
|
526
|
+
View all components in Storybook:
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
npm run storybook
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## ♿ Accessibility
|
|
535
|
+
|
|
536
|
+
All components are built with accessibility in mind:
|
|
537
|
+
- Keyboard navigation
|
|
538
|
+
- Screen reader support
|
|
539
|
+
- ARIA labels
|
|
540
|
+
- Focus management
|
|
541
|
+
- Color contrast
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## 📋 Component Checklist
|
|
546
|
+
|
|
547
|
+
Essential components:
|
|
548
|
+
- [x] Button
|
|
549
|
+
- [x] Input
|
|
550
|
+
- [x] Card
|
|
551
|
+
- [x] Dialog
|
|
552
|
+
- [x] Select
|
|
553
|
+
- [x] Tabs
|
|
554
|
+
- [x] Badge
|
|
555
|
+
- [x] Table
|
|
556
|
+
- [x] Toast
|
|
557
|
+
- [x] Checkbox
|
|
558
|
+
- [x] Radio
|
|
559
|
+
- [x] Switch
|
|
560
|
+
- [x] Textarea
|
|
561
|
+
- [x] Progress
|
|
562
|
+
- [x] Skeleton
|
|
563
|
+
- [x] Dropdown Menu
|
|
564
|
+
- [x] Popover
|
|
565
|
+
- [x] Alert Dialog
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## 🤝 Contributing
|
|
570
|
+
|
|
571
|
+
### Adding New Components
|
|
572
|
+
|
|
573
|
+
1. Create component in `src/components/`
|
|
574
|
+
2. Export from `src/index.ts`
|
|
575
|
+
3. Add Storybook story
|
|
576
|
+
4. Document usage
|
|
577
|
+
5. Test accessibility
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## 📄 License
|
|
582
|
+
|
|
583
|
+
ISC License
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## 🔗 Related Packages
|
|
588
|
+
|
|
589
|
+
- [@codeswayam/api-client](../api-client/README.md) - API client
|
|
590
|
+
- [@codeswayam/auth](../auth-client/README.md) - Auth utilities
|
|
591
|
+
- [@shared/database](../database/README.md) - Database utilities
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
**Last Updated**: April 2026
|
|
596
|
+
|
|
597
|
+
For more information, see the main [README.md](../../README.md)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
|
+
declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
|
+
declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
5
|
+
declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
7
|
+
//# sourceMappingURL=avatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../src/components/base/avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AAGzD,QAAA,MAAM,MAAM,yJAYV,CAAA;AAGF,QAAA,MAAM,WAAW,gKASf,CAAA;AAGF,QAAA,MAAM,cAAc,iKAYlB,CAAA;AAGF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
4
|
+
import { cn } from "../../utils/cn";
|
|
5
|
+
const Avatar = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Root, { ref: ref, className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className), ...props })));
|
|
6
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
7
|
+
const AvatarImage = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Image, { ref: ref, className: cn("aspect-square h-full w-full", className), ...props })));
|
|
8
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
9
|
+
const AvatarFallback = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Fallback, { ref: ref, className: cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className), ...props })));
|
|
10
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
11
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const badgeVariants: (props?: ({
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "warning" | "info" | "purple" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
7
|
+
}
|
|
8
|
+
declare function Badge({ className, variant, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export { Badge, badgeVariants };
|
|
10
|
+
//# sourceMappingURL=badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/components/base/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,aAAa;;8EAmBlB,CAAC;AAEF,MAAM,WAAW,UACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,YAAY,CAAC,OAAO,aAAa,CAAC;CAAG;AAEzC,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,2CAE1D;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../../utils/cn";
|
|
4
|
+
const badgeVariants = cva("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
8
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
9
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
10
|
+
outline: "text-foreground",
|
|
11
|
+
success: "border-transparent bg-emerald-100 text-emerald-700",
|
|
12
|
+
warning: "border-transparent bg-amber-100 text-amber-700",
|
|
13
|
+
info: "border-transparent bg-blue-100 text-blue-700",
|
|
14
|
+
purple: "border-transparent bg-purple-100 text-purple-700",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
variant: "default",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
function Badge({ className, variant, ...props }) {
|
|
22
|
+
return _jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
23
|
+
}
|
|
24
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export { Button, buttonVariants };
|
|
12
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/base/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,cAAc;;;8EAwBnB,CAAC;AAEF,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,QAAA,MAAM,MAAM,uFAOX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { cn } from "../../utils/cn";
|
|
6
|
+
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
10
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
11
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
12
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
13
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
14
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
default: "h-9 px-4 py-2",
|
|
18
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
19
|
+
lg: "h-10 rounded-md px-8",
|
|
20
|
+
icon: "h-9 w-9",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: "default",
|
|
25
|
+
size: "default",
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
29
|
+
const Comp = (asChild ? Slot : "button");
|
|
30
|
+
return (_jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref: ref, ...props }));
|
|
31
|
+
});
|
|
32
|
+
Button.displayName = "Button";
|
|
33
|
+
export { Button, buttonVariants };
|