omgkit 2.1.1 → 2.2.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.
Files changed (50) hide show
  1. package/package.json +1 -1
  2. package/plugin/skills/SKILL_STANDARDS.md +743 -0
  3. package/plugin/skills/databases/mongodb/SKILL.md +797 -28
  4. package/plugin/skills/databases/prisma/SKILL.md +776 -30
  5. package/plugin/skills/databases/redis/SKILL.md +885 -25
  6. package/plugin/skills/devops/aws/SKILL.md +686 -28
  7. package/plugin/skills/devops/github-actions/SKILL.md +684 -29
  8. package/plugin/skills/devops/kubernetes/SKILL.md +621 -24
  9. package/plugin/skills/frameworks/django/SKILL.md +920 -20
  10. package/plugin/skills/frameworks/express/SKILL.md +1361 -35
  11. package/plugin/skills/frameworks/fastapi/SKILL.md +1260 -33
  12. package/plugin/skills/frameworks/laravel/SKILL.md +1244 -31
  13. package/plugin/skills/frameworks/nestjs/SKILL.md +1005 -26
  14. package/plugin/skills/frameworks/rails/SKILL.md +594 -28
  15. package/plugin/skills/frameworks/spring/SKILL.md +528 -35
  16. package/plugin/skills/frameworks/vue/SKILL.md +1296 -27
  17. package/plugin/skills/frontend/accessibility/SKILL.md +1108 -34
  18. package/plugin/skills/frontend/frontend-design/SKILL.md +1304 -26
  19. package/plugin/skills/frontend/responsive/SKILL.md +847 -21
  20. package/plugin/skills/frontend/shadcn-ui/SKILL.md +976 -38
  21. package/plugin/skills/frontend/tailwindcss/SKILL.md +831 -35
  22. package/plugin/skills/frontend/threejs/SKILL.md +1298 -29
  23. package/plugin/skills/languages/javascript/SKILL.md +935 -31
  24. package/plugin/skills/methodology/brainstorming/SKILL.md +597 -23
  25. package/plugin/skills/methodology/defense-in-depth/SKILL.md +832 -34
  26. package/plugin/skills/methodology/dispatching-parallel-agents/SKILL.md +665 -31
  27. package/plugin/skills/methodology/executing-plans/SKILL.md +556 -24
  28. package/plugin/skills/methodology/finishing-development-branch/SKILL.md +595 -25
  29. package/plugin/skills/methodology/problem-solving/SKILL.md +429 -61
  30. package/plugin/skills/methodology/receiving-code-review/SKILL.md +536 -24
  31. package/plugin/skills/methodology/requesting-code-review/SKILL.md +632 -21
  32. package/plugin/skills/methodology/root-cause-tracing/SKILL.md +641 -30
  33. package/plugin/skills/methodology/sequential-thinking/SKILL.md +262 -3
  34. package/plugin/skills/methodology/systematic-debugging/SKILL.md +571 -32
  35. package/plugin/skills/methodology/test-driven-development/SKILL.md +779 -24
  36. package/plugin/skills/methodology/testing-anti-patterns/SKILL.md +691 -29
  37. package/plugin/skills/methodology/token-optimization/SKILL.md +598 -29
  38. package/plugin/skills/methodology/verification-before-completion/SKILL.md +543 -22
  39. package/plugin/skills/methodology/writing-plans/SKILL.md +590 -18
  40. package/plugin/skills/omega/omega-architecture/SKILL.md +838 -39
  41. package/plugin/skills/omega/omega-coding/SKILL.md +636 -39
  42. package/plugin/skills/omega/omega-sprint/SKILL.md +855 -48
  43. package/plugin/skills/omega/omega-testing/SKILL.md +940 -41
  44. package/plugin/skills/omega/omega-thinking/SKILL.md +703 -50
  45. package/plugin/skills/security/better-auth/SKILL.md +1065 -28
  46. package/plugin/skills/security/oauth/SKILL.md +968 -31
  47. package/plugin/skills/security/owasp/SKILL.md +894 -33
  48. package/plugin/skills/testing/playwright/SKILL.md +764 -38
  49. package/plugin/skills/testing/pytest/SKILL.md +873 -36
  50. package/plugin/skills/testing/vitest/SKILL.md +980 -35
@@ -1,58 +1,996 @@
1
1
  ---
2
2
  name: shadcn-ui
3
- description: shadcn/ui components. Use for pre-built accessible React components.
3
+ description: shadcn/ui component library with accessible React components, theming, and form integration
4
+ category: frontend
5
+ triggers:
6
+ - shadcn
7
+ - shadcn/ui
8
+ - ui components
9
+ - radix ui
10
+ - react components
4
11
  ---
5
12
 
