Agent skill

Shadcn UI

by jh941213 in jh941213/my-cc-harness

Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components.

MITAuto-check: notesFrontend & Design

Install Shadcn UI

skills CLI
$ npx skills add jh941213/my-cc-harness --skill shadcn-ui -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install jh941213/my-cc-harness shadcn-ui --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/jh941213/my-cc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/shadcn-ui .claude/skills/shadcn-ui && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
shadcn-ui
GitHub stars
125
Used in
4 other repos
Token cost
~9.7k tokens
SKILL.md length
550 words
Files
5
Skills in repo
62
Repo updated
First seen
Licence
MIT

At a glance

Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components.

  • Works in 8 steps: Accessibility: Components use Radix UI… → Customization: Modify components… → Type Safety: Use TypeScript for… → …
  • Setting up shadcn/ui
  • SKILL.md covers Table of Contents, When to Use, Quick Start and What is shadcn/ui?, plus 5 more sections
  • Calls npx and npm

What it does

Shadcn UI is an agent skill from jh941213/my-cc-harness. Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components. Use when setting up shadcn/ui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts. 안티-트리거: "Material UI", "Chakra UI", "순수 CSS 컴포넌트"

Its SKILL.md is about 9.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files (for example `learn.md`, `official-ui-reference.md` and `reference.md`).

It sits in Frontend & Design, covering Design systems, React components and Forms and validation. It works with shadcn/ui, Tailwind CSS, Zod and TypeScript. The licence is MIT.

When your agent uses it

  • Setting up shadcn/ui
  • Installing components
  • Building forms with React Hook Form and Zod
  • Customizing themes with Tailwind CSS

Example prompts

  • “Material UI”
  • “Chakra UI”
  • “순수 CSS 컴포넌트”
  • “/shadcn-ui”

Requirements

  • Node.js
  • Pre-approved tools (allowed-tools): Read, Write, Bash, Edit, Glob

Workflow steps

8 steps, taken from the first numbered list in SKILL.md.

  1. Accessibility: Components use Radix UI primitives for ARIA compliance
  2. Customization: Modify components directly in your codebase
  3. Type Safety: Use TypeScript for type-safe props and state
  4. Validation: Use Zod schemas for form validation
  5. Styling: Leverage Tailwind utilities and CSS variables
  6. Consistency: Use the same component patterns across your app
  7. Testing: Components are testable with React Testing Library
  8. Performance: Components are optimized and tree-shakeable

What it can do on your machine

Read from SKILL.md and the folder at commit e9210e2. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Write
    • Bash
    • Edit
    • Glob

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx
    • npm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • ui.shadcn.com
    • radix-ui.com
    • react-hook-form.com
    • zod.dev
    • tailwindcss.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Shadcn UI loads about 9.7k tokens when it runs. Until then it costs about 106 tokens; SKILL.md has 550 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~106
When it runs · the whole SKILL.md, loaded when a task matches
~9.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Read, Write, Bash, Edit, Glob

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from jh941213/my-cc-harness at commit e9210e2, republished under its MIT licence (© jh941213). 550 words, ~9,732 tokens.

Download SKILL.mdSave it as .claude/skills/shadcn-ui/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
shadcn-ui
description
Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components. Use when setting up shadcn/ui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts. 안티-트리거: "Material UI", "Chakra UI", "순수 CSS 컴포넌트"
allowed-tools
Read, Write, Bash, Edit, Glob
user-invocable
false
language
typescript,tsx
framework
react,nextjs,tailwindcss
license
MIT

shadcn/ui Component Patterns

Expert guide for building accessible, customizable UI components with shadcn/ui, Radix UI, and Tailwind CSS.

스니펫 조회: 기본은 official-ui-reference.md(공식 문서 최신 덤프, blocks·chart 등 범위 넓음)를 읽고, 거기 없는 스니펫만 ui-reference.md(구버전 발췌)에서 보조 조회한다.

Table of Contents

When to Use

  • 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
  • Creating complex layouts and data displays

Quick Start

For new projects, use the automated setup:

bash
# Create Next.js project with shadcn/ui
npx create-next-app@latest my-app --typescript --tailwind --eslint --app
cd my-app
npx shadcn@latest init

