Icon Principles
Filosofi iconography MASA
DS v2.0 60+ icons

Icon Principles

Icon di MASA bukan dekorasi — mereka adalah bahasa visual yang membantu user bernavigasi dan memahami tanpa membaca. 5 prinsip ini berlaku untuk setiap keputusan icon baru.

MASA Icon Philosophy: Icon harus dapat dipahami oleh siapapun dalam 200ms — dari kader Muhammadiyah usia 60 tahun hingga Gen Z habit seeker. Universal sebelum ekspresif.
Recognizable — dikenal dalam 200ms
Gunakan metaphor yang universal. "Buku" untuk Qur'an, "jam" untuk jadwal salat, "hati" untuk sedekah. Hindari metaphor abstrak yang membutuhkan interpretasi.
Consistent — satu sistem, satu gaya
Semua icon dari satu library (Phosphor Icons Regular). Tidak boleh mixing gaya — outline di satu layar, filled di layar lain. Kecuali untuk state aktif/tidak aktif yang disengaja.
Trustworthy — tidak ambigu
Untuk fitur yang berhubungan dengan uang, ibadah, dan identitas — gunakan icon yang paling literal dan familiar. Bukan icon yang "keren tapi ambigu". Trust adalah prioritas.
Accessible — contrast dan ukuran yang cukup
Minimum 24px visual, 44px touch target. Stroke weight 1.5px minimum agar terlihat jelas pada layar low-density. Jangan gunakan icon tanpa label teks kecuali sangat universal (search, back, close).
Islamic-aware — menghormati konteks
Beberapa icon perlu perhatian khusus dalam konteks Islam. Masjid, Al-Qur'an, doa — jangan gunakan representasi yang disederhanakan berlebihan. Hormat tanpa menjadi berat dan ornamental.

Style Decision

Evaluasi 4 gaya icon library yang umum. MASA menggunakan Phosphor Icons — Regular weight.

Phosphor Icons
Regular · 1.5px stroke · rounded
Bersih, modern, rounded corner yang sesuai dengan brand personality "tenang dan bijak". Tidak terlalu kaku, tidak terlalu playful. 7000+ icon.
✓ DIPILIH untuk MASA
Heroicons
Outline · 1.5px stroke · sharp
Terlalu angular dan "tech-startup". Tidak sesuai dengan warmth brand MASA. Corner radius-nya kaku.
✕ Terlalu angular
Material Symbols
Rounded · variable weight
Terlalu identik dengan Google/Android. Kehilangan identitas brand MASA. Juga membutuhkan Material widget ecosystem.
✕ Terlalu Google
Lucide Icons
Consistent · 2px stroke
Bagus dan consistent, tapi 2px stroke terlalu tebal untuk ukuran kecil. Lebih cocok untuk web app. Bisa jadi fallback.
~ Fallback option
Keputusan final: Phosphor Icons Regular sebagai library utama. Alasan: (1) stroke 1.5px optimal untuk 20–24px, (2) rounded corners sesuai brand "tenang", (3) 7000+ icon termasuk kategori yang dibutuhkan MASA, (4) free open-source MIT license, (5) tersedia sebagai Flutter package (phosphor_flutter) dan SVG.

24px Icon Grid

Semua icon MASA didesain pada grid 24×24px. Grid mendefinisikan live area, padding, dan keyline — memastikan semua icon terasa konsisten secara visual weight.

Icon Grid Anatomy
24px bounding box 2px padding 20px live area keylines
Grid Specifications
ElementValueKeterangan
Bounding Box24 × 24pxTotal ukuran icon SVG viewBox
Live Area20 × 20pxArea dimana artwork boleh ada (2px padding setiap sisi)
Padding2px semua sisiBreathing room — tidak boleh ada artwork di sini
Circle keyline⌀18pxReferensi untuk icon berbentuk bulat
Square keyline16 × 16pxReferensi untuk icon berbentuk kotak
Stroke weight1.5pxKonsisten di semua icon. Minimum 1px untuk detail kecil.
Stroke caproundstroke-linecap: round; stroke-linejoin: round;
Corner radius1–2pxUntuk icon yang punya corner (buku, kartu, dll)
Aturan optical correction: Icon bulat (lingkaran, oval) secara visual terasa lebih kecil dari icon kotak dengan ukuran yang sama. Kompensasi: buat diameter lingkaran 2–4% lebih besar dari square keyline agar terasa seimbang secara visual.

Sizes & Touch Targets

4 ukuran icon yang digunakan di MASA. Visual size berbeda dari touch target — semua tappable element membutuhkan minimum 44×44px touch area.

Size nameVisualTouch areaStrokePenggunaan
icon-xs16px1.5pxBadge icon, status indicator kecil. Tidak standalone — selalu dalam konteks teks atau komponen.
icon-sm20px44×44px wrapper1.5pxBottom nav items (aktif/tidak aktif), inline icon dalam teks, list trailing.
icon-md24px44×44px wrapper1.5pxDEFAULT. Semua icon standalone, puck grid, Top App Bar actions, form labels.
icon-lg32px52×52px wrapper1.5–2pxEmpty state illustration, feature hero icon, onboarding illustration.
icon-xl48px64×64px wrapper2pxSuccess state check, splash screen, milestone illustration. Sangat jarang.

