โ† All skills
Tencent SkillHub ยท Developer Tools

Shadcn UI

Build accessible, customizable UIs with shadcn/ui, Radix UI, and Tailwind CSS. Use when setting up shadcn/ui, installing components, building forms with React Hook Form + Zod, customizing themes, or implementing component patterns.

skill openclawclawhub Free
0 Downloads
0 Stars
0 Installs
0 Score
High Signal

Build accessible, customizable UIs with shadcn/ui, Radix UI, and Tailwind CSS. Use when setting up shadcn/ui, installing components, building forms with React Hook Form + Zod, customizing themes, or implementing component patterns.

โฌ‡ 0 downloads โ˜… 0 stars Unverified but indexed

Install for OpenClaw

Quick setup
  1. Download the package from Yavira.
  2. Extract the archive and review SKILL.md first.
  3. Import or place the package into your OpenClaw setup.

Requirements

Target platform
OpenClaw
Install method
Manual import
Extraction
Extract archive
Prerequisites
OpenClaw
Primary doc
SKILL.md

Package facts

Download mode
Yavira redirect
Package format
ZIP package
Source platform
Tencent SkillHub
What's included
README.md, SKILL.md, references/learn.md, references/extended-components.md

Validation

  • Use the Yavira download entry.
  • Review SKILL.md after the package is downloaded.
  • Confirm the extracted package contains the expected setup assets.

Install with your agent

Agent handoff

Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.

  1. Download the package from Yavira.
  2. Extract it into a folder your agent can access.
  3. Paste one of the prompts below and point your agent at the extracted folder.
New install

I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.

Upgrade existing

I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.

Trust & source

Release facts

Source
Tencent SkillHub
Verification
Indexed source record
Version
1.0.0

Documentation

ClawHub primary doc Primary doc: SKILL.md 23 sections Open source page

shadcn/ui Component Patterns

Expert guide for building accessible, customizable UI components with shadcn/ui.

OpenClaw / Moltbot / Clawbot

npx clawhub@latest install shadcn-ui

WHEN

Setting up a new project with shadcn/ui Installing or configuring individual components Building forms with React Hook Form and Zod validation Creating accessible UI components (buttons, dialogs, dropdowns, sheets) Customizing component styling with Tailwind CSS Implementing design systems with shadcn/ui Building Next.js applications with TypeScript

What is shadcn/ui?

A collection of reusable components you copy into your project โ€” not an npm package. You own the code. Built on Radix UI (accessibility) and Tailwind CSS (styling).

Quick Start

# New Next.js project npx create-next-app@latest my-app --typescript --tailwind --eslint --app cd my-app npx shadcn@latest init # Install components npx shadcn@latest add button input form card dialog select toast npx shadcn@latest add --all # or install everything

The cn Utility

Merges Tailwind classes with conflict resolution โ€” used in every component: import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) }

Class Variance Authority (CVA)

Manages component variants โ€” the pattern behind every shadcn/ui component: import { cva, type VariantProps } from "class-variance-authority" const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input bg-background hover:bg-accent", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default" }, } )

Button

import { Button } from "@/components/ui/button" import { Loader2 } from "lucide-react" // Variants: default | destructive | outline | secondary | ghost | link // Sizes: default | sm | lg | icon <Button variant="outline" size="sm">Click me</Button> // Loading state <Button disabled> <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Please wait </Button> // As link (uses Radix Slot) <Button asChild> <a href="/dashboard">Go to Dashboard</a> </Button>

Forms with Validation

