Alur Kerja Figma ke Next.js: Cara Saya Menerjemahkan Desain ke Komponen

Foto oleh Unsplash

Foto oleh Unsplash
Ada kesenjangan yang menyakitkan antara desain Figma yang dipoles dan komponen React yang berfungsi. Nilai piksel yang tidak memetakan ke default Tailwind. Nama warna dalam sistem desain yang tidak ada hubungannya dengan nama variabel CSS di codebase. Setelah mengiterasi alur kerja ini di beberapa proyek — termasuk portofolio ini — saya mendarat pada proses yang menjaga fidelitas desain tinggi dan waktu terjemahan rendah.
Penghemat waktu terbesar adalah menghabiskan 30 menit mengaudit file Figma sebelum menyentuh kode. Yang saya cari: ketidakkonsistenan dalam penggunaan token desain, penggunaan auto-layout, dan hierarki komponen. Desain yang menggunakan auto-layout secara menyeluruh dan setup variabel lokal yang tepat diterjemahkan hampir secara mekanis.
Dev Mode Figma berguna tetapi memerlukan interpretasi. Ini memberi Anda nilai piksel yang tepat, arah auto-layout dan gap, radius sudut, opacity, dan warna. Yang tidak diberikan adalah makna semantik — tidak akan memberi tahu Anda bahwa warna adalah brand-500 dalam sistem desain Anda.
Panel variabel Figma dan konfigurasi Tailwind perlu menggunakan nama yang sama untuk nilai yang sama. Saya menyiapkan konfigurasi Tailwind sebelum menulis komponen, memperluas tema untuk mencocokkan nama variabel Figma secara tepat: jika Figma memiliki color/brand/500, kunci Tailwind adalah brand-500.
┌─────────────┐ Inspect ┌──────────────────────┐
│ FIGMA │ ─────────────► │ Design Tokens │
│ (Design) │ Dev Mode │ colors, spacing, │
└─────────────┘ │ typography, radius │
└──────────┬───────────┘
│ tailwind.config.ts
▼
┌─────────────────────────────────────────────────────┐
│ COMPONENT MAPPING │
│ │
│ Figma Frame/Group → React Component │
│ Figma Auto-layout → flex / grid classes │
│ Figma Variant → TypeScript props union │
│ Figma Component → Storybook story │
└──────────────────────────┬──────────────────────────┘
│ build
▼
Next.js Page
(server components)Instal plugin Figma Tokens Studio for Figma untuk mengekspor token desain langsung sebagai file JSON, lalu gunakan Style Dictionary untuk menghasilkan ekstensi konfigurasi Tailwind Anda secara otomatis. Untuk proyek dengan lebih dari 50 token unik, ini menghilangkan seluruh kategori kesalahan sinkronisasi manual.
Setiap komponen Figma menjadi antarmuka TypeScript. Varian Figma memetakan ke tipe union TypeScript. Properti boolean Figma memetakan ke props boolean opsional. Aturan saya: apa pun yang secara eksplisit dibuat desainer sebagai varian atau penggantian gaya yang dapat dikonfigurasi harus menjadi prop.
Desain Figma biasanya untuk satu lebar viewport — biasanya desktop 1440px atau mobile 375px. Saat menerjemahkan ke Next.js, saya menggunakan prefix responsif Tailwind (sm, md, lg) untuk menginterpolasi antara dua status yang didesain.
// tailwind.config.ts — mirror Figma token names exactly
import type { Config } from "tailwindcss"
const config: Config = {
theme: {
extend: {
colors: {
brand: {
50: "#eff6ff",
500: "#3b82f6", // match Figma "brand/500"
900: "#1e3a5f",
},
},
spacing: {
18: "4.5rem", // custom Figma spacing token
},
borderRadius: {
"2xl": "1rem", // Figma corner radius
},
},
},
}
export default config
// components/ui/Button.tsx — typed props from Figma variants
type ButtonVariant = "primary" | "secondary" | "ghost"
type ButtonSize = "sm" | "md" | "lg"
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant
size?: ButtonSize
loading?: boolean
}
const variantClasses: Record<ButtonVariant, string> = {
primary: "bg-brand-500 text-white hover:bg-brand-600",
secondary: "bg-transparent border border-brand-500 text-brand-500",
ghost: "bg-transparent text-brand-500 hover:bg-brand-50",
}
const sizeClasses: Record<ButtonSize, string> = {
sm: "px-3 py-1.5 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
}
export function Button({
variant = "primary",
size = "md",
loading,
children,
className,
...props
}: ButtonProps) {
return (
<button
className={`rounded-2xl font-medium transition-colors ${variantClasses[variant]} ${sizeClasses[size]} ${className ?? ""}`}
disabled={loading}
{...props}
>
{loading ? <span className="animate-spin">⏳</span> : children}
</button>
)
}Setiap komponen yang saya bangun dari Figma mendapatkan cerita Storybook bersamanya. Cerita mencakup setiap varian persis seperti yang muncul di Figma, ditambah kasus tepi — status kosong, string panjang, status loading, status error. Storybook berfungsi sebagai jembatan hidup antara desain dan implementasi.
Menghabiskan berjam-jam mencocokkan perbedaan 2px yang hanya terlihat pada zoom 200% hampir selalu merupakan tradeoff yang salah. Rilis dengan fidelitas 95% dengan cepat, kumpulkan umpan balik pengguna, lalu perbaiki. Setujui tingkat toleransi yang jelas dengan desainer Anda sebelum ulasan komponen.
Saya menggunakan Lucide React sebagai pustaka ikon default — dapat di-tree-shake, konsisten dalam gaya, dan mencakup sebagian besar kebutuhan UI. Untuk ikon kustom dari desain, saya mengekspornya dari Figma sebagai SVG, mengoptimalkannya dengan SVGO, dan membungkusnya dalam komponen React sederhana.
Terkadang saya membangun fitur di mana desainer masih mengerjakan file Figma. Dalam kasus itu, saya mulai dengan API komponen terlebih dahulu — mendefinisikan antarmuka TypeScript untuk props, mengestub komponen dengan konten placeholder, dan menulis cerita Storybook. Desain komponen muncul dari props, bukan sebaliknya.