Files
gh-tenequm-claude-plugins-s…/skills/skill/SKILL.md
2025-11-30 09:01:28 +08:00

12 KiB

name, description
name description
styling-with-tailwind Creates UIs using Tailwind CSS utility classes and shadcn/ui patterns. Covers CSS variables with OKLCH colors, component variants with CVA, responsive design, dark mode, and Tailwind v4 features. Use when building interfaces with Tailwind, styling shadcn/ui components, implementing themes, or working with utility-first CSS.

Styling with Tailwind CSS

Build accessible UIs using Tailwind utility classes and shadcn/ui component patterns.

Core Patterns

CSS Variables for Theming

shadcn/ui uses semantic CSS variables mapped to Tailwind utilities:

/* globals.css - Light mode */
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --primary: oklch(0.205 0 0);
  --primary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);
  --border: oklch(0.922 0 0);
  --radius: 0.5rem;
}

/* Dark mode */
.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --primary: oklch(0.922 0 0);
  --primary-foreground: oklch(0.205 0 0);
}

/* Tailwind v4: Map variables */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
}

Usage in components:

// Background colors omit the "-background" suffix
<div className="bg-primary text-primary-foreground">
<div className="bg-muted text-muted-foreground">
<div className="bg-destructive text-destructive-foreground">

Component Variants with CVA

Use class-variance-authority for component variants:

import { cva } from "class-variance-authority"

const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 px-3 text-xs",
        lg: "h-10 px-8",
        icon: "size-9",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

// Usage
<Button variant="outline" size="sm">Click me</Button>

Responsive Design

Mobile-first breakpoints:

// Stack on mobile, grid on tablet+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">

// Hide on mobile
<div className="hidden md:block">

// Different layouts per breakpoint
<div className="flex flex-col md:flex-row lg:gap-8">
  <aside className="w-full md:w-64">
  <main className="flex-1">
</div>

// Responsive text sizes
<h1 className="text-3xl md:text-4xl lg:text-5xl">

Dark Mode

// Use dark: prefix for dark mode styles
<div className="bg-white dark:bg-black text-black dark:text-white">

// Theme toggle component
"use client"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"

export function ThemeToggle() {
  const { theme, setTheme } = useTheme()

  return (
    <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      <Sun className="rotate-0 scale-100 dark:-rotate-90 dark:scale-0" />
      <Moon className="absolute rotate-90 scale-0 dark:rotate-0 dark:scale-100" />
    </button>
  )
}

Common Component Patterns

Card

<div className="rounded-xl border bg-card text-card-foreground shadow">
  <div className="flex flex-col space-y-1.5 p-6">
    <h3 className="font-semibold leading-none tracking-tight">Title</h3>
    <p className="text-sm text-muted-foreground">Description</p>
  </div>
  <div className="p-6 pt-0">Content</div>
  <div className="flex items-center p-6 pt-0">Footer</div>
</div>

Form Field

<div className="space-y-2">
  <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
    Email
  </label>
  <input
    type="email"
    className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
  />
  <p className="text-sm text-muted-foreground">Helper text</p>
</div>

Badge

const badgeVariants = cva(
  "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors",
  {
    variants: {
      variant: {
        default: "border-transparent bg-primary text-primary-foreground shadow",
        secondary: "border-transparent bg-secondary text-secondary-foreground",
        destructive: "border-transparent bg-destructive text-destructive-foreground",
        outline: "text-foreground",
      },
    },
  }
)

Alert

<div className="relative w-full rounded-lg border px-4 py-3 text-sm [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11">
  <AlertCircle className="size-4" />
  <div className="font-medium">Alert Title</div>
  <div className="text-sm text-muted-foreground">Description</div>
</div>

Loading Skeleton

<div className="space-y-2">
  <div className="h-4 w-[250px] animate-pulse rounded bg-muted" />
  <div className="h-4 w-[200px] animate-pulse rounded bg-muted" />
</div>

Layout Patterns

Centered Layout

<div className="flex min-h-screen items-center justify-center">
  <div className="w-full max-w-md space-y-8 p-8">
    {/* Content */}
  </div>
</div>

Sidebar Layout

<div className="flex h-screen">
  <aside className="w-64 border-r bg-muted/40">Sidebar</aside>
  <main className="flex-1 overflow-auto">Content</main>
</div>

Dashboard Grid

<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
  <Card className="col-span-2">Wide card</Card>
  <Card>Regular</Card>
  <Card>Regular</Card>
  <Card className="col-span-4">Full width</Card>
</div>

Container with Max Width

<div className="container mx-auto px-4 md:px-6 lg:px-8">
  <div className="max-w-2xl mx-auto">
    {/* Centered content */}
  </div>
</div>

Accessibility Patterns

Focus Visible

<button className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">

Screen Reader Only

<span className="sr-only">Close dialog</span>

Disabled States

<button className="disabled:cursor-not-allowed disabled:opacity-50" disabled>

ARIA-friendly Alert

