shadcn-components

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

shadcn/ui Components Skill

shadcn/ui 组件使用技能

Components live in
packages/ui/
. shadcn/ui is copied into your codebase for full control.
packages/ui/
├── src/
│   ├── components/     # shadcn/ui components
│   ├── lib/utils.ts    # cn() utility
│   └── styles/globals.css
├── components.json     # shadcn/ui config
└── package.json
组件存放在
packages/ui/
目录下。shadcn/ui会被复制到你的代码库中,以便你拥有完全的控制权。
packages/ui/
├── src/
│   ├── components/     # shadcn/ui components
│   ├── lib/utils.ts    # cn() utility
│   └── styles/globals.css
├── components.json     # shadcn/ui config
└── package.json

Discovery with MCP Tools

通过MCP工具检索组件

typescript
// Search for components
mcp__shadcn__search_items_in_registries({ registries: ["@shadcn"], query: "button" })

// View component details
mcp__shadcn__view_items_in_registries({ items: ["@shadcn/button", "@shadcn/card"] })

// Get add command
mcp__shadcn__get_add_command_for_items({ items: ["@shadcn/dropdown-menu"] })
typescript
// Search for components
mcp__shadcn__search_items_in_registries({ registries: ["@shadcn"], query: "button" })

// View component details
mcp__shadcn__view_items_in_registries({ items: ["@shadcn/button", "@shadcn/card"] })

// Get add command
mcp__shadcn__get_add_command_for_items({ items: ["@shadcn/dropdown-menu"] })

Adding Components

添加组件

bash
cd packages/ui
npx shadcn@latest add dropdown-menu
npx shadcn@latest add dropdown-menu select tabs  # Multiple
Export in
packages/ui/src/index.ts
:
typescript
export {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
} from "./components/dropdown-menu";
Use in apps:
typescript
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@sgcarstrends/ui";
bash
cd packages/ui
npx shadcn@latest add dropdown-menu
npx shadcn@latest add dropdown-menu select tabs  # Multiple
packages/ui/src/index.ts
中导出组件:
typescript
export {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
} from "./components/dropdown-menu";
在应用中使用:
typescript
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@sgcarstrends/ui";

Core Components

核心组件

typescript
// Button variants: default, destructive, outline, secondary, ghost, link
// Button sizes: default, sm, lg, icon
<Button variant="destructive" size="sm">Delete</Button>

// Card composition
<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Description</CardDescription>
  </CardHeader>
  <CardContent>Content</CardContent>
  <CardFooter>Footer</CardFooter>
</Card>

// Dialog
<Dialog>
  <DialogTrigger asChild><Button>Open</Button></DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Confirm</DialogTitle>
      <DialogDescription>Are you sure?</DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>

// Form elements
<Label htmlFor="name">Name</Label>
<Input id="name" placeholder="Enter name" />
<Textarea id="message" />

// Badge variants: default, secondary, destructive, outline
<Badge variant="secondary">Status</Badge>
typescript
// Button variants: default, destructive, outline, secondary, ghost, link
// Button sizes: default, sm, lg, icon
<Button variant="destructive" size="sm">Delete</Button>

// Card composition
<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Description</CardDescription>
  </CardHeader>
  <CardContent>Content</CardContent>
  <CardFooter>Footer</CardFooter>
</Card>

// Dialog
<Dialog>
  <DialogTrigger asChild><Button>Open</Button></DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Confirm</DialogTitle>
      <DialogDescription>Are you sure?</DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>

// Form elements
<Label htmlFor="name">Name</Label>
<Input id="name" placeholder="Enter name" />
<Textarea id="message" />

// Badge variants: default, secondary, destructive, outline
<Badge variant="secondary">Status</Badge>

Customizing Variants

自定义组件变体

Edit component file directly in
packages/ui/src/components/
:
typescript
// button.tsx - Add custom variant
const buttonVariants = cva("inline-flex items-center...", {
  variants: {
    variant: {
      // existing variants...
      success: "bg-green-500 text-white hover:bg-green-600",
    },
    size: {
      // existing sizes...
      xl: "h-14 rounded-md px-10 text-lg",
    },
  },
});
直接在
packages/ui/src/components/
目录下编辑组件文件:
typescript
// button.tsx - Add custom variant
const buttonVariants = cva("inline-flex items-center...", {
  variants: {
    variant: {
      // existing variants...
      success: "bg-green-500 text-white hover:bg-green-600",
    },
    size: {
      // existing sizes...
      xl: "h-14 rounded-md px-10 text-lg",
    },
  },
});