6
- # shadcn/ui Skill
13
+ # shadcn/ui
14
+
15
+ Enterprise-grade **React component library** built on Radix UI primitives following industry best practices. This skill covers component installation, theming, form integration, customization, and accessibility patterns used by top engineering teams.
16
+
17
+ ## Purpose
18
+
19
+ Build beautiful, accessible React applications:
20
+
21
+ - Install and configure components
22
+ - Customize themes and variants
23
+ - Integrate with React Hook Form
24
+ - Build complex UI patterns
25
+ - Extend component functionality
26
+ - Maintain accessibility standards
27
+ - Create consistent design systems
28
+
29
+ ## Features
30
+
31
+ ### 1. Installation and Setup
7
32
 
8
- ## Installation
9
33
  ```bash
34
+ # Initialize shadcn/ui in your project
10
35
  npx shadcn-ui@latest init
36
+
37
+ # Add individual components
11
38
  npx shadcn-ui@latest add button
39
+ npx shadcn-ui@latest add card
40
+ npx shadcn-ui@latest add form
41
+ npx shadcn-ui@latest add input
42
+ npx shadcn-ui@latest add dialog
43
+ npx shadcn-ui@latest add dropdown-menu
44
+ npx shadcn-ui@latest add table
45
+ npx shadcn-ui@latest add toast
46
+
47
+ # Add multiple components at once
48
+ npx shadcn-ui@latest add button card input form
49
+ ```
50
+
51
+ ```json
52
+ // components.json
53
+ {
54
+ "$schema": "https://ui.shadcn.com/schema.json",
55
+ "style": "default",
56
+ "rsc": true,
57
+ "tsx": true,
58
+ "tailwind": {
59
+ "config": "tailwind.config.ts",
60
+ "css": "app/globals.css",
61
+ "baseColor": "slate",
62
+ "cssVariables": true,
63
+ "prefix": ""
64
+ },
65
+ "aliases": {
66
+ "components": "@/components",
67
+ "utils": "@/lib/utils"
68
+ }
69
+ }
12
70
  ```
13
71
 
14
- ## Usage
72
+ ```typescript
73
+ // lib/utils.ts
74
+ import { type ClassValue, clsx } from "clsx";
75
+ import { twMerge } from "tailwind-merge";
76
+
77
+ export function cn(...inputs: ClassValue[]) {
78
+ return twMerge(clsx(inputs));
79
+ }
80
+ ```
81
+
82
+ ### 2. Core Components
83
+
15
84
  ```tsx
16
- import { Button } from "@/components/ui/button"
17
- import { Input } from "@/components/ui/input"
18
- import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
85
+ // Button usage with variants
86
+ import { Button } from "@/components/ui/button";
87
+
88
+ export function ButtonExamples() {
89
+ return (
90
+ <div className="flex flex-wrap gap-4">
91
+ <Button>Default</Button>
92
+ <Button variant="secondary">Secondary</Button>
93
+ <Button variant="destructive">Destructive</Button>
94
+ <Button variant="outline">Outline</Button>
95
+ <Button variant="ghost">Ghost</Button>
96
+ <Button variant="link">Link</Button>
97
+
98
+ {/* Sizes */}
99
+ <Button size="sm">Small</Button>
100
+ <Button size="default">Default</Button>
101
+ <Button size="lg">Large</Button>
102
+ <Button size="icon">
103
+ <PlusIcon className="h-4 w-4" />
104
+ </Button>
105
+
106
+ {/* With loading state */}
107
+ <Button disabled>
108
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
109
+ Please wait
110
+ </Button>
111
+
112
+ {/* As child (for links) */}
113
+ <Button asChild>
114
+ <a href="/dashboard">Go to Dashboard</a>
115
+ </Button>
116
+ </div>
117
+ );
118
+ }
19
119
 
20
- <Button variant="default">Click me</Button>
21
- <Button variant="outline">Outline</Button>
22
- <Button variant="ghost">Ghost</Button>
120
+ // Card component
121
+ import {
122
+ Card,
123
+ CardContent,
124
+ CardDescription,
125
+ CardFooter,
126
+ CardHeader,
127
+ CardTitle,
128
+ } from "@/components/ui/card";
23
129
 
24
- <Card>
25
- <CardHeader>
26
- <CardTitle>Title</CardTitle>
27
- </CardHeader>
28
- <CardContent>
29
- Content here
30
- </CardContent>
31
- </Card>
130
+ export function CardExample() {
131
+ return (
132
+ <Card className="w-[350px]">
133
+ <CardHeader>
134
+ <CardTitle>Create project</CardTitle>
135
+ <CardDescription>Deploy your new project in one-click.</CardDescription>
136
+ </CardHeader>
137
+ <CardContent>
138
+ <form>
139
+ <div className="grid w-full items-center gap-4">
140
+ <div className="flex flex-col space-y-1.5">
141
+ <Label htmlFor="name">Name</Label>
142
+ <Input id="name" placeholder="Name of your project" />
143
+ </div>
144
+ <div className="flex flex-col space-y-1.5">
145
+ <Label htmlFor="framework">Framework</Label>
146
+ <Select>
147
+ <SelectTrigger id="framework">
148
+ <SelectValue placeholder="Select" />
149
+ </SelectTrigger>
150
+ <SelectContent position="popper">
151
+ <SelectItem value="next">Next.js</SelectItem>
152
+ <SelectItem value="sveltekit">SvelteKit</SelectItem>
153
+ <SelectItem value="astro">Astro</SelectItem>
154
+ <SelectItem value="nuxt">Nuxt.js</SelectItem>
155
+ </SelectContent>
156
+ </Select>
157
+ </div>
158
+ </div>
159
+ </form>
160
+ </CardContent>
161
+ <CardFooter className="flex justify-between">
162
+ <Button variant="outline">Cancel</Button>
163
+ <Button>Deploy</Button>
164
+ </CardFooter>
165
+ </Card>
166
+ );
167
+ }
168
+
169
+ // Input component
170
+ import { Input } from "@/components/ui/input";
171
+ import { Label } from "@/components/ui/label";
172
+
173
+ export function InputWithLabel() {
174
+ return (
175
+ <div className="grid w-full max-w-sm items-center gap-1.5">
176
+ <Label htmlFor="email">Email</Label>
177
+ <Input type="email" id="email" placeholder="Email" />
178
+ </div>
179
+ );
180
+ }
181
+
182
+ export function InputWithButton() {
183
+ return (
184
+ <div className="flex w-full max-w-sm items-center space-x-2">
185
+ <Input type="email" placeholder="Email" />
186
+ <Button type="submit">Subscribe</Button>
187
+ </div>
188
+ );
189
+ }
32
190
  ```