# Install essential components
npx shadcn@latest add button input form card dialog select

For existing projects:

bash
# Install dependencies
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react

# Initialize shadcn/ui
npx shadcn@latest init

What is shadcn/ui?

shadcn/ui is not a traditional component library or npm package. Instead:

  • It's a collection of reusable components that you can copy into your project
  • Components are yours to customize - you own the code
  • Built with Radix UI primitives for accessibility
  • Styled with Tailwind CSS utilities
  • Includes CLI tool for easy component installation

Installation & Setup

Initial Setup
bash
# Initialize shadcn/ui in your project
npx shadcn@latest init

During setup, you'll configure:

  • TypeScript or JavaScript
  • Style (Default, New York, etc.)
  • Base color theme
  • CSS variables or Tailwind CSS classes
  • Component installation path
Installing Individual Components
bash
# Install a single component
npx shadcn@latest add button

# Install multiple components
npx shadcn@latest add button input form

# Install all components
npx shadcn@latest add --all
Manual Installation

If you prefer manual setup:

bash
# Install dependencies for a specific component
npm install @radix-ui/react-slot

# Copy component code from ui.shadcn.com
# Place in src/components/ui/

Project Configuration

Required Dependencies
json
{
  "dependencies": {
    "@radix-ui/react-accordion": "^1.1.2",
    "@radix-ui/react-alert-dialog": "^1.0.5",
    "@radix-ui/react-dialog": "^1.0.5",
    "@radix-ui/react-dropdown-menu": "^2.0.6",
    "@radix-ui/react-label": "^2.0.2",
    "@radix-ui/react-select": "^2.0.0",
    "@radix-ui/react-separator": "^1.0.3",
    "@radix-ui/react-slot": "^1.0.2",
    "@radix-ui/react-toast": "^1.1.5",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.0.0",
    "lucide-react": "^0.294.0",
    "tailwind-merge": "^2.0.0",
    "tailwindcss-animate": "^1.0.7"
  }
}
TSConfig Configuration
json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["./src/components/*"],
      "@/lib/*": ["./src/lib/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}
Tailwind Configuration
js
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: "",
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
      borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
}
CSS Variables (globals.css)
css
@tailwind base;
@tailwind components;
@tailwind utilities;

@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%;
  }
}

@layer base {
  * {
    @apply border-border;
  }
  body {
    @apply bg-background text-foreground;
  }
}

Core Components

Button Component

Installation:

bash
npx shadcn@latest add button

Basic usage:

tsx
import { Button } from "@/components/ui/button";

export function ButtonDemo() {
  return <Button>Click me</Button>;
}

Button variants:

tsx
import { Button } from "@/components/ui/button";

export function ButtonVariants() {
  return (
    <div className="flex gap-4">
      <Button variant="default">Default</Button>
      <Button variant="destructive">Destructive</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="link">Link</Button>
    </div>
  );
}

Button sizes:

tsx
<div className="flex gap-4 items-center">
  <Button size="default">Default</Button>
  <Button size="sm">Small</Button>
  <Button size="lg">Large</Button>
  <Button size="icon">
    <Icon className="h-4 w-4" />
  </Button>
</div>

With loading state:

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

export function ButtonLoading() {
  return (
    <Button disabled>
      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
      Please wait
    </Button>
  );
}
Input & Form Fields
Input Component

Installation:

bash
npx shadcn@latest add input

Basic input:

tsx
import { Input } from "@/components/ui/input";

export function InputDemo() {
  return <Input type="email" placeholder="Email" />;
}

Input with label:

tsx
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

export function InputWithLabel() {
  return (
    <div className="grid w-full max-w-sm items-center gap-1.5">
      <Label htmlFor="email">Email</Label>
      <Input type="email" id="email" placeholder="Email" />
    </div>
  );
}

Input with button:

tsx
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

export function InputWithButton() {
  return (
    <div className="flex w-full max-w-sm items-center gap-2">
      <Input type="email" placeholder="Email" />
      <Button type="submit" variant="outline">Subscribe</Button>
    </div>
  );
}
Forms with Validation

