Target ekspor default figmascope adalah Jetpack Compose. Ini bukan hal yang sembarangan — model layout Compose (Column, Row, Box, Modifier) sangat sesuai dengan jenis node IR (stack, overlay, absolute, leaf). Stack vertikal di Figma adalah Column di Compose. Terjemahannya bersifat mekanis, yang membuatnya cocok untuk codegen yang digerakkan agen.
Panduan ini mencakup pemetaan IR-ke-Compose secara detail, menunjukkan fragmen JSON nyata beserta Composable yang sesuai, dan menjelaskan lapisan pemetaan token.
Mengapa Compose adalah target default
Tiga alasan struktural:
- Auto-layout ↔ Column/Row. Frame auto-layout Figma (mayoritas besar desain Figma modern) diekspor sebagai node
kind: "stack". Node stack memiliki propertiaxis—verticaldipetakan keColumn,horizontaldipetakan keRow. Ini adalah pemetaan 1:1 tanpa langkah interpretasi. - Token spacing ↔ nilai dp. Compose menggunakan
Dpuntuk semua dimensi layout. Nilai token dalamtokens.jsonadalah bilangan bulat tanpa satuan (mis.spacing.16 = 16) yang langsung dipetakan ke16.dp. Tanpa konversi, tanpa skala. - Token warna ↔ Color composable. Nilai hex Figma dalam
tokens.jsondipetakan keColor(0xFFrrggbb)dengan satu transformasi. Kunci token menjadi nama variabel semantik dalam tema Anda.
Jenis node IR dan pemetaan Compose-nya
| Jenis IR | Properti | Primitif Compose |
|---|---|---|
stack | axis: "vertical" | Column |
stack | axis: "horizontal" | Row |
overlay | children berlapis | Box |
absolute | x, y, width, height | Box dengan Modifier.offset(x.dp, y.dp) |
leaf | type: "text" | Text dengan TextStyle |
leaf | type: "rectangle" dengan fill | Box(Modifier.background(Color(...))) |
Semua jenis node dapat membawa properti spacing (jarak antar children) dan objek padding (atas/kanan/bawah/kiri). Keduanya merujuk pada kunci token.
Pemetaan token secara detail
File tokens.json terlihat seperti ini:
{
"spacing": {
"4": 4, "8": 8, "12": 12, "16": 16,
"20": 20, "24": 24, "32": 32, "48": 48
},
"radius": {
"4": 4, "8": 8, "12": 12, "16": 16, "full": 9999
},
"color": {
"7f5cfe": "#7F5CFE",
"1a1a2e": "#1A1A2E",
"f6f2ea": "#F6F2EA",
"ffffff": "#FFFFFF",
"e53935": "#E53935"
},
"typography": {
"heading.24": { "size": 24, "weight": 700, "lineHeight": 1.2 },
"body.14": { "size": 14, "weight": 400, "lineHeight": 1.5 },
"label.12": { "size": 12, "weight": 500, "lineHeight": 1.4 }
}
}
Aturan pemetaan:
spacing.16→16.dpradius.12→RoundedCornerShape(12.dp)color.7f5cfe→Color(0xFF7F5CFE)(tambahkan0xFFuntuk alpha penuh)typography.heading.24→TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Bold, lineHeight = 28.8.sp)
Kunci token sengaja dibuat buram (string hex untuk warna, string numerik untuk spacing) agar tidak membiaskan model ke konvensi penamaan tertentu. Tema Compose Anda dapat mengaliaskannya ke nama semantik — colorPrimary, spacingMd — secara independen dari IR.
Contoh nyata: JSON home screen ke Composable
Berikut adalah IR home screen yang disederhanakan. Stack vertikal dengan leaf header dan daftar kartu:
{
"name": "home",
"kind": "stack",
"axis": "vertical",
"spacing": "spacing.24",
"padding": { "top": "spacing.16", "right": "spacing.16",
"bottom": "spacing.16", "left": "spacing.16" },
"fill": "color.f6f2ea",
"children": [
{
"kind": "leaf",
"type": "text",
"stringRef": "home.title",
"typography": "typography.heading.24",
"fill": "color.1a1a2e"
},
{
"kind": "stack",
"axis": "vertical",
"spacing": "spacing.12",
"children": [
{
"kind": "overlay",
"radius": "radius.12",
"fill": "color.ffffff",
"padding": { "top": "spacing.16", "right": "spacing.16",
"bottom": "spacing.16", "left": "spacing.16" },
"children": [
{
"kind": "leaf",
"type": "text",
"stringRef": "home.card.label",
"typography": "typography.label.12",
"fill": "color.7f5cfe"
}
]
}
]
}
]
}
Composable yang sesuai — apa yang harus dihasilkan agen dari IR ini:
@Composable
fun HomeScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF6F2EA))
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
Text(
text = stringResource(R.string.home_title),
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
lineHeight = 28.8.sp,
color = Color(0xFF1A1A2E)
)
)
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Box(
modifier = Modifier
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFFFFFFFF))
.padding(16.dp)
) {
Text(
text = stringResource(R.string.home_card_label),
style = TextStyle(
fontSize = 12.sp,
fontWeight = FontWeight.Medium,
lineHeight = 16.8.sp,
color = Color(0xFF7F5CFE)
)
)
}
}
}
}
Setiap nilai dalam Composable dapat ditelusuri ke kunci token dalam IR. Tidak ada yang hardcoded — 16.dp berasal dari spacing.16, 24.dp dari spacing.24, Color(0xFF7F5CFE) dari color.7f5cfe.
String refs — pemetaan stringResource
Setiap node teks dalam IR membawa stringRef dengan kunci notasi titik. File strings.json memetakan kunci ke nilai tampilan dan fallback:
{
"home.title": { "value": "Good morning", "fallback": "Good morning" },
"home.card.label": { "value": "Today's summary", "fallback": "Summary" }
}
Notasi titik dipetakan ke ID resource string Android dengan titik diganti garis bawah: home.title → R.string.home_title. Field fallback adalah yang Anda hardcode sebagai string literal jika resource belum ada di strings.xml:
text = stringResource(R.string.home_title, "Good morning")
Beri tahu agen untuk selalu menggunakan field fallback — bukan string kosong — agar layar dapat terbaca selama pengembangan sebelum strings.xml diisi.
Positioning absolut
Node dengan kind: "absolute" menggunakan koordinat Figma secara langsung. Ini muncul dalam desain dengan elemen yang saling tumpang tindih atau elemen yang ditambatkan ke posisi tertentu. Pemetaan Compose menggunakan Box sebagai parent dan Modifier.offset pada children:
// IR: { "kind": "absolute", "x": 24, "y": 80, "width": 120, "height": 40 }
Box(modifier = Modifier.fillMaxSize()) {
Box(
modifier = Modifier
.offset(x = 24.dp, y = 80.dp)
.size(width = 120.dp, height = 40.dp)
) {
// children
}
}
Positioning absolut jarang terjadi dalam file Figma yang terstruktur dengan baik (sebagian besar file modern menggunakan auto-layout). Ketika Anda menemukannya, periksa apakah maksud desain benar-benar absolut atau apakah desainer hanya tidak menerapkan constraint auto-layout — IR tidak dapat menyimpulkan maksud.
Keterbatasan yang jujur
Bundle ini menangani kasus umum dengan baik. Beberapa hal yang tidak ditangani:
- Fill gradien. IR mengekspor peringatan saat menemukan gradien. Fill latar belakang node dihilangkan. Tinggalkan
// TODO: gradientdan implementasikan secara manual. - Efek kompleks. Drop shadow dan blur tidak direpresentasikan dalam IR. Keduanya muncul di peringatan
_meta.jsonjika ada. - Ikon vektor. IR menyimpan ID referensi untuk node ikon, bukan data path. Anda perlu me-resolve ikon ke drawable atau compose icon yang sebenarnya secara terpisah.
- Komponen bersarang. IR menyertakan
componentIdpada node instance.components/inventory.jsonmemetakan ID ke nama. Implementasikan komponen secara terpisah dan referensikan berdasarkan nama dalam Composable parent.
Keterbatasan ini bersifat eksplisit — muncul di peringatan _meta.json dan CONTEXT.md. Agen tidak menebak-nebak melaluinya secara diam-diam.
Ekspor context bundle dari aplikasi figmascope utama, lalu gunakan bersama Claude Code atau Cursor untuk mengimplementasikan Composable langsung dari IR. Tanpa tebak-tebakan screenshot, tanpa nilai hardcoded.