Pendahuluan
Produk hebat bukan dibangun dari komponen acak. Ia dibangun dari sistem.
Jika project Anda mulai terasa tidak konsisten — ukuran tombol berbeda-beda, warna tidak sinkron, spacing berantakan — itu bukan masalah coding. Itu masalah sistem.
Di artikel ini kita akan membangun design system sederhana tapi scalable menggunakan:
- Next.js 14
- Tailwind CSS
- shadcn/ui
Kenapa Perlu Design System?
Tanpa design system:
- UI cepat jadi tidak konsisten
- Developer sulit maintain
- Scaling tim makin berantakan
- Refactor makin mahal
Dengan design system:
- Komponen reusable
- Styling konsisten
- Mudah dikembangkan
- Siap scale ke produk besar
1. Standarisasi Warna (Token System)
Di tailwind.config.ts, buat sistem warna berbasis CSS variable:
theme: {
extend: {
colors: {
primary: 'hsl(var(--primary))',
secondary: 'hsl(var(--secondary))',
muted: 'hsl(var(--muted))',
border: 'hsl(var(--border))',
},
},
}Lalu definisikan di globals.css:
:root {
--primary: 222 89% 55%;
--secondary: 240 5% 84%;
--muted: 240 4% 95%;
--border: 240 6% 90%;
}Sekarang semua warna berbasis token.
Ganti satu variable → seluruh UI ikut berubah.
2. Standarisasi Typography
Gunakan satu font utama:
import { Plus_Jakarta_Sans } from 'next/font/google'
const jakarta = Plus_Jakarta_Sans({
subsets: ['latin'],
variable: '--font-sans',
})Tambahkan ke Tailwind:
fontFamily: {
sans: ['var(--font-sans)'],
},Definisikan skala ukuran:
fontSize: {
xs: ['12px', { lineHeight: '1.4' }],
sm: ['14px', { lineHeight: '1.5' }],
base: ['16px', { lineHeight: '1.6' }],
lg: ['18px', { lineHeight: '1.6' }],
xl: ['20px', { lineHeight: '1.5' }],
}Typography yang konsisten = UI terasa profesional.
3. Struktur Folder yang Rapi
Struktur scalable:
components/
ui/ → komponen dasar (Button, Input, Card)
layout/ → Navbar, Footer
sections/ → Hero, Features, CTA
lib/
utils.ts
app/
(routes)
Pisahkan komponen UI generik dan komponen spesifik halaman.
4. Komponen Button Terstandarisasi
Contoh implementasi Button reusable:
import { cn } from '@/lib/utils'
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'default' | 'outline'
}
export function Button({
className,
variant = 'default',
...props
}: ButtonProps) {
return (
<button
className={cn(
'rounded-lg px-5 py-2 text-sm font-medium transition-all',
variant === 'default' &&
'bg-primary text-white hover:opacity-90',
variant === 'outline' &&
'border border-border hover:bg-muted',
className
)}
{...props}
/>
)
}Keuntungannya:
- Tidak styling ulang tiap kali
- Variant terkontrol
- Mudah scale
5. Komponen Card System
export function Card({ children }: { children: React.ReactNode }) {
return (
<div className="rounded-2xl border border-border bg-white p-6 shadow-sm">
{children}
</div>
)
}Simple. Clean. Konsisten.
Visualisasi Komponen
Best Practice Production
- Hindari inline styling berulang
- Gunakan utility class konsisten
- Pakai token system (warna, spacing, font)
- Hindari magic number
- Buat variant untuk komponen utama
Design system bukan soal estetika.
Ini soal efisiensi engineering jangka panjang.
Kesimpulan
Semakin besar produk Anda, semakin penting sistemnya.
Design system yang baik membuat:
- Developer lebih cepat
- UI lebih konsisten
- Refactor lebih aman
- Tim lebih produktif
Bangun sistem sejak awal.
Karena scaling tanpa sistem = technical debt yang mahal.
Artikel berikutnya bisa kita lanjut ke:
- Optimasi Performance Next.js
- Struktur Project Monorepo
- Setup Dark Mode Production-Ready
- Accessibility & Semantic HTML di Next.js
Tinggal pilih arah strateginya.