33
191
 
34
- ## Form Pattern
192
+ ### 3. Form Integration with React Hook Form
193
+
35
194
  ```tsx
36
- import { useForm } from "react-hook-form"
37
- import { Form, FormField, FormItem, FormLabel, FormControl } from "@/components/ui/form"
38
-
39
- <Form {...form}>
40
- <FormField
41
- control={form.control}
42
- name="email"
43
- render={({ field }) => (
44
- <FormItem>
45
- <FormLabel>Email</FormLabel>
46
- <FormControl>
47
- <Input {...field} />
48
- </FormControl>
49
- </FormItem>
50
- )}
51
- />
52
- </Form>
195
+ // Complete form example with validation
196
+ "use client";
197
+
198
+ import { zodResolver } from "@hookform/resolvers/zod";
199
+ import { useForm } from "react-hook-form";
200
+ import * as z from "zod";
201
+
202
+ import { Button } from "@/components/ui/button";
203
+ import {
204
+ Form,
205
+ FormControl,
206
+ FormDescription,
207
+ FormField,
208
+ FormItem,
209
+ FormLabel,
210
+ FormMessage,
211
+ } from "@/components/ui/form";
212
+ import { Input } from "@/components/ui/input";
213
+ import {
214
+ Select,
215
+ SelectContent,
216
+ SelectItem,
217
+ SelectTrigger,
218
+ SelectValue,
219
+ } from "@/components/ui/select";
220
+ import { Textarea } from "@/components/ui/textarea";
221
+ import { Checkbox } from "@/components/ui/checkbox";
222
+ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
223
+ import { Switch } from "@/components/ui/switch";
224
+ import { toast } from "@/components/ui/use-toast";
225
+
226
+ const formSchema = z.object({
227
+ username: z
228
+ .string()
229
+ .min(2, "Username must be at least 2 characters.")
230
+ .max(30, "Username must not exceed 30 characters."),
231
+ email: z.string().email("Please enter a valid email address."),
232
+ bio: z
233
+ .string()
234
+ .max(160, "Bio must not exceed 160 characters.")
235
+ .optional(),
236
+ role: z.enum(["admin", "user", "guest"], {
237
+ required_error: "Please select a role.",
238
+ }),
239
+ notifications: z.boolean().default(false),
240
+ marketingEmails: z.boolean().default(false),
241
+ securityEmails: z.boolean().default(true),
242
+ communicationMethod: z.enum(["email", "sms", "push"], {
243
+ required_error: "Please select a communication method.",
244
+ }),
245
+ });
246
+
247
+ type FormData = z.infer<typeof formSchema>;
248
+
249
+ export function ProfileForm() {
250
+ const form = useForm<FormData>({
251
+ resolver: zodResolver(formSchema),
252
+ defaultValues: {
253
+ username: "",
254
+ email: "",
255
+ bio: "",
256
+ notifications: false,
257
+ marketingEmails: false,
258
+ securityEmails: true,
259
+ },
260
+ });
261
+
262
+ async function onSubmit(data: FormData) {
263
+ try {
264
+ // API call here
265
+ console.log(data);
266
+ toast({
267
+ title: "Profile updated",
268
+ description: "Your profile has been updated successfully.",
269
+ });
270
+ } catch (error) {
271
+ toast({
272
+ title: "Error",
273
+ description: "Something went wrong. Please try again.",
274
+ variant: "destructive",
275
+ });
276
+ }
277
+ }
278
+
279
+ return (
280
+ <Form {...form}>
281
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
282
+ <FormField
283
+ control={form.control}
284
+ name="username"
285
+ render={({ field }) => (
286
+ <FormItem>
287
+ <FormLabel>Username</FormLabel>
288
+ <FormControl>
289
+ <Input placeholder="johndoe" {...field} />
290
+ </FormControl>
291
+ <FormDescription>
292
+ This is your public display name.
293
+ </FormDescription>
294
+ <FormMessage />
295
+ </FormItem>
296
+ )}
297
+ />
298
+
299
+ <FormField
300
+ control={form.control}
301
+ name="email"
302
+ render={({ field }) => (
303
+ <FormItem>
304
+ <FormLabel>Email</FormLabel>
305
+ <FormControl>
306
+ <Input type="email" placeholder="john@example.com" {...field} />
307
+ </FormControl>
308
+ <FormMessage />
309
+ </FormItem>
310
+ )}
311
+ />
312
+
313
+ <FormField
314
+ control={form.control}
315
+ name="bio"
316
+ render={({ field }) => (
317
+ <FormItem>
318
+ <FormLabel>Bio</FormLabel>
319
+ <FormControl>
320
+ <Textarea
321
+ placeholder="Tell us a little about yourself"
322
+ className="resize-none"
323
+ {...field}
324
+ />
325
+ </FormControl>
326
+ <FormDescription>
327
+ You can @mention other users and organizations.
328
+ </FormDescription>
329
+ <FormMessage />
330
+ </FormItem>
331
+ )}
332
+ />
333
+
334
+ <FormField
335
+ control={form.control}
336
+ name="role"
337
+ render={({ field }) => (
338
+ <FormItem>
339
+ <FormLabel>Role</FormLabel>
340
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
341
+ <FormControl>
342
+ <SelectTrigger>
343
+ <SelectValue placeholder="Select a role" />
344
+ </SelectTrigger>
345
+ </FormControl>
346
+ <SelectContent>
347
+ <SelectItem value="admin">Admin</SelectItem>
348
+ <SelectItem value="user">User</SelectItem>
349
+ <SelectItem value="guest">Guest</SelectItem>
350
+ </SelectContent>
351
+ </Select>
352
+ <FormMessage />
353
+ </FormItem>
354
+ )}
355
+ />
356
+
357
+ <FormField
358
+ control={form.control}
359
+ name="communicationMethod"
360
+ render={({ field }) => (
361
+ <FormItem className="space-y-3">
362
+ <FormLabel>Notify me via</FormLabel>
363
+ <FormControl>
364
+ <RadioGroup
365
+ onValueChange={field.onChange}
366
+ defaultValue={field.value}
367
+ className="flex flex-col space-y-1"
368
+ >
369
+ <FormItem className="flex items-center space-x-3 space-y-0">
370
+ <FormControl>
371
+ <RadioGroupItem value="email" />
372
+ </FormControl>
373
+ <FormLabel className="font-normal">Email</FormLabel>
374
+ </FormItem>
375
+ <FormItem className="flex items-center space-x-3 space-y-0">
376
+ <FormControl>
377
+ <RadioGroupItem value="sms" />
378
+ </FormControl>
379
+ <FormLabel className="font-normal">SMS</FormLabel>
380
+ </FormItem>
381
+ <FormItem className="flex items-center space-x-3 space-y-0">
382
+ <FormControl>
383
+ <RadioGroupItem value="push" />
384
+ </FormControl>
385
+ <FormLabel className="font-normal">Push notification</FormLabel>
386
+ </FormItem>
387
+ </RadioGroup>
388
+ </FormControl>
389
+ <FormMessage />
390
+ </FormItem>
391
+ )}
392
+ />
393
+
394
+ <div className="space-y-4">
395
+ <FormField
396
+ control={form.control}
397
+ name="notifications"
398
+ render={({ field }) => (
399
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
400
+ <div className="space-y-0.5">
401
+ <FormLabel className="text-base">Push Notifications</FormLabel>
402
+ <FormDescription>
403
+ Receive push notifications on your device.
404
+ </FormDescription>
405
+ </div>
406
+ <FormControl>
407
+ <Switch
408
+ checked={field.value}
409
+ onCheckedChange={field.onChange}
410
+ />
411
+ </FormControl>
412
+ </FormItem>
413
+ )}
414
+ />
415
+
416
+ <FormField
417
+ control={form.control}
418
+ name="marketingEmails"
419
+ render={({ field }) => (
420
+ <FormItem className="flex flex-row items-start space-x-3 space-y-0">
421
+ <FormControl>
422
+ <Checkbox
423
+ checked={field.value}
424
+ onCheckedChange={field.onChange}
425
+ />
426
+ </FormControl>
427
+ <div className="space-y-1 leading-none">
428
+ <FormLabel>Marketing emails</FormLabel>
429
+ <FormDescription>
430
+ Receive emails about new products and features.
431
+ </FormDescription>
432
+ </div>
433
+ </FormItem>
434
+ )}
435
+ />
436
+ </div>
437
+
438
+ <Button type="submit" disabled={form.formState.isSubmitting}>
439
+ {form.formState.isSubmitting ? "Saving..." : "Save changes"}
440
+ </Button>
441
+ </form>
442
+ </Form>
443
+ );
444
+ }
445
+ ```
446
+
447
+ ### 4. Dialog and Modals
448
+
449
+ ```tsx
450
+ // Dialog component
451
+ import {
452
+ Dialog,
453
+ DialogContent,
454
+ DialogDescription,
455
+ DialogFooter,
456
+ DialogHeader,
457
+ DialogTitle,
458
+ DialogTrigger,
459
+ DialogClose,
460
+ } from "@/components/ui/dialog";
461
+
462
+ export function DialogExample() {
463
+ return (
464
+ <Dialog>
465
+ <DialogTrigger asChild>
466
+ <Button variant="outline">Edit Profile</Button>
467
+ </DialogTrigger>
468
+ <DialogContent className="sm:max-w-[425px]">
469
+ <DialogHeader>
470
+ <DialogTitle>Edit profile</DialogTitle>
471
+ <DialogDescription>
472
+ Make changes to your profile here. Click save when you're done.
473
+ </DialogDescription>
474
+ </DialogHeader>
475
+ <div className="grid gap-4 py-4">
476
+ <div className="grid grid-cols-4 items-center gap-4">
477
+ <Label htmlFor="name" className="text-right">
478
+ Name
479
+ </Label>
480
+ <Input
481
+ id="name"
482
+ defaultValue="Pedro Duarte"
483
+ className="col-span-3"
484
+ />
485
+ </div>
486
+ <div className="grid grid-cols-4 items-center gap-4">
487
+ <Label htmlFor="username" className="text-right">
488
+ Username
489
+ </Label>
490
+ <Input
491
+ id="username"
492
+ defaultValue="@peduarte"
493
+ className="col-span-3"
494
+ />
495
+ </div>
496
+ </div>
497
+ <DialogFooter>
498
+ <DialogClose asChild>
499
+ <Button variant="outline">Cancel</Button>
500
+ </DialogClose>
501
+ <Button type="submit">Save changes</Button>
502
+ </DialogFooter>
503
+ </DialogContent>
504
+ </Dialog>
505
+ );
506
+ }
507
+
508
+ // Alert Dialog for confirmations
509
+ import {
510
+ AlertDialog,
511
+ AlertDialogAction,
512
+ AlertDialogCancel,
513
+ AlertDialogContent,
514
+ AlertDialogDescription,
515
+ AlertDialogFooter,
516
+ AlertDialogHeader,
517
+ AlertDialogTitle,
518
+ AlertDialogTrigger,
519
+ } from "@/components/ui/alert-dialog";
520
+
521
+ export function DeleteConfirmation({ onDelete }: { onDelete: () => void }) {
522
+ return (
523
+ <AlertDialog>
524
+ <AlertDialogTrigger asChild>
525
+ <Button variant="destructive">Delete</Button>
526
+ </AlertDialogTrigger>
527
+ <AlertDialogContent>
528
+ <AlertDialogHeader>
529
+ <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
530
+ <AlertDialogDescription>
531
+ This action cannot be undone. This will permanently delete your
532
+ account and remove your data from our servers.
533
+ </AlertDialogDescription>
534
+ </AlertDialogHeader>
535
+ <AlertDialogFooter>
536
+ <AlertDialogCancel>Cancel</AlertDialogCancel>
537
+ <AlertDialogAction onClick={onDelete}>
538
+ Yes, delete account
539
+ </AlertDialogAction>
540
+ </AlertDialogFooter>
541
+ </AlertDialogContent>
542
+ </AlertDialog>
543
+ );
544
+ }
545
+
546
+ // Sheet (slide-out panel)
547
+ import {
548
+ Sheet,
549
+ SheetClose,
550
+ SheetContent,
551
+ SheetDescription,
552
+ SheetFooter,
553
+ SheetHeader,
554
+ SheetTitle,
555
+ SheetTrigger,
556
+ } from "@/components/ui/sheet";
557
+
558
+ export function SheetExample() {
559
+ return (
560
+ <Sheet>
561
+ <SheetTrigger asChild>
562
+ <Button variant="outline">Open Settings</Button>
563
+ </SheetTrigger>
564
+ <SheetContent>
565
+ <SheetHeader>
566
+ <SheetTitle>Edit settings</SheetTitle>
567
+ <SheetDescription>
568
+ Make changes to your settings here.
569
+ </SheetDescription>
570
+ </SheetHeader>
571
+ <div className="grid gap-4 py-4">
572
+ {/* Form fields */}
573
+ </div>
574
+ <SheetFooter>
575
+ <SheetClose asChild>
576
+ <Button type="submit">Save changes</Button>
577
+ </SheetClose>
578
+ </SheetFooter>
579
+ </SheetContent>
580
+ </Sheet>
581
+ );
582
+ }
583
+ ```
584
+
585
+ ### 5. Data Display Components
586
+
587
+ ```tsx
588
+ // Table component
589
+ import {
590
+ Table,
591
+ TableBody,
592
+ TableCaption,
593
+ TableCell,
594
+ TableHead,
595
+ TableHeader,
596
+ TableRow,
597
+ } from "@/components/ui/table";
598
+
599
+ interface Invoice {
600
+ id: string;
601
+ paymentStatus: string;
602
+ totalAmount: number;
603
+ paymentMethod: string;
604
+ }
605
+
606
+ export function DataTable({ invoices }: { invoices: Invoice[] }) {
607
+ return (
608
+ <Table>
609
+ <TableCaption>A list of your recent invoices.</TableCaption>
610
+ <TableHeader>
611
+ <TableRow>
612
+ <TableHead className="w-[100px]">Invoice</TableHead>
613
+ <TableHead>Status</TableHead>
614
+ <TableHead>Method</TableHead>
615
+ <TableHead className="text-right">Amount</TableHead>
616
+ </TableRow>
617
+ </TableHeader>
618
+ <TableBody>
619
+ {invoices.map((invoice) => (
620
+ <TableRow key={invoice.id}>
621
+ <TableCell className="font-medium">{invoice.id}</TableCell>
622
+ <TableCell>
623
+ <Badge
624
+ variant={
625
+ invoice.paymentStatus === "paid" ? "default" : "secondary"
626
+ }
627
+ >
628
+ {invoice.paymentStatus}
629
+ </Badge>
630
+ </TableCell>
631
+ <TableCell>{invoice.paymentMethod}</TableCell>
632
+ <TableCell className="text-right">
633
+ ${invoice.totalAmount.toFixed(2)}
634
+ </TableCell>
635
+ </TableRow>
636
+ ))}
637
+ </TableBody>
638
+ </Table>
639
+ );
640
+ }
641
+
642
+ // Tabs component
643
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
644
+
645
+ export function TabsExample() {
646
+ return (
647
+ <Tabs defaultValue="account" className="w-[400px]">
648
+ <TabsList className="grid w-full grid-cols-2">
649
+ <TabsTrigger value="account">Account</TabsTrigger>
650
+ <TabsTrigger value="password">Password</TabsTrigger>
651
+ </TabsList>
652
+ <TabsContent value="account">
653
+ <Card>
654
+ <CardHeader>
655
+ <CardTitle>Account</CardTitle>
656
+ <CardDescription>
657
+ Make changes to your account here.
658
+ </CardDescription>
659
+ </CardHeader>
660
+ <CardContent className="space-y-2">
661
+ <div className="space-y-1">
662
+ <Label htmlFor="name">Name</Label>
663
+ <Input id="name" defaultValue="Pedro Duarte" />
664
+ </div>
665
+ <div className="space-y-1">
666
+ <Label htmlFor="username">Username</Label>
667
+ <Input id="username" defaultValue="@peduarte" />
668
+ </div>
669
+ </CardContent>
670
+ <CardFooter>
671
+ <Button>Save changes</Button>
672
+ </CardFooter>
673
+ </Card>
674
+ </TabsContent>
675
+ <TabsContent value="password">
676
+ <Card>
677
+ <CardHeader>
678
+ <CardTitle>Password</CardTitle>
679
+ <CardDescription>Change your password here.</CardDescription>
680
+ </CardHeader>
681
+ <CardContent className="space-y-2">
682
+ <div className="space-y-1">
683
+ <Label htmlFor="current">Current password</Label>
684
+ <Input id="current" type="password" />
685
+ </div>
686
+ <div className="space-y-1">
687
+ <Label htmlFor="new">New password</Label>
688
+ <Input id="new" type="password" />
689
+ </div>
690
+ </CardContent>
691
+ <CardFooter>
692
+ <Button>Save password</Button>
693
+ </CardFooter>
694
+ </Card>
695
+ </TabsContent>
696
+ </Tabs>
697
+ );
698
+ }
699
+ ```
700
+
701
+ ### 6. Navigation Components
702
+
703
+ ```tsx
704
+ // Dropdown Menu
705
+ import {
706
+ DropdownMenu,
707
+ DropdownMenuContent,
708
+ DropdownMenuItem,
709
+ DropdownMenuLabel,
710
+ DropdownMenuSeparator,
711
+ DropdownMenuShortcut,
712
+ DropdownMenuTrigger,
713
+ DropdownMenuSub,
714
+ DropdownMenuSubContent,
715
+ DropdownMenuSubTrigger,
716
+ } from "@/components/ui/dropdown-menu";
717
+
718
+ export function UserMenu() {
719
+ return (
720
+ <DropdownMenu>
721
+ <DropdownMenuTrigger asChild>
722
+ <Button variant="ghost" className="relative h-8 w-8 rounded-full">
723
+ <Avatar className="h-8 w-8">
724
+ <AvatarImage src="/avatars/01.png" alt="@username" />
725
+ <AvatarFallback>JD</AvatarFallback>
726
+ </Avatar>
727
+ </Button>
728
+ </DropdownMenuTrigger>
729
+ <DropdownMenuContent className="w-56" align="end" forceMount>
730
+ <DropdownMenuLabel className="font-normal">
731
+ <div className="flex flex-col space-y-1">
732
+ <p className="text-sm font-medium leading-none">John Doe</p>
733
+ <p className="text-xs leading-none text-muted-foreground">
734
+ john@example.com
735
+ </p>
736
+ </div>
737
+ </DropdownMenuLabel>
738
+ <DropdownMenuSeparator />
739
+ <DropdownMenuItem>
740
+ <User className="mr-2 h-4 w-4" />
741
+ Profile
742
+ <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
743
+ </DropdownMenuItem>
744
+ <DropdownMenuItem>
745
+ <Settings className="mr-2 h-4 w-4" />
746
+ Settings
747
+ <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
748
+ </DropdownMenuItem>
749
+ <DropdownMenuSeparator />
750
+ <DropdownMenuItem className="text-red-600">
751
+ <LogOut className="mr-2 h-4 w-4" />
752
+ Log out
753
+ <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
754
+ </DropdownMenuItem>
755
+ </DropdownMenuContent>
756
+ </DropdownMenu>
757
+ );
758
+ }
759
+
760
+ // Command Menu (CMD+K)
761
+ import {
762
+ CommandDialog,
763
+ CommandEmpty,
764
+ CommandGroup,
765
+ CommandInput,
766
+ CommandItem,
767
+ CommandList,
768
+ CommandSeparator,
769
+ CommandShortcut,
770
+ } from "@/components/ui/command";
771
+
772
+ export function CommandMenu() {
773
+ const [open, setOpen] = useState(false);
774
+
775
+ useEffect(() => {
776
+ const down = (e: KeyboardEvent) => {
777
+ if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
778
+ e.preventDefault();
779
+ setOpen((open) => !open);
780
+ }
781
+ };
782
+
783
+ document.addEventListener("keydown", down);
784
+ return () => document.removeEventListener("keydown", down);
785
+ }, []);
786
+
787
+ return (
788
+ <CommandDialog open={open} onOpenChange={setOpen}>
789
+ <CommandInput placeholder="Type a command or search..." />
790
+ <CommandList>
791
+ <CommandEmpty>No results found.</CommandEmpty>
792
+ <CommandGroup heading="Suggestions">
793
+ <CommandItem>
794
+ <Calendar className="mr-2 h-4 w-4" />
795
+ Calendar
796
+ </CommandItem>
797
+ <CommandItem>
798
+ <Search className="mr-2 h-4 w-4" />
799
+ Search
800
+ </CommandItem>
801
+ </CommandGroup>
802
+ <CommandSeparator />
803
+ <CommandGroup heading="Settings">
804
+ <CommandItem>
805
+ <User className="mr-2 h-4 w-4" />
806
+ Profile
807
+ <CommandShortcut>⌘P</CommandShortcut>
808
+ </CommandItem>
809
+ <CommandItem>
810
+ <Settings className="mr-2 h-4 w-4" />
811
+ Settings
812
+ <CommandShortcut>⌘S</CommandShortcut>
813
+ </CommandItem>
814
+ </CommandGroup>
815
+ </CommandList>
816
+ </CommandDialog>
817
+ );
818
+ }
819
+ ```
820
+
821
+ ### 7. Toast Notifications
822
+
823
+ ```tsx
824
+ // Toast setup and usage
825
+ // components/ui/toaster.tsx
826
+ "use client";
827
+
828
+ import {
829
+ Toast,
830
+ ToastClose,
831
+ ToastDescription,
832
+ ToastProvider,
833
+ ToastTitle,
834
+ ToastViewport,
835
+ } from "@/components/ui/toast";
836
+ import { useToast } from "@/components/ui/use-toast";
837
+
838
+ export function Toaster() {
839
+ const { toasts } = useToast();
840
+
841
+ return (
842
+ <ToastProvider>
843
+ {toasts.map(function ({ id, title, description, action, ...props }) {
844
+ return (
845
+ <Toast key={id} {...props}>
846
+ <div className="grid gap-1">
847
+ {title && <ToastTitle>{title}</ToastTitle>}
848
+ {description && (
849
+ <ToastDescription>{description}</ToastDescription>
850
+ )}
851
+ </div>
852
+ {action}
853
+ <ToastClose />
854
+ </Toast>
855
+ );
856
+ })}
857
+ <ToastViewport />
858
+ </ToastProvider>
859
+ );
860
+ }
861
+
862
+ // Usage in components
863
+ import { useToast } from "@/components/ui/use-toast";
864
+ import { ToastAction } from "@/components/ui/toast";
865
+
866
+ export function ToastDemo() {
867
+ const { toast } = useToast();
868
+
869
+ return (
870
+ <div className="space-x-4">
871
+ <Button
872
+ onClick={() => {
873
+ toast({
874
+ title: "Success!",
875
+ description: "Your changes have been saved.",
876
+ });
877
+ }}
878
+ >
879
+ Show Toast
880
+ </Button>
881
+
882
+ <Button
883
+ variant="destructive"
884
+ onClick={() => {
885
+ toast({
886
+ variant: "destructive",
887
+ title: "Uh oh! Something went wrong.",
888
+ description: "There was a problem with your request.",
889
+ action: <ToastAction altText="Try again">Try again</ToastAction>,
890
+ });
891
+ }}
892
+ >
893
+ Show Error Toast
894
+ </Button>
895
+ </div>
896
+ );
897
+ }
898
+ ```
899
+
900
+ ## Use Cases
901
+
902
+ ### Complete Dashboard Page
903
+
904
+ ```tsx
905
+ // app/dashboard/page.tsx
906
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
907
+ import { DataTable } from "@/components/data-table";
908
+ import { UserMenu } from "@/components/user-menu";
909
+
910
+ export default function DashboardPage() {
911
+ return (
912
+ <div className="flex min-h-screen flex-col">
913
+ <header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
914
+ <div className="container flex h-14 items-center">
915
+ <div className="mr-4 flex">
916
+ <a className="mr-6 flex items-center space-x-2" href="/">
917
+ <span className="font-bold">Dashboard</span>
918
+ </a>
919
+ </div>
920
+ <div className="flex flex-1 items-center justify-end space-x-2">
921
+ <UserMenu />
922
+ </div>
923
+ </div>
924
+ </header>
925
+
926
+ <main className="flex-1 space-y-4 p-8 pt-6">
927
+ <div className="flex items-center justify-between space-y-2">
928
+ <h2 className="text-3xl font-bold tracking-tight">Dashboard</h2>
929
+ <Button>Download Report</Button>
930
+ </div>
931
+
932
+ <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
933
+ <Card>
934
+ <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
935
+ <CardTitle className="text-sm font-medium">Total Revenue</CardTitle>
936
+ <DollarSign className="h-4 w-4 text-muted-foreground" />
937
+ </CardHeader>
938
+ <CardContent>
939
+ <div className="text-2xl font-bold">$45,231.89</div>
940
+ <p className="text-xs text-muted-foreground">
941
+ +20.1% from last month
942
+ </p>
943
+ </CardContent>
944
+ </Card>
945
+ {/* More cards... */}
946
+ </div>
947
+
948
+ <Card>
949
+ <CardHeader>
950
+ <CardTitle>Recent Orders</CardTitle>
951
+ </CardHeader>
952
+ <CardContent>
953
+ <DataTable />
954
+ </CardContent>
955
+ </Card>
956
+ </main>
957
+ </div>
958
+ );
959
+ }
53
960
  ```
