shadcn-components

安装量: 73
排名: #20053

安装

npx skills add https://github.com/sgcarstrends/sgcarstrends --skill shadcn-components

shadcn/ui Components Skill

This skill helps you work with shadcn/ui components in packages/ui/.

When to Use This Skill Adding new shadcn/ui components to the shared UI library Customizing existing shadcn/ui component variants Updating component styling with Tailwind Finding and implementing component examples Debugging shadcn/ui component issues Managing component dependencies shadcn/ui Overview

shadcn/ui is a collection of re-usable components built with Radix UI and Tailwind CSS. Components are copied into your codebase, giving you full control.

packages/ui/ ├── src/ │ ├── components/ # shadcn/ui components │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── dialog.tsx │ │ └── ... │ ├── lib/ │ │ └── utils.ts # cn() utility for class merging │ └── styles/ │ └── globals.css # Global styles ├── components.json # shadcn/ui configuration └── package.json

Discovery and Research Search for Components // Use MCP tool to search for components mcp__shadcn__search_items_in_registries({ registries: ["@shadcn"], query: "button" })

mcp__shadcn__search_items_in_registries({ registries: ["@shadcn"], query: "form input" })

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

Get Component Examples // Find usage examples mcp__shadcn__get_item_examples_from_registries({ registries: ["@shadcn"], query: "button demo" })

mcp__shadcn__get_item_examples_from_registries({ registries: ["@shadcn"], query: "form example" })

Get Add Command // Get CLI command to add components mcp__shadcn__get_add_command_for_items({ items: ["@shadcn/button", "@shadcn/dialog"] })

Adding New Components Step 1: Search and Research

Use MCP tools to find the component

Example: Adding a dropdown menu component

mcp__shadcn__search_items_in_registries({ registries: ["@shadcn"], query: "dropdown menu" })

Step 2: Get Add Command mcp__shadcn__get_add_command_for_items({ items: ["@shadcn/dropdown-menu"] })

// Returns: npx shadcn@latest add dropdown-menu

Step 3: Add Component

Navigate to packages/ui

cd packages/ui

Add component using CLI

npx shadcn@latest add dropdown-menu

Or add multiple components at once

npx shadcn@latest add dropdown-menu select tabs

Step 4: Export Component

Update packages/ui/src/index.ts:

export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuGroup, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, } from "./components/dropdown-menu";

Step 5: Use in App // In apps/web or apps/api import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from "@sgcarstrends/ui";

export function UserMenu() { return ( Open Profile Settings Logout ); }

Core Components Button Component // packages/ui/src/components/button.tsx import { Button } from "@sgcarstrends/ui";

// Variants

// Sizes

Card Component import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, } from "@sgcarstrends/ui";

export function InfoCard() { return ( Card Title Card description goes here

Card content

Card footer

); }

Dialog Component import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@sgcarstrends/ui";

export function ConfirmDialog() { return (

Are you sure? This action cannot be undone.
); }

Form Components import { Label } from "@sgcarstrends/ui"; import { Input } from "@sgcarstrends/ui"; import { Textarea } from "@sgcarstrends/ui";

export function ContactForm() { return (

  <div className="space-y-2">
    <Label htmlFor="message">Message</Label>
    <Textarea id="message" placeholder="Enter your message" />
  </div>

  <Button type="submit">Submit</Button>
</form>

); }

Badge Component import { Badge } from "@sgcarstrends/ui";

export function StatusBadge({ status }: { status: string }) { return ( <> Default Secondary Destructive Outline </> ); }

Customization Customizing Component Variants

Edit component file directly:

// packages/ui/src/components/button.tsx const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium", { 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 hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", // Add custom variant success: "bg-green-500 text-white hover:bg-green-600", }, 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", // Add custom size xl: "h-14 rounded-md px-10 text-lg", }, }, defaultVariants: { variant: "default", size: "default", }, } );

Creating Compound Components // 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; description?: string; trend?: "up" | "down"; className?: string; }

export function StatCard({ title, value, description, trend, className, }: StatCardProps) { return ( {title} {trend && ( {trend === "up" ? "↑" : "↓"} )}

{value}
{description && (

{description}

)} ); }

Export in packages/ui/src/index.ts:

export { StatCard } from "./components/stat-card";

Theming Customizing Colors

Edit packages/ui/src/styles/globals.css:

@layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 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%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;

} }

Component Configuration components.json { "$schema": "https://ui.shadcn.com/schema.json", "style": "default", "rsc": true, "tsx": true, "tailwind": { "config": "tailwind.config.ts", "css": "src/styles/globals.css", "baseColor": "slate", "cssVariables": true }, "aliases": { "components": "@/components", "utils": "@/lib/utils" } }

Utility Functions cn() Utility // packages/ui/src/lib/utils.ts import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); }

Usage:

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

export function MyComponent({ className }: { className?: string }) { return (

Content
); }

Testing Components // packages/ui/src/components/tests/button.test.tsx import { render, screen } from "@testing-library/react"; import { Button } from "../button";

describe("Button", () => { it("renders correctly", () => { render(); expect(screen.getByText("Click me")).toBeInTheDocument(); });

it("applies variant styles", () => { render(); const button = screen.getByText("Delete"); expect(button).toHaveClass("bg-destructive"); });

it("handles click events", () => { const handleClick = vi.fn(); render();

screen.getByText("Click me").click();
expect(handleClick).toHaveBeenCalledOnce();

}); });

Run tests:

pnpm -F @sgcarstrends/ui test

Common Patterns Responsive Components import { Button } from "@sgcarstrends/ui";

export function ResponsiveButton() { return ( ); }

Composition import { Card, CardHeader, CardTitle, CardContent } from "@sgcarstrends/ui"; import { Button } from "@sgcarstrends/ui";

export function ActionCard({ title, children, onAction }: Props) { return ( {title} {children} ); }

Troubleshooting Component Not Found

Problem: Import error when using component Solution:

Check component is exported in packages/ui/src/index.ts Verify component file exists in packages/ui/src/components/ Run pnpm install to update dependencies Styling Issues

Problem: Tailwind classes not applying Solution:

Check packages/ui/tailwind.config.ts includes correct content paths Verify CSS variables are defined in globals.css Ensure parent app imports UI package's global CSS TypeScript Errors

Problem: Type errors when using components Solution:

Check component props are properly typed Run pnpm build in packages/ui Restart TypeScript server in IDE Updating Components

When shadcn/ui updates:

cd packages/ui

Update specific component

npx shadcn@latest add button --overwrite

Update multiple components

npx shadcn@latest add button card dialog --overwrite

References shadcn/ui Documentation: https://ui.shadcn.com Radix UI: https://www.radix-ui.com Related files: packages/ui/src/components/ - All UI components packages/ui/components.json - shadcn/ui config packages/ui/CLAUDE.md - UI package documentation Best Practices Use MCP Tools: Search before adding to avoid duplicates Export Components: Always export in index.ts Naming: Follow shadcn/ui naming conventions Testing: Write tests for custom variants Documentation: Document custom components Versioning: Keep shadcn/ui components updated Customization: Extend, don't modify core components Type Safety: Leverage TypeScript for props Size Utility: Use size- instead of h- w-* for equal dimensions (Tailwind v3.4+) Size Utility Convention

When styling shadcn/ui components with equal height and width, use the size-* utility:

// ✅ Good - Use size-* for equal dimensions

// ❌ Avoid - Redundant h- and w-

← 返回排行榜