Visual comparison

16px · xs
20px · sm
24px · md ★
32px · lg
48px · xl
Touch target rule: Semua icon yang bisa di-tap WAJIB di-wrap dengan container 44×44px minimum. Di Flutter gunakan IconButton (default 48×48) atau InkWell dengan constraints: BoxConstraints(minWidth:44, minHeight:44). Jangan biarkan user tap pada icon 20px tanpa wrapper.

Icon Color Tokens

Icon mengikuti token warna yang sudah didefinisikan di Color System. Tidak ada warna custom untuk icon. 6 use case warna.

--ink-0 (#14110E)
Primary icon
Icon aktif, icon standalone, icon dalam konteks teks utama. Default untuk semua icon.
--ink-4 (#9A9286)
Secondary / inactive
Bottom nav inactive, placeholder icon, disabled icon, trailing icon yang tidak penting.
--blue-700 (#005E8C)
Interactive / action
Search icon dalam focus state, icon dalam blue accent card (NOW zone), link icon, info icon.
--green-500 (#2D6A4F)
Success / verified
Check icon dalam success state, verification icon, habit tracker icon, LazisMu badge icon.
--err-700 (#8E2A2A)
Error / warning
Error state icon, warning icon, delete/destructive action icon. Jangan gunakan untuk hal lain.
#ffffff
Inverse (on dark)
Icon pada latar belakang gelap: e-KTAM card, splash screen, success overlay, FAB.

Stroke & Fill Rules

Kapan gunakan outline, kapan gunakan filled, dan bagaimana menggunakan keduanya untuk menyampaikan state.

Outline (Regular) — Default
Gunakan untuk semua icon dalam keadaan default / tidak aktif. Terasa lebih ringan dan tidak dominan.
Bottom nav (inactive), list icon, action icon, empty state
Fill (Bold) — Active State
Gunakan untuk icon dalam keadaan aktif / selected. Filled terasa lebih "berat" secara visual — cocok untuk menandai state aktif.
Bottom nav (active), selected tab, bookmark yang sudah disimpan

State transition: outline → filled

Home inactive
Home active
|
Bookmark off
Bookmark on
|
Heart outline
Heart filled

Navigation Icons

Icon untuk navigasi utama: Bottom Nav, Top App Bar, dan breadcrumb. Setiap icon bottom nav punya versi outline (inactive) dan filled (active).

Bottom Navigation 5 pairs
house
house (filled)
book
book (filled)
newspaper
newspaper (filled)
user
user (filled)
Top App Bar 8 icons
arrow-left (back)
x (close)
search
settings
share
more-h (···)
bell (notif)
bookmark

Action Icons

Icon untuk aksi user — tap, submit, confirm, cancel. Semua dari Phosphor Icons Regular.

Payment & Transaction 10 icons
credit-card
dollar (nominal)
check
x (cancel)
upload (share)
download (receipt)
cart (qurban order)
refresh (retry)
table (iuran list)
file-text (kuitansi)
Form & Input 8 icons
edit
trash (delete)
plus-circle
chevron-down
chevron-right
search
filter
info

Ibadah Icons

Icon khusus untuk fitur ibadah. Dibuat dengan kehati-hatian — representasi yang menghormati konteks Islam tanpa menjadi berlebihan atau terlalu literal.

Islamic sensitivity note: Beberapa representasi dalam konteks Islam memerlukan kehati-hatian. Kami tidak menggunakan: representasi figuratif manusia dalam posisi ibadah, gambar ka'bah yang terlalu detail, atau arabesque yang berlebihan. Kami menggunakan: metaphor yang clean dan universal.
Ibadah Core 12 icons
book (Qur'an)
clock (salat)
hands (doa)
compass (kiblat)
calendar (KHGT)
moon (isya/subuh)
sun (dzuhur)
sunset (maghrib)
star (fav doa)
bell (adzan notif)
map-pin (lokasi)
volume (tilawah)

Trust & Identity

Icon untuk fitur yang berhubungan dengan kepercayaan, keanggotaan, dan identitas Muhammadiyah.

Membership & KTAM 8 icons
id-card (KTAM)
qr-code
iuran (payment)
users (ranting)
shield-check
award (badge)
buildings (org)
hash (NBM)
Donation & Giving 8 icons
heart (sedekah)
heart (filled)
calc (zakat)
qurban icon
heart (donasi)
flame (streak)
chart-line (progress)
users (impact)

Content & Media

Icon untuk fitur konten: Berita, Video, Event, ChatHPT.

Content Icons 12 icons
newspaper
video
calendar-check
chat-plus (HPT)
play-circle
chat (comment)
file (artikel)
share-2
link (external)
image (photo)
send (submit)
clock (timeline)

Feedback & Status

Icon untuk state feedback: sukses, error, warning, info, loading. Konsisten di seluruh app.

Status Icons 10 icons
check-circle
x-circle (error)
warning
info
spinner (loader)
download (PDF)
phone
mail
QR scanner
sun-dim (ambient)

Context Examples

Bagaimana icon digunakan dalam konteks komponen nyata.

Bottom Navigation — outline vs filled

Beranda
Ibadah
Konten
Saya

Puck Grid — 8 icon dengan label

Qur'an
Salat
Sedekah
Doa
Zakat
Qurban
Event
Semua

Icon Anti-patterns

✕ Jangan
  • Mix gaya dalam satu screen (outline + filled + filled-outline)
  • Icon tanpa label untuk fungsi yang tidak universal
  • Icon <16px tanpa context teks
  • Warna icon yang tidak dari token (hardcode hex)
  • Icon decorative yang tidak menambah makna
  • Icon berbeda untuk konsep yang sama di screen berbeda
  • Rotate/flip icon yang bukan arrow/directional
  • Gunakan emoji sebagai pengganti icon di production
  • Icon tanpa alt text / semanticLabel untuk screen reader
  • Scale icon dengan CSS transform (gunakan SVG size attribute)
✓ Lakukan
  • Satu style konsisten per screen (outline default, filled active)
  • Selalu sertakan label teks untuk navigasi dan fitur
  • Minimum 24px untuk icon standalone
  • Selalu gunakan token warna dari Color System
  • Setiap icon punya semanticLabel untuk aksesibilitas
  • Icon yang sama untuk konsep yang sama di seluruh app
  • Test icon pada background gelap (e-KTAM, splash)
  • Gunakan filled variant hanya untuk state aktif
  • Wrap semua tappable icon dengan 44×44px container
  • Pastikan contrast ratio icon ≥3:1 terhadap background

Flutter Implementation

Dua cara implement iconography di Flutter: menggunakan package phosphor_flutter atau load SVG dengan flutter_svg.

Option 1 — phosphor_flutter package (recommended)

# pubspec.yaml dependencies: phosphor_flutter: ^2.0.0 // usage in widget: import 'package:phosphor_flutter/phosphor_flutter.dart'; // Standard 24px outline (default) PhosphorIcon( PhosphorIcons.book(), // outline/regular size: 24, color: MasaColors.ink0, semanticLabel: 'Al-Qur\'an', // WAJIB untuk aksesibilitas ) // Active/filled state (bottom nav active) PhosphorIcon( PhosphorIcons.book(PhosphorIconsStyle.fill), size: 24, color: MasaColors.ink0, semanticLabel: 'Al-Qur\'an, aktif', ) // Inline in bottom nav: NavigationDestination( icon: PhosphorIcon(PhosphorIcons.house()), selectedIcon: PhosphorIcon( PhosphorIcons.house(PhosphorIconsStyle.fill), color: MasaColors.ink0, ), label: 'Beranda', )

Option 2 — flutter_svg (untuk icon custom MASA-specific)

# pubspec.yaml dependencies: flutter_svg: ^2.0.0 // assets/icons/ — folder untuk semua SVG custom // pubspec.yaml assets: flutter: assets: - assets/icons/ // usage: SvgPicture.asset( 'assets/icons/qurban.svg', width: 24, height: 24, colorFilter: ColorFilter.mode( MasaColors.ink0, BlendMode.srcIn, ), semanticsLabel: 'Qurban', )

MasaIcon widget — wrapper untuk konsistensi

// lib/shared/widgets/masa_icon.dart // Wrapper yang enforce sizing, touch target, dan semanticLabel class MasaIcon extends StatelessWidget { const MasaIcon({ required this.icon, required this.semanticLabel, this.size = 24, this.color, this.onTap, }); final IconData icon; final String semanticLabel; final double size; final Color? color; final VoidCallback? onTap; @override Widget build(BuildContext context) { final iconWidget = Icon( icon, size: size, color: color ?? MasaColors.ink0, semanticLabel: semanticLabel, ); if (onTap == null) return iconWidget; // Tappable: enforce 44x44 minimum touch target return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(99), child: Container( constraints: const BoxConstraints( minWidth: 44, minHeight: 44, ), alignment: Alignment.center, child: iconWidget, ), ); } }

Icon naming convention

PatternContohKeterangan
PhosphorIcons.{name}()PhosphorIcons.book()Outline/Regular — default, inactive
PhosphorIcons.{name}(fill)PhosphorIcons.book(PhosphorIconsStyle.fill)Filled — active, selected state
assets/icons/masa_{name}.svgmasa_qurban.svg, masa_kiblat.svgCustom MASA-specific icons tidak ada di Phosphor
semanticLabel wajib"Al-Qur'an" / "Al-Qur'an, aktif"Untuk screen reader aksesibilitas — selalu dalam Bahasa Indonesia
Index · UI Components · Motion Tokens Iconography System v1.0 · 15 Jun 2026