shadcn-ui: 使用 Tailwind 构建无障碍 React UI - Openclaw Skills

作者:互联网

2026-03-26

AI教程

什么是 shadcn-ui?

shadcn-ui 技能使开发人员能够利用一系列可重用组件构建专业级的用户界面。与传统的组件库不同,此技能专注于你可以拥有并直接在项目中修改的组件。它与 Radix UI 无缝集成以实现强大的无障碍功能,并与 Tailwind CSS 集成以实现快速样式设计。此 Openclaw Skills 实现简化了支架化 Next.js 应用程序的过程,通过 Class Variance Authority (CVA) 管理组件变体,并使用 TypeScript 确保类型安全。

通过使用此技能,开发人员可以在保持对 UI 代码完全控制的同时,受益于表单、模态框和导航的行业标准模式。它弥补了开箱即用组件与定制设计系统之间的差距,允许通过 CSS 变量和 Tailwind 配置进行深度定制。

下载入口:https://github.com/openclaw/skills/tree/main/skills/wpank/shadcn

安装与下载

1. ClawHub CLI

从源直接安装技能的最快方式。

npx clawhub@latest install shadcn

2. 手动安装

将技能文件夹复制到以下位置之一

全局模式 ~/.openclaw/skills/ 工作区 /skills/

优先级:工作区 > 本地 > 内置

3. 提示词安装

将此提示词复制到 OpenClaw 即可自动安装。

请帮我使用 Clawhub 安装 shadcn。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。

shadcn-ui 应用场景

  • 使用预配置的 UI 基础搭建新的 Next.js 或 React 项目。
  • 通过 CLI 安装和配置特定的 UI 组件,如按钮、对话框和表格。
  • 使用 React Hook Form 和 Zod 验证构建复杂的类型安全表单。
  • 使用 sheet、下拉菜单和导航菜单实现无障碍导航模式。
  • 通过修改集中主题文件中的 CSS 变量来开发自定义设计系统。
  • 通过 toast 通知和加载状态增强用户体验。
shadcn-ui 工作原理
  1. 使用 shadcn CLI 初始化项目环境,设置 Tailwind 和全局 CSS 变量。
  2. 从库中安装所需的组件,这些组件随后会直接复制到项目的 components 目录中。
  3. 配置 cn 工具类以处理动态 Tailwind 类合并和冲突解决。
  4. 使用 Class Variance Authority 定义组件变体和尺寸,以确保整个应用程序的样式一致。
  5. 通过嵌套基元并使用 React Hooks 处理状态来组合复杂界面。
  6. 通过更新基础 CSS 层中的 HSL 值来部署一致的全局样式。

shadcn-ui 配置指南

要在 AI 代理环境中使用此技能,请运行以下安装命令:

npx clawhub@latest install shadcn-ui

对于新项目设置,请使用以下命令初始化配置:

npx shadcn@latest init

然后,根据需要添加必要的组件:

npx shadcn@latest add button input form card

shadcn-ui 数据架构与分类体系

类别 实现细节
组件 作为原始源代码存储在 @/components/ui/
工具类 位于 @/lib/utils.ts 中的 cn 等辅助函数
主题 globals.css 中定义的 HSL 变量
验证 用于表单状态管理的 Zod 模式
类型 每个组件自动生成的 TypeScript 接口
name: shadcn-ui
model: fast
description: 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.
keywords: [shadcn, shadcn/ui, radix ui, tailwind, react components, forms, react hook form, zod, dialog, sheet, button, card, toast, select, dropdown, table, accessible components]

shadcn/ui Component Patterns

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

Installation

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

Core Concepts

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" },
  }
)

Essential Components

Button

import { Button } from "@/components/ui/button"
import { Loader2 } from "lucide-react"

// Variants: default | destructive | outline | secondary | ghost | link
// Sizes: default | sm | lg | icon


// Loading state


// As link (uses Radix Slot)

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>({
    resolver: zodResolver(formSchema),
    defaultValues: { username: "", email: "", role: "user" },
  })

  function onSubmit(values: z.infer) {
    console.log(values)
  }

  return (
    
( Username Your public display name. )} /> ( Email )} /> ( Role )} /> ) }

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

  
  
    
      Edit profile
      Make changes here. Click save when done.
    
    
{/* form fields */}
// Slide-over panel (side: "left" | "right" | "top" | "bottom") Settings {/* content */}

Card

import {
  Card, CardContent, CardDescription,
  CardFooter, CardHeader, CardTitle,
} from "@/components/ui/card"


  
    Create project
    Deploy your new project in one-click.
  
  
    

Toast Notifications

// 1. Add Toaster to root layout
import { Toaster } from "@/components/ui/toaster"

export default function RootLayout({ children }) {
  return (
    
      {children}
    
  )
}

// 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: Try again,
})

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" },
]

A list of your recent invoices.
    
      Invoice
      Status
      Method
      Amount
    
  
    {invoices.map((invoice) => (
      
        {invoice.invoice}
        {invoice.status}
        {invoice.method}
        {invoice.amount}
      
    ))}
  

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

Component Install Key Props
Button add button variant, size, asChild
Input add input Standard HTML input props
Form add form React Hook Form + Zod integration
Card add card Header, Content, Footer composition
Dialog add dialog Modal with trigger pattern
Sheet add sheet Slide-over panel, side prop
Select add select Accessible dropdown
Toast add toast variant: "default" | "destructive"
Table add table Header, Body, Row, Cell composition
Tabs add tabs defaultValue, trigger/content pairs
Accordion add accordion type: "single" | "multiple"
Command add command Command palette / search
Dropdown Menu add dropdown-menu Context menus, action menus
Menubar add menubar Application menus with shortcuts

Next.js Integration

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 (
    
      
        {children}
        
      
    
  )
}

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

Practice Details
Use TypeScript All components ship with full type definitions
Zod for validation Pair with React Hook Form for type-safe forms
asChild pattern Use Radix Slot to render as different elements
Server Components Most shadcn/ui components need "use client"
Consistent structure Follow the existing component patterns when customizing
Accessibility Radix primitives handle ARIA; don't override without reason
CSS variables Theme via variables, not by editing component classes
Tree-shaking Only install components you need — they're independent

NEVER Do

Never Why Instead
Install shadcn as npm package It's not a package — it's source code you own Use CLI: npx shadcn@latest add
Override ARIA attributes Radix handles accessibility correctly Trust the primitives
Use inline styles for theming Defeats the design system Modify CSS variables
Copy components from docs manually May miss dependencies Use CLI for proper installation
Mix component styles Creates inconsistency Follow 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