Creating Compound Components

创建复合组件

typescript
// packages/ui/src/components/stat-card.tsx
import { Card, CardHeader, CardTitle, CardContent } from "./card";
import { cn } from "../lib/utils";

interface StatCardProps {
  title: string;
  value: string | number;
  trend?: "up" | "down";
  className?: string;
}

export function StatCard({ title, value, trend, className }: StatCardProps) {
  return (
    <Card className={cn("", className)}>
      <CardHeader className="flex flex-row items-center justify-between pb-2">
        <CardTitle className="text-sm font-medium">{title}</CardTitle>
        {trend && <span className={trend === "up" ? "text-green-500" : "text-red-500"}>{trend === "up" ? "↑" : "↓"}</span>}
      </CardHeader>
      <CardContent>
        <div className="text-2xl font-bold">{value}</div>
      </CardContent>
    </Card>
  );
}
typescript
// packages/ui/src/components/stat-card.tsx
import { Card, CardHeader, CardTitle, CardContent } from "./card";
import { cn } from "../lib/utils";

interface StatCardProps {
  title: string;
  value: string | number;
  trend?: "up" | "down";
  className?: string;
}

export function StatCard({ title, value, trend, className }: StatCardProps) {
  return (
    <Card className={cn("", className)}>
      <CardHeader className="flex flex-row items-center justify-between pb-2">
        <CardTitle className="text-sm font-medium">{title}</CardTitle>
        {trend && <span className={trend === "up" ? "text-green-500" : "text-red-500"}>{trend === "up" ? "↑" : "↓"}</span>}
      </CardHeader>
      <CardContent>
        <div className="text-2xl font-bold">{value}</div>
      </CardContent>
    </Card>
  );
}

cn() Utility

cn() 工具函数

typescript
import { cn } from "@sgcarstrends/ui/lib/utils";

<div className={cn("base-classes", condition && "conditional", className)}>
typescript
import { cn } from "@sgcarstrends/ui/lib/utils";

<div className={cn("base-classes", condition && "conditional", className)}>

Theming (CSS Variables)

主题定制(CSS变量)

Edit
packages/ui/src/styles/globals.css
:
css
@layer base {
  :root {
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    /* ... */
  }
  .dark {
    --primary: 210 40% 98%;
    /* ... */
  }
}
编辑
packages/ui/src/styles/globals.css
文件:
css
@layer base {
  :root {
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    /* ... */
  }
  .dark {
    --primary: 210 40% 98%;
    /* ... */
  }
}

Updating Components

更新组件

bash
cd packages/ui
npx shadcn@latest add button --overwrite
bash
cd packages/ui
npx shadcn@latest add button --overwrite

Troubleshooting

故障排除

  • Component not found: Check export in
    packages/ui/src/index.ts
  • Styling not applied: Verify content paths in
    tailwind.config.ts
  • TypeScript errors: Run
    pnpm build
    in packages/ui
  • 组件未找到:检查
    packages/ui/src/index.ts
    中的导出配置
  • 样式未生效:验证
    tailwind.config.ts
    中的内容路径
  • TypeScript错误:在packages/ui目录下运行
    pnpm build
    命令

Best Practices

最佳实践

  1. Use MCP Tools: Search before adding to avoid duplicates
  2. Export Components: Always export in index.ts
  3. Size Utility: Use
    size-*
    instead of
    h-* w-*
    for equal dimensions
  4. Extend, don't modify: Add custom variants rather than changing core styles
  1. 使用MCP工具:添加前先搜索,避免重复组件
  2. 导出组件:务必在index.ts中导出组件
  3. 尺寸工具类:使用
    size-*
    替代
    h-* w-*
    来设置等宽高尺寸
  4. 扩展而非修改:添加自定义变体,而非修改核心样式

References

参考资料