Installation:

bash
npx shadcn@latest add form

This installs React Hook Form, Zod, and form components.

Complete form example:

tsx
"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 { toast } from "@/components/ui/use-toast"

const formSchema = z.object({
  username: z.string().min(2, {
    message: "Username must be at least 2 characters.",
  }),
  email: z.string().email({
    message: "Please enter a valid email address.",
  }),
})

export function ProfileForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      username: "",
      email: "",
    },
  })

  function onSubmit(values: z.infer<typeof formSchema>) {
    toast({
      title: "You submitted the following values:",
      description: (
        <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
          <code className="text-white">{JSON.stringify(values, null, 2)}</code>
        </pre>
      ),
    })
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
        <FormField
          control={form.control}
          name="username"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="shadcn" {...field} />
              </FormControl>
              <FormDescription>
                This is your public display name.
              </FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input type="email" placeholder="you@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}
Card Component

Installation:

bash
npx shadcn@latest add card

Basic card:

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

export function CardDemo() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Card Title</CardTitle>
        <CardDescription>Card Description</CardDescription>
      </CardHeader>
      <CardContent>
        <p>Card Content</p>
      </CardContent>
      <CardFooter>
        <p>Card Footer</p>
      </CardFooter>
    </Card>
  )
}

Card with form:

tsx
import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

export function CardWithForm() {
  return (
    <Card className="w-[350px]">
      <CardHeader>
        <CardTitle>Create project</CardTitle>
        <CardDescription>Deploy your new project in one-click.</CardDescription>
      </CardHeader>
      <CardContent>
        <form>
          <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="Name of your project" />
            </div>
          </div>
        </form>
      </CardContent>
      <CardFooter className="flex justify-between">
        <Button variant="outline">Cancel</Button>
        <Button>Deploy</Button>
      </CardFooter>
    </Card>
  )
}
Dialog (Modal) Component

Installation:

bash
npx shadcn@latest add dialog

Basic dialog:

tsx
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"

export function DialogDemo() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="outline">Open Dialog</Button>
      </DialogTrigger>
      <DialogContent className="sm:max-w-[425px]">
        <DialogHeader>
          <DialogTitle>Edit profile</DialogTitle>
          <DialogDescription>
            Make changes to your profile here. Click save when you're done.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="name" className="text-right">
              Name
            </Label>
            <Input id="name" value="Pedro Duarte" className="col-span-3" />
          </div>
        </div>
        <DialogFooter>
          <Button type="submit">Save changes</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
Sheet (Slide-over) Component

Installation:

bash
npx shadcn@latest add sheet

Basic sheet:

tsx
import { Button } from "@/components/ui/button"
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"

export function SheetDemo() {
  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button variant="outline">Open Sheet</Button>
      </SheetTrigger>
      <SheetContent>
        <SheetHeader>
          <SheetTitle>Edit profile</SheetTitle>
          <SheetDescription>
            Make changes to your profile here. Click save when you're done.
          </SheetDescription>
        </SheetHeader>
        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="name" className="text-right">
              Name
            </Label>
            <Input id="name" value="Pedro Duarte" className="col-span-3" />
          </div>
          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="username" className="text-right">
              Username
            </Label>
            <Input id="username" value="@peduarte" className="col-span-3" />
          </div>
        </div>
      </SheetContent>
    </Sheet>
  )
}

Sheet with side placement:

tsx
<Sheet>
  <SheetTrigger asChild>
    <Button variant="outline">Open Right Sheet</Button>
  </SheetTrigger>
  <SheetContent side="right">
    <SheetHeader>
      <SheetTitle>Settings</SheetTitle>
      <SheetDescription>
        Configure your application settings here.
      </SheetDescription>
    </SheetHeader>
    {/* Settings content */}
  </SheetContent>
</Sheet>
Menubar & Navigation
Menubar Component

Installation:

bash
npx shadcn@latest add menubar

Basic menubar:

tsx
import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarSeparator,
  MenubarShortcut,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from "@/components/ui/menubar"