The standard pattern: Zod schema + React Hook Form + shadcn Form components. npx shadcn@latest add form input select checkbox textarea "use client" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import * as z from "zod" import { Button } from "@/components/ui/button" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" const formSchema = z.object({ username: z.string().min(2, "Username must be at least 2 characters."), email: z.string().email("Please enter a valid email."), role: z.enum(["admin", "user", "guest"]), }) export function ProfileForm() { const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { username: "", email: "", role: "user" }, }) function onSubmit(values: z.infer<typeof formSchema>) { console.log(values) } return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> <FormField control={form.control} name="username" render={({ field }) => ( <FormItem> <FormLabel>Username</FormLabel> <FormControl><Input placeholder="shadcn" {...field} /></FormControl> <FormDescription>Your public display name.</FormDescription> <FormMessage /> </FormItem> )} /> <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl><Input type="email" {...field} /></FormControl> <FormMessage /> </FormItem> )} /> <FormField control={form.control} name="role" render={({ field }) => ( <FormItem> <FormLabel>Role</FormLabel> <Select onValueChange={field.onChange} defaultValue={field.value}> <FormControl> <SelectTrigger><SelectValue placeholder="Select a role" /></SelectTrigger> </FormControl> <SelectContent> <SelectItem value="admin">Admin</SelectItem> <SelectItem value="user">User</SelectItem> <SelectItem value="guest">Guest</SelectItem> </SelectContent> </Select> <FormMessage /> </FormItem> )} /> <Button type="submit">Submit</Button> </form> </Form> ) }

Dialog & Sheet

import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet" // Modal dialog <Dialog> <DialogTrigger asChild><Button variant="outline">Edit profile</Button></DialogTrigger> <DialogContent className="sm:max-w-[425px]"> <DialogHeader> <DialogTitle>Edit profile</DialogTitle> <DialogDescription>Make changes here. Click save when done.</DialogDescription> </DialogHeader> <div className="grid gap-4 py-4">{/* form fields */}</div> <DialogFooter><Button type="submit">Save changes</Button></DialogFooter> </DialogContent> </Dialog> // Slide-over panel (side: "left" | "right" | "top" | "bottom") <Sheet> <SheetTrigger asChild><Button variant="outline">Open</Button></SheetTrigger> <SheetContent side="right"> <SheetHeader><SheetTitle>Settings</SheetTitle></SheetHeader> {/* content */} </SheetContent> </Sheet>

Card

import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" <Card className="w-[350px]"> <CardHeader> <CardTitle>Create project</CardTitle> <CardDescription>Deploy your new project in one-click.</CardDescription> </CardHeader> <CardContent> <div className="grid w-full items-center gap-4"> <div className="flex flex-col space-y-1.5"> <Label htmlFor="name">Name</Label> <Input id="name" placeholder="Project name" /> </div> </div> </CardContent> <CardFooter className="flex justify-between"> <Button variant="outline">Cancel</Button> <Button>Deploy</Button> </CardFooter> </Card>

Toast Notifications

// 1. Add Toaster to root layout import { Toaster } from "@/components/ui/toaster" export default function RootLayout({ children }) { return ( <html lang="en"> <body>{children}<Toaster /></body> </html> ) } // 2. Use toast in components import { useToast } from "@/components/ui/use-toast" import { ToastAction } from "@/components/ui/toast" const { toast } = useToast() toast({ title: "Success", description: "Changes saved." }) toast({ variant: "destructive", title: "Error", description: "Something went wrong.", action: <ToastAction altText="Try again">Try again</ToastAction>, })

Table

import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" const invoices = [ { invoice: "INV001", status: "Paid", method: "Credit Card", amount: "$250.00" }, { invoice: "INV002", status: "Pending", method: "PayPal", amount: "$150.00" }, ] <Table> <TableCaption>A list of your recent invoices.</TableCaption> <TableHeader> <TableRow> <TableHead>Invoice</TableHead> <TableHead>Status</TableHead> <TableHead>Method</TableHead> <TableHead className="text-right">Amount</TableHead> </TableRow> </TableHeader> <TableBody> {invoices.map((invoice) => ( <TableRow key={invoice.invoice}> <TableCell className="font-medium">{invoice.invoice}</TableCell> <TableCell>{invoice.status}</TableCell> <TableCell>{invoice.method}</TableCell> <TableCell className="text-right">{invoice.amount}</TableCell> </TableRow> ))} </TableBody> </Table>

