QTPortfolio
Tailwind CSS + shadcn/ui: Building a Design System in Minutes
Tailwind CSSshadcn/uiReactUI Design

Tailwind CSS + shadcn/ui: Building a Design System in Minutes

January 25, 20262 min read~226 words

Why shadcn/ui?

Unlike traditional component libraries (MUI, Chakra UI), shadcn/ui takes a unique approach: you own the code. Components are copied directly into your project, giving you full control to customize them without overriding library styles.

Setting Up Dark Mode

With next-themes and Tailwind's dark mode class strategy, implementing a theme toggle is straightforward:

// tailwind.config.ts
export default {
  darkMode: ["class"],
  theme: {
    extend: {
      colors: {
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
      },
    },
  },
}

CSS Variables for Theming

The real power comes from CSS custom properties. Swap an entire theme by changing a few HSL values:

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary: 221.2 83.2% 53.3%;
}

.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  --primary: 217.2 91.2% 59.8%;
}

Framer Motion Animations

Adding entrance animations to any component is as simple as wrapping it with motion.div:

import { motion } from "motion/react";

export function AnimatedCard({ children }) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true }}
      transition={{ duration: 0.5 }}
    >
      {children}
    </motion.div>
  );
}

The Result

A pixel-perfect, accessible, responsive UI that you fully own and control — no fighting against library defaults, no massive bundle bloat. This stack is my go-to for any new React project.

Enjoyed this article?

Share it with your network or explore more posts below.