export function MenubarDemo() {
  return (
    <Menubar>
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New Tab <MenubarShortcut>⌘T</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            New Window <MenubarShortcut>⌘N</MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem>Share</MenubarItem>
          <MenubarSeparator />
          <MenubarItem>Print</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            Undo <MenubarShortcut>⌘Z</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            Redo <MenubarShortcut>⌘Y</MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarSub>
            <MenubarSubTrigger>Find</MenubarSubTrigger>
            <MenubarSubContent>
              <MenubarItem>Search the web</MenubarItem>
              <MenubarItem>Find...</MenubarItem>
              <MenubarItem>Find Next</MenubarItem>
              <MenubarItem>Find Previous</MenubarItem>
            </MenubarSubContent>
          </MenubarSub>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}
Select (Dropdown) Component

Installation:

bash
npx shadcn@latest add select

Basic select:

tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

export function SelectDemo() {
  return (
    <Select>
      <SelectTrigger className="w-[180px]">
        <SelectValue placeholder="Select a fruit" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="apple">Apple</SelectItem>
        <SelectItem value="banana">Banana</SelectItem>
        <SelectItem value="orange">Orange</SelectItem>
      </SelectContent>
    </Select>
  )
}

Select in form:

tsx
<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>
  )}
/>
Show full SKILL.md (216 more words)Show less
Toast Notifications

Installation:

bash
npx shadcn@latest add toast

Setup toast provider in root layout:

tsx
import { Toaster } from "@/components/ui/toaster"

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Toaster />
      </body>
    </html>
  )
}

Using toast:

tsx
import { useToast } from "@/components/ui/use-toast"
import { Button } from "@/components/ui/button"

export function ToastDemo() {
  const { toast } = useToast()

  return (
    <Button
      onClick={() => {
        toast({
          title: "Scheduled: Catch up",
          description: "Friday, February 10, 2023 at 5:57 PM",
        })
      }}
    >
      Show Toast
    </Button>
  )
}

Toast variants:

tsx
// Success
toast({
  title: "Success",
  description: "Your changes have been saved.",
})

// Error
toast({
  variant: "destructive",
  title: "Error",
  description: "Something went wrong.",
})

// With action
toast({
  title: "Uh oh! Something went wrong.",
  description: "There was a problem with your request.",
  action: <ToastAction altText="Try again">Try again</ToastAction>,
})
Table Component

Installation:

bash
npx shadcn@latest add table

Basic table:

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

export function TableDemo() {
  return (
    <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>
  )
}

Customization

Theming with CSS Variables

shadcn/ui uses CSS variables for theming. Configure in globals.css:

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%;
    --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%;
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
    /* ... other dark mode variables */
  }
}
Customizing Components

Since you own the code, customize directly:

tsx
// components/ui/button.tsx
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

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",
        // Add custom variant
        custom: "bg-gradient-to-r from-purple-500 to-pink-500 text-white",
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        // Add custom size
        xl: "h-14 rounded-md px-10 text-lg",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  }
)
Button.displayName = "Button"

export { Button, buttonVariants }

Next.js Integration

App Router Setup

For Next.js 13+ with App Router, ensure components use "use client" directive:

tsx
// src/components/ui/button.tsx
"use client"

import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

// ... rest of component
Layout Integration

Add the Toaster to your root layout:

tsx
// 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

When using shadcn/ui components in Server Components, wrap them in a Client Component:

tsx
// app/dashboard/page.tsx
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { ButtonClient } from "@/components/ui/button-client"

export default function DashboardPage() {
  return (
    <div className="container mx-auto p-6">
      <Card>
        <CardHeader>
          <CardTitle>Dashboard</CardTitle>
        </CardHeader>
        <CardContent>
          <ButtonClient>Interactive Button</ButtonClient>
        </CardContent>
      </Card>
    </div>
  )
}
tsx
// src/components/ui/button-client.tsx
"use client"

import { Button } from "./button"

export function ButtonClient(props: React.ComponentProps<typeof Button>) {
  return <Button {...props} />
}
Route Handlers with Forms

Create API routes for form submissions:

tsx
// app/api/contact/route.ts
import { NextRequest, NextResponse } from "next/server"
import { z } from "zod"

const contactSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  message: z.string().min(10),
})

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const validated = contactSchema.parse(body)

    // Process form data
    console.log("Form submission:", validated)

    return NextResponse.json({ success: true })
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { errors: error.errors },
        { status: 400 }
      )
    }

    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    )
  }
}
Form with Server Action

Using Next.js 14+ Server Actions:

tsx
// app/contact/page.tsx
"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,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { toast } from "@/components/ui/use-toast"

const formSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  message: z.string().min(10),
})

async function onSubmit(values: z.infer<typeof formSchema>) {
  try {
    const response = await fetch("/api/contact", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(values),
    })

    if (!response.ok) throw new Error("Failed to submit")

    toast({
      title: "Success!",
      description: "Your message has been sent.",
    })
  } catch (error) {
    toast({
      variant: "destructive",
      title: "Error",
      description: "Failed to send message. Please try again.",
    })
  }
}

export default function ContactPage() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
  })

  return (
    <div className="container mx-auto max-w-2xl py-8">
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
          <FormField
            control={form.control}
            name="name"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Name</FormLabel>
                <FormControl>
                  <Input placeholder="Your name" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="email"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Email</FormLabel>
                <FormControl>
                  <Input type="email" placeholder="your@email.com" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="message"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Message</FormLabel>
                <FormControl>
                  <Textarea
                    placeholder="Your message..."
                    className="resize-none"
                    {...field}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <Button type="submit" className="w-full">
            Send Message
          </Button>
        </form>
      </Form>
    </div>
  )
}
Metadata with shadcn/ui

Using shadcn/ui components in metadata:

tsx
// app/layout.tsx
import { Metadata } from "next"

export const metadata: Metadata = {
  title: {
    default: "My App",
    template: "%s | My App",
  },
  description: "Built with shadcn/ui and Next.js",
}

// app/about/page.tsx
import { Metadata } from "next"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"

export const metadata: Metadata = {
  title: "About Us",
  description: "Learn more about our company",
}

export default function AboutPage() {
  return (
    <div className="container mx-auto py-8">
      <Card>
        <CardHeader>
          <CardTitle>About Our Company</CardTitle>
        </CardHeader>
        <CardContent>
          <p>We build amazing products with modern web technologies.</p>
        </CardContent>
      </Card>
    </div>
  )
}
Font Optimization

Optimize fonts with next/font:

tsx
// app/layout.tsx
import { Inter } from "next/font/google"
import { Toaster } from "@/components/ui/toaster"
import { cn } from "@/lib/utils"
import "./globals.css"

const inter = Inter({ subsets: ["latin"] })

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={cn("min-h-screen bg-background font-sans antialiased", inter.className)}>
        {children}
        <Toaster />
      </body>
    </html>
  )
}

Advanced Patterns

Form with Multiple Fields
tsx
const formSchema = z.object({
  username: z.string().min(2).max(50),
  email: z.string().email(),
  bio: z.string().max(160).min(4),
  role: z.enum(["admin", "user", "guest"]),
  notifications: z.boolean().default(false),
})

export function AdvancedForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      username: "",
      email: "",
      bio: "",
      role: "user",
      notifications: false,
    },
  })

  function onSubmit(values: z.infer<typeof formSchema>) {
    console.log(values)
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
        {/* Username field */}
        <FormField
          control={form.control}
          name="username"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="johndoe" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        {/* Email field */}
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input type="email" placeholder="john@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        {/* Textarea field */}
        <FormField
          control={form.control}
          name="bio"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Bio</FormLabel>
              <FormControl>
                <Textarea
                  placeholder="Tell us about yourself"
                  className="resize-none"
                  {...field}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        {/* Select field */}
        <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>
          )}
        />

        {/* Checkbox field */}
        <FormField
          control={form.control}
          name="notifications"
          render={({ field }) => (
            <FormItem className="flex flex-row items-start space-x-3 space-y-0">
              <FormControl>
                <Checkbox
                  checked={field.value}
                  onCheckedChange={field.onChange}
                />
              </FormControl>
              <div className="space-y-1 leading-none">
                <FormLabel>Email notifications</FormLabel>
                <FormDescription>
                  Receive emails about your account activity.
                </FormDescription>
              </div>
            </FormItem>
          )}
        />

        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}

