惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
有赞技术团队
有赞技术团队
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
博客园_首页
Y
Y Combinator Blog
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
雷峰网
雷峰网
博客园 - 司徒正美
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Help Net Security
P
Proofpoint News Feed
B
Blog
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
shadcn/ui is Not a Component Library
Subhan Farra · 2026-05-26 · via DEV Community

Subhan Farrakh

Originally published on subhanfarrakh.com/blog

The Standard Model is Broken

Every team I've worked on has had the same conversation at some point: "The design doesn't match what the library gives us, but overriding it is a nightmare." You end up in specificity wars, wrapping components in extra divs, and fighting the library's opinions with your own.

shadcn/ui takes a different position entirely: don't install a library, own the code.

What shadcn/ui Actually Is

When you run npx shadcn@latest add button, nothing gets added to node_modules. Instead, a Button.tsx file lands in your components/ui/ directory — with full source code, your project's Tailwind theme already wired in, and zero external dependency for the component itself.

// This is YOUR file now. Edit it freely.
import { cva, type VariantProps } from 'class-variance-authority';

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 hover:bg-accent hover:text-accent-foreground',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
      },
      size: {
        default: 'h-10 px-4 py-2',
        sm: 'h-9 rounded-md px-3',
        lg: 'h-11 rounded-md px-8',
      },
    },
    defaultVariants: { variant: 'default', size: 'default' },
  }
);

Enter fullscreen mode Exit fullscreen mode

The underlying primitives (Radix UI for accessibility, CVA for variants, Tailwind for styling) are still npm dependencies. But the component layer — the part you interact with daily — is yours.

Why This Changes Everything

Customization is the default, not the exception. Need a ghost button with a custom hover color that matches your brand? Edit the file. No sx props, no CSS overrides, no wrapper components. Just change the Tailwind class.

The abstraction boundary is honest. Traditional component libraries hide their internals. When something goes wrong, you're debugging minified code in node_modules. With shadcn/ui, the code is in your repo, readable and traceable.

Updates are deliberate. This is the tradeoff: shadcn/ui components don't auto-update. You re-run npx shadcn@latest add button and get a diff to review. Some teams see this as a downside. I see it as appropriate friction — UI should change intentionally.

The CSS Variable System

shadcn/ui pairs with a CSS variable design token system:

: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);
}

.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
}

Enter fullscreen mode Exit fullscreen mode

Change the variables, the entire system shifts. Dark mode is a matter of flipping a class on <html>. The whole system is coherent because it's all pointing at the same tokens.

When Not to Use It

shadcn/ui is a great fit for product UI where you need control. It's less ideal if:

  • You're prototyping fast and don't want to own components yet
  • Your team doesn't have a design system and won't maintain the components
  • You're using a framework that isn't React (though ports exist for Vue, Svelte, etc.)

For those cases, a traditional library like MUI or Mantine might serve you better. But if you've ever felt constrained by a component library, shadcn/ui is worth a serious look.