<div role="alert" className="rounded-lg border p-4">
  <div className="flex items-start gap-3">
    <AlertCircle className="size-5 text-destructive" />
    <div className="flex-1 space-y-1">
      <h5 className="font-medium">Error</h5>
      <p className="text-sm text-muted-foreground">Message</p>
    </div>
  </div>
</div>

Tailwind v4 Features

Size Utility

// New syntax (replaces w-* h-*)
<div className="size-4">
<div className="size-8">
<div className="size-full">

@theme Directive

/* Tailwind v4 syntax */
@theme {
  --color-primary: oklch(0.205 0 0);
  --font-sans: "Inter", system-ui;
}

/* With CSS variables */
@theme inline {
  --color-primary: var(--primary);
}

Animation

/* globals.css */
@import "tw-animate-css";
<div className="animate-fade-in">
<div className="animate-slide-in-from-top">
<div className="animate-spin">

Tailwind v4.1 Features (April 2025)

Text Shadow:

// Subtle text shadows for depth
<h1 className="text-shadow-sm text-4xl font-bold">
<h2 className="text-shadow-md text-2xl">
<div className="text-shadow-lg text-xl">

// Custom text shadows
<div className="text-shadow-[0_2px_4px_rgb(0_0_0_/_0.1)]">

Mask Utilities:

// Gradient masks for fade effects
<div className="mask-linear-to-b from-black to-transparent">
  Fades to transparent at bottom
</div>

// Image masks
<div className="mask-[url('/mask.svg')]">
  Masked content
</div>

// Common patterns
<div className="mask-radial-gradient">Spotlight effect</div>

Colored Drop Shadow:

// Brand-colored shadows
<div className="drop-shadow-[0_4px_12px_oklch(0.488_0.243_264.376)]">

// Use with semantic colors
<Button className="drop-shadow-lg drop-shadow-primary/50">
  Glowing button
</Button>

Overflow Wrap:

// Break long words
<p className="overflow-wrap-anywhere">
  verylongwordthatneedstowrap
</p>

<p className="overflow-wrap-break-word">
  URLs and long strings
</p>

OKLCH Colors

Use OKLCH for better color perception:

/* Format: oklch(lightness chroma hue) */
--primary: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);

/* Benefits: perceptually uniform, consistent lightness across hues */

Base Color Palettes

shadcn/ui provides multiple base colors:

/* Neutral (default) - pure grayscale */
--primary: oklch(0.205 0 0);

/* Zinc - cooler, blue-gray */
--primary: oklch(0.21 0.006 285.885);

/* Slate - balanced blue-gray */
--primary: oklch(0.208 0.042 265.755);

/* Stone - warmer, brown-gray */
--primary: oklch(0.216 0.006 56.043);

Best Practices

Prefer Semantic Colors

// Good - uses theme
<div className="bg-background text-foreground">

// Avoid - hardcoded
<div className="bg-white text-black dark:bg-zinc-950">
<div className="
  flex items-center justify-between
  rounded-lg border
  bg-card text-card-foreground
  p-4 shadow-sm
  hover:bg-accent
">

Avoid Arbitrary Values

// Prefer design tokens
<div className="p-4 text-sm">

// Avoid when unnecessary
<div className="p-[17px] text-[13px]">

Installation

# Initialize shadcn/ui
pnpm dlx shadcn@latest init

# Add components
pnpm dlx shadcn@latest add button card form

# Add all components
pnpm dlx shadcn@latest add --all

Troubleshooting

Colors not updating:

  1. Check CSS variable in globals.css
  2. Verify @theme inline includes variable
  3. Clear build cache

Dark mode not working:

  1. Verify ThemeProvider wraps app
  2. Check suppressHydrationWarning on html tag
  3. Ensure dark: variants defined

Tailwind v4 migration:

  1. Run @tailwindcss/upgrade@next codemod
  2. Update CSS variables with hsl() wrappers
  3. Change @theme to @theme inline
  4. Install tw-animate-css

Component Patterns

For detailed component patterns see components.md:

  • Composition: asChild pattern for wrapping elements
  • Typography: Heading scales, prose styles, inline code
  • Forms: React Hook Form with Zod validation
  • Icons: Lucide icons integration and sizing
  • Inputs: OTP, file, grouped inputs
  • Dialogs: Modal patterns and composition
  • Data Tables: TanStack table integration
  • Toasts: Sonner notifications
  • CLI: Complete command reference

Resources

See theming.md for complete color system reference and examples.

Summary

Key concepts:

  • Use semantic CSS variables for theming
  • Apply CVA for component variants
  • Follow mobile-first responsive patterns
  • Implement dark mode with next-themes
  • Use OKLCH for modern color handling
  • Prefer Tailwind v4 features (size-*, @theme)
  • Always ensure accessibility with focus-visible, sr-only

This skill focuses on shadcn/ui patterns with Tailwind CSS. For component-specific examples, refer to the official shadcn/ui documentation.