Best Practices

  1. Accessibility: Components use Radix UI primitives for ARIA compliance
  2. Customization: Modify components directly in your codebase
  3. Type Safety: Use TypeScript for type-safe props and state
  4. Validation: Use Zod schemas for form validation
  5. Styling: Leverage Tailwind utilities and CSS variables
  6. Consistency: Use the same component patterns across your app
  7. Testing: Components are testable with React Testing Library
  8. Performance: Components are optimized and tree-shakeable

Common Component Combinations

Login Form
tsx
<Card className="w-[350px]">
  <CardHeader>
    <CardTitle>Login</CardTitle>
    <CardDescription>Enter your credentials to continue</CardDescription>
  </CardHeader>
  <CardContent>
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input type="email" placeholder="you@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="password"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Password</FormLabel>
              <FormControl>
                <Input type="password" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit" className="w-full">Login</Button>
      </form>
    </Form>
  </CardContent>
</Card>

References

© jh941213, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files in skills/shadcn-ui of jh941213/my-cc-harness.

  • SKILL.md
  • learn.md
  • official-ui-reference.md
  • reference.md
  • ui-reference.md

Open the folder on GitHubat commit e9210e2

Used in 4 other repositories

We found 5 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 4 other GitHub owners. This page covers the copy in jh941213/my-cc-harness, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Shadcn UI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Shadcn UI compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Shadcn UI this skilljh941213/my-cc-harness1254 repos~9.7kAutomated safety check: NotesMIT
Buzzformbuildnbuzz/buzzform102—~1.5kAutomated safety check: PassMIT
Creative Tim UI Blockscreativetimofficial/ui12k—~2.1kAutomated safety check: NotesMIT
Ss Learnbitjaru/styleseed973—~1.3kAutomated safety check: PassMIT
Animated React Component LibrariesHainrixz/editor-pro-max2641 repos~5.7kAutomated safety check: PassCustom licence
Nextjs15 Initbear2u/my-skills932—~2.4kAutomated safety check: PassNone

Similar skills

  • Buzzform

    buildnbuzz/buzzform

    A skill your agent uses when working with BuzzForm schema-driven forms, @buildnbuzz/form-core, @buildnbuzz/form-react, or any related APIs like defineSchema, InferType, FormProvider, useDataField…

    102 GitHub stars~1.5k tokensUpdated 4 mo ago
    Frontend & DesignAuto-check passed
  • Creative Tim UI Blocks

    creativetimofficial/ui

    Helps install, generate and review Creative Tim UI blocks: shadcn/ui-based React and Tailwind sections that follow a restrained, production-minded design philosophy.

    12k GitHub stars~2.1k tokensUpdated 6 mo ago
    Frontend & DesignAuto-check: notes
  • Ss Learn

    bitjaru/styleseed

    Capture a human-approved UI design lesson as a privacy-minimized local StyleSeed candidate, review it, and prepare an opt-in share package without transmitting project code, prompts, screenshots, or…

    973 GitHub stars~1.3k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Animated React Component Libraries

    Hainrixz/editor-pro-max

    Helps choose and drop in animated React components from Magic UI and React Bits for landing pages, marketing sites and dashboards, instead of hand-coding animations.

    264 GitHub starsUsed in 1 repo~5.7k tokens
    Frontend & DesignAuto-check passed
  • Nextjs15 Init

    bear2u/my-skills

    A skill your agent uses when user wants to create a new Next.js 15 project (Todo/Blog/Dashboard/E-commerce/Custom domain) with App Router, ShadCN, Zustand, Tanstack Query, and modern Next.js stack

    932 GitHub stars~2.4k tokensUpdated 3 mo ago
    Frontend & DesignAuto-check passed
  • Styleseed

    bitjaru/styleseed

    Build, improve, or inspect UI with StyleSeed. An agent skill from bitjaru/styleseed.

    973 GitHub stars~1.1k tokensUpdated yesterday
    Frontend & DesignAuto-check passed

More from jh941213/my-cc-harness

All 62 skills in this repo
  • API Design Principles

    jh941213/my-cc-harness

    REST 및 GraphQL API 설계 원칙 가이드. An agent skill from jh941213/my-cc-harness.

    125 GitHub starsUsed in 18 repos~3.4k tokens
    Auto-check passed
  • Tailwind Design System

    jh941213/my-cc-harness

    Build scalable design systems with Tailwind CSS, design tokens, component libraries, and responsive patterns.

    125 GitHub starsUsed in 10 repos~4.7k tokens
    Auto-check passed
  • Docs Architecture

    jh941213/my-cc-harness

    Generate/update architecture docs — ARCHITECTURE.md (codemap), architecture diagrams (C4 mermaid), ADRs (MADR), data model ERD.

    125 GitHub stars~923 tokensUpdated 2 mo ago
    Auto-check: notes
  • Auto Memory

    jh941213/my-cc-harness

    A skill your agent uses when starting substantial work in a repo (implementation, fixes, deploys, debugging), when first exploring a new repo, or when finishing work that produced reusable knowledge.

    125 GitHub stars~890 tokensUpdated 2 mo ago
    Auto-check passed
  • Async Python Patterns

    jh941213/my-cc-harness

    Python asyncio 및 async/await 패턴 가이드. An agent skill from jh941213/my-cc-harness.

    125 GitHub starsUsed in 14 repos~4.7k tokens
    Auto-check passed
  • Python Testing Patterns

    jh941213/my-cc-harness

    Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development.

    125 GitHub starsUsed in 17 repos~5.4k tokens
    Auto-check passed

Questions about Shadcn UI

What does Shadcn UI do?

Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components. Shadcn UI is an agent skill from jh941213/my-cc-harness. Complete shadcn/ui component library guide including installation, configuration, and implementation of accessible React components.

When should I use Shadcn UI?

Shadcn UI fits situations like: setting up shadcn/ui; installing components; building forms with React Hook Form and Zod; customizing themes with Tailwind CSS.

How do I install Shadcn UI in Claude Code?

Run `npx skills add jh941213/my-cc-harness --skill shadcn-ui -a claude-code`. Or copy the skill folder (skills/shadcn-ui in jh941213/my-cc-harness) into .claude/skills/shadcn-ui in your project. Claude Code loads it when a task matches its description.

How do I install Shadcn UI in Codex?

Run `npx skills add jh941213/my-cc-harness --skill shadcn-ui -a codex`. Or copy the skill folder (skills/shadcn-ui in jh941213/my-cc-harness) into .agents/skills/shadcn-ui in your project. Codex loads it when a task matches its description.

Can I use Shadcn UI in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jh941213/my-cc-harness --skill shadcn-ui -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/shadcn-ui, .gemini/skills/shadcn-ui, .github/skills/shadcn-ui and .opencode/skills/shadcn-ui in your project.

What does Shadcn UI need to run?

Going by SKILL.md and its folder, Shadcn UI needs the command-line tools its instructions call (npx and npm). Our summary lists: Node.js. Its frontmatter pre-approves these tools: Read, Write, Bash, Edit, Glob.

Does Shadcn UI access the network?

SKILL.md names 5 domains. As links in the text: ui.shadcn.com, radix-ui.com, react-hook-form.com, zod.dev and tailwindcss.com. This is read from the text; nothing was executed.

Is Shadcn UI safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Shadcn UI use?

Shadcn UI is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Shadcn UI use?

About 9.7k tokens (SKILL.md is roughly 39k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Shadcn UI?

Skills that share tags, products or a category with Shadcn UI: Buzzform (buildnbuzz/buzzform, 102 stars), Creative Tim UI Blocks (creativetimofficial/ui, 12k stars), Ss Learn (bitjaru/styleseed, 973 stars) and Animated React Component Libraries (Hainrixz/editor-pro-max, 264 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Shadcn UI?

jh941213 (a GitHub user) maintains it in jh941213/my-cc-harness, which has 125 GitHub stars. The repository holds 62 skills in this directory. The repository was last updated on August 3, 2026.

Source: jh941213/my-cc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.