Theming

shadcn/ui uses CSS variables in HSL format. Configure in globals.css: @layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --destructive: 0 84.2% 60.2%; --border: 214.3 31.8% 91.4%; --ring: 222.2 84% 4.9%; --radius: 0.5rem; } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 11.2%; /* ... mirror all variables for dark mode */ } } Colors reference as hsl(var(--primary)) in Tailwind config. Change the CSS variables to retheme the entire app.

Customizing Components

Since you own the code, modify components directly: // Add a custom variant to button.tsx const buttonVariants = cva("...", { variants: { variant: { // ... existing variants gradient: "bg-gradient-to-r from-purple-500 to-pink-500 text-white", }, size: { // ... existing sizes xl: "h-14 rounded-md px-10 text-lg", }, }, })

Component Reference

ComponentInstallKey PropsButtonadd buttonvariant, size, asChildInputadd inputStandard HTML input propsFormadd formReact Hook Form + Zod integrationCardadd cardHeader, Content, Footer compositionDialogadd dialogModal with trigger patternSheetadd sheetSlide-over panel, side propSelectadd selectAccessible dropdownToastadd toastvariant: "default" | "destructive"Tableadd tableHeader, Body, Row, Cell compositionTabsadd tabsdefaultValue, trigger/content pairsAccordionadd accordiontype: "single" | "multiple"Commandadd commandCommand palette / searchDropdown Menuadd dropdown-menuContext menus, action menusMenubaradd menubarApplication menus with shortcuts

App Router Setup

For Next.js 13+ with App Router, ensure interactive components use "use client": // src/components/ui/button.tsx "use client" import * as React from "react" import { Slot } from "@radix-ui/react-slot" // ... rest of component

Layout Integration

Add the Toaster to your root layout: // app/layout.tsx import { Toaster } from "@/components/ui/toaster" import "./globals.css" export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" suppressHydrationWarning> <body className="min-h-screen bg-background font-sans antialiased"> {children} <Toaster /> </body> </html> ) }

Server Components

Most shadcn/ui components need "use client". For Server Components, wrap them in a client component or use them in client component children.

CLI Reference

npx shadcn@latest init # Initialize project npx shadcn@latest add [component] # Add specific component npx shadcn@latest add --all # Add all components npx shadcn@latest diff # Show upstream changes

Best Practices

PracticeDetailsUse TypeScriptAll components ship with full type definitionsZod for validationPair with React Hook Form for type-safe formsasChild patternUse Radix Slot to render as different elementsServer ComponentsMost shadcn/ui components need "use client"Consistent structureFollow the existing component patterns when customizingAccessibilityRadix primitives handle ARIA; don't override without reasonCSS variablesTheme via variables, not by editing component classesTree-shakingOnly install components you need โ€” they're independent

NEVER Do

NeverWhyInsteadInstall shadcn as npm packageIt's not a package โ€” it's source code you ownUse CLI: npx shadcn@latest addOverride ARIA attributesRadix handles accessibility correctlyTrust the primitivesUse inline styles for themingDefeats the design systemModify CSS variablesCopy components from docs manuallyMay miss dependenciesUse CLI for proper installationMix component stylesCreates inconsistencyFollow CVA variant pattern

References

Learning Guide โ€” progression from basics to advanced patterns Extended Components โ€” Terminal, Dock, Charts, animations, custom hooks Official Docs | Radix UI | React Hook Form | Zod

Category context

Code helpers, APIs, CLIs, browser automation, testing, and developer operations.

Source: Tencent SkillHub

Largest current source with strong distribution and engagement signals.

Package contents

Included in package
4 Docs
  • SKILL.md Primary doc
  • README.md Docs
  • references/extended-components.md Docs
  • references/learn.md Docs