54
961
 
55
962
  ## Best Practices
963
+
964
+ ### Do's
965
+
966
+ - Install only components you need
967
+ - Use the cn() utility for class merging
968
+ - Extend components with composition
969
+ - Follow form validation patterns
970
+ - Use proper ARIA attributes
56
971
  - Customize via CSS variables
57
- - Use with React Hook Form
58
- - Extend components as needed
972
+ - Keep components accessible
973
+ - Use TypeScript for type safety
974
+ - Follow React Hook Form patterns
975
+ - Test component accessibility
976
+
977
+ ### Don'ts
978
+
979
+ - Don't modify generated component files directly
980
+ - Don't skip form validation
981
+ - Don't ignore accessibility features
982
+ - Don't override styles without reason
983
+ - Don't use inline styles
984
+ - Don't skip loading states
985
+ - Don't ignore error handling
986
+ - Don't hardcode text strings
987
+ - Don't skip responsive testing
988
+ - Don't ignore keyboard navigation
989
+
990
+ ## References
991
+
992
+ - [shadcn/ui Documentation](https://ui.shadcn.com/)
993
+ - [Radix UI Primitives](https://www.radix-ui.com/)
994
+ - [React Hook Form](https://react-hook-form.com/)
995
+ - [Zod Validation](https://zod.dev/)
996
+ - [Tailwind CSS](https://tailwindcss.com/)