karawaci.kode

2026-06-04 · 6 min

shadcn + Tailwind v4: Migrasi Design System 1 Hari

Klien SaaS B2B Jakarta minta visual refresh setelah 18 bulan UI yang sama. Saya lihat ini momen bagus untuk sekaligus migrasi dari Tailwind v3 + Radix custom (yang saya hand-roll dulu) ke shadcn + Tailwind v4. Janji ke klien: 1 hari kerja, tidak ada visual regression yang signifikan.

Setup

App existing: Next.js 15, Tailwind v3.4, Radix Primitives langsung dengan custom styling. ~120 component custom. CSS bundle 187KB (minified, non-gzip). Build time 42 detik di GitHub Actions Ubuntu runner.

Target: Tailwind v4, shadcn (CLI install per component), keep Radix di bawah (shadcn pakai Radix anyway).

Tim: saya solo untuk migration ini.

Eksekusi

Pagi (4 jam):

  1. Branch baru. Install Tailwind v4: bun add tailwindcss@latest @tailwindcss/postcss.
  2. Migrate tailwind.config.ts ke CSS-native @theme block di globals.css. Tailwind v4 default-nya CSS-first config. Saya hapus config file lama.
  3. Run codemod official: npx @tailwindcss/upgrade. Auto-convert ~80% utility class lama (e.g., bg-opacity-50bg-black/50).
  4. Setup shadcn: bunx shadcn@latest init. Pilih theme: zinc, CSS variables.

Siang (3 jam):

  1. Install component shadcn yang setara dengan custom saya: button, input, dialog, dropdown-menu, form, table, toast, card, badge, tabs, sheet. Total 23 component.
  2. Find-and-replace import: dari @/components/ui/Button (custom) ke @/components/ui/button (shadcn). Codemod manual via ripgrep + sed.
  3. Visual diff via Percy snapshot. 47 diff terdetect. 31 di antaranya intended (theme refresh). 16 yang regression. Fix 16 ini.

Sore (1 jam):

  1. Build production. CSS bundle: 99KB (minified). Dari 187KB. Reduction 47%.
  2. Build time: 26 detik. Dari 42 detik. Reduction 38%.
  3. Lighthouse score: performance dari 89 ke 94. Accessibility tetap 96.

Selesai pukul 17:30. Push branch, klien review besoknya.

Yang break

  1. Plugin @tailwindcss/forms: di v4 belum officially released, ada compatibility branch. Saya pakai @tailwindcss/forms@next. Works, tapi watch GitHub issue untuk official release.

  2. Custom utility text-balance: di v3 saya pakai plugin community. Di v4 sudah built-in: text-balance. Saya hapus plugin custom. -1 dependency.

  3. darkMode: 'class': di v4 syntax beda. Sekarang pakai @media (prefers-color-scheme: dark) atau @variant dark. Saya pakai @variant dark + class-based toggle. Kerja sama persis seperti dulu.

  4. CSS variable HSL → OKLCH: shadcn theme terbaru pakai OKLCH color space. Lebih akurat di wide-gamut display. Saya keep, klien suka warna terlihat lebih “modern” (terutama di MacBook Retina).

Yang juga gotcha

Custom border radius design system klien dulu pakai --radius: 0.5rem. shadcn terbaru pakai variable scaled (--radius-sm, --radius-md, --radius-lg). Saya keep custom variable supaya konsisten dengan brand guide klien, override default shadcn.

Animation: shadcn pakai tw-animate-css plugin baru di v4 (replace tailwindcss-animate di v3). Migration straightforward, tapi beberapa keyframe naming beda. Saya audit 8 component yang custom animate, fix 3.

Bundle deep dive

Sebelum:

  • Tailwind utility CSS: 142KB
  • Custom CSS (component styling): 45KB
  • Total: 187KB

Sesudah:

  • Tailwind utility CSS: 78KB (better tree-shaking di v4 engine)
  • shadcn component (CSS-in-class): 21KB
  • Custom CSS: 0 (semua via Tailwind utility)
  • Total: 99KB

Tailwind v4 punya new engine (Rust-based via Oxide) yang jauh lebih efektif di tree-shake unused utility. Real measurable.

Build time deep dive

Sebelum (v3):

  • Tailwind JIT compile: 14 detik
  • Next.js build: 28 detik
  • Total: 42 detik

Sesudah (v4):

  • Tailwind Oxide compile: 3,8 detik
  • Next.js build: 22 detik (less CSS to process)
  • Total: 26 detik

CI saving per build: 16 detik. Untuk team ini yang push ~40 commit/hari di CI: saving 10,6 menit/hari, atau 3,2 jam/bulan compute time.

Cost & verdict

Saving:

  • CI compute (Vercel): ~$8/mo
  • Page weight (faster mobile load): tidak ada metric langsung ke revenue, tapi Lighthouse +5 point
  • Developer happiness: less config file, more CSS-native

Cost:

  • Saya 8 jam migration: Rp 2jt billed ke klien
  • Risk: 1 minor regression slip yang kena production 2 hari (badge color mismatch di mobile view, fix 15 menit)

Klien happy. Investment break-even di hosting saving ~3 tahun, tapi visual refresh saja sudah worth pricing.

shadcn pattern (copy-paste component, own your code) makes sense untuk team kecil yang butuh kontrol full. Tailwind v4 worth migration untuk project active development. Pattern serupa dengan migrasi build-time saya di Astro 6: tooling upgrade yang bayar dirinya sendiri dalam hitungan minggu.

Bukan untuk project legacy yang tidak ada bandwidth audit. Untuk project active: lakukan.

Ditulis oleh Reza Pradipta