Skip to content

Tailwind CSS + shadcn/ui — Checklist

OWNER: alexander ALSO_USED_BY: floris, floor LAST_VERIFIED: 2026-03-26 GE_STACK_VERSION: tailwindcss ^4, shadcn ^3.8.4


PROJECT SETUP CHECKLIST

  • [ ] CHECK: Main CSS file uses @import "tailwindcss" (not v3 @tailwind directives)
  • [ ] CHECK: No tailwind.config.js exists (v4 uses CSS-first config)
  • [ ] CHECK: No postcss-import or autoprefixer in PostCSS config (v4 handles both)
  • [ ] CHECK: lib/utils.ts contains cn() helper (clsx + tailwind-merge)
  • [ ] CHECK: Design tokens defined in @theme { } block
  • [ ] CHECK: Semantic tokens defined in :root and [data-theme="dark"]
  • [ ] CHECK: @custom-variant dark configured if using attribute-based dark mode
  • [ ] CHECK: shadcn components installed in components/ui/

COMPONENT DEVELOPMENT CHECKLIST

  • [ ] CHECK: Component uses React.forwardRef
  • [ ] CHECK: Component accepts and merges className via cn()
  • [ ] CHECK: Variants defined with CVA (not ternary chains)
  • [ ] CHECK: Both component and variants are exported
  • [ ] CHECK: Component has displayName set
  • [ ] CHECK: No direct modifications to components/ui/ files (use wrappers)
  • [ ] CHECK: Icons from Lucide have explicit size classes (h-4 w-4)

RESPONSIVE DESIGN CHECKLIST

  • [ ] CHECK: Base styles are mobile (no breakpoint prefix)
  • [ ] CHECK: Larger screens use progressive sm: / md: / lg: prefixes
  • [ ] CHECK: Touch targets meet 44x44px minimum on mobile
  • [ ] CHECK: Content has max-w-* to prevent ultra-wide layouts
  • [ ] CHECK: Images use w-full h-auto as base with constrained max-width
  • [ ] CHECK: Container queries used for reusable components in varied contexts

ACCESSIBILITY CHECKLIST

  • [ ] CHECK: All interactive elements are keyboard-navigable
  • [ ] CHECK: Focus rings visible (using focus-visible:ring-2)
  • [ ] CHECK: Color contrast meets WCAG 2.1 AA (4.5:1 normal, 3:1 large)
  • [ ] CHECK: Color is not the sole indicator of state
  • [ ] CHECK: Radix accessibility features not overridden
  • [ ] CHECK: No outline-none without focus-visible replacement

TOKEN/THEMING CHECKLIST

  • [ ] CHECK: Colors use OKLCH format in @theme
  • [ ] CHECK: Semantic tokens reference base tokens via var()
  • [ ] CHECK: Status colors use semantic names (error, success) not raw (red-500)
  • [ ] CHECK: Dark mode tokens tested — all text readable on dark backgrounds
  • [ ] CHECK: No hardcoded color values in component files

BUILD CHECKLIST

  • [ ] CHECK: No dynamically constructed class names (string interpolation)
  • [ ] CHECK: All Tailwind classes are complete scannable strings
  • [ ] CHECK: Border elements specify explicit color (border-border)
  • [ ] CHECK: Gradient utilities use v4 syntax (bg-linear-to-r not bg-gradient-to-r) IF_SKIPPED: Gradients silently fail — no visual error, just missing gradient
  • [ ] CHECK: Zod error handling uses .issues not .errors ADDED_FROM: admin-ui-rebuild-2026-02, form validation bug

Cross-References

READ_ALSO: wiki/docs/stack/tailwind-shadcn/index.md READ_ALSO: wiki/docs/stack/tailwind-shadcn/pitfalls.md