Lewati ke konten utama

🧩 Component Specification

Target: Figma master components for Amal E-Santri Design System Used by: Designer (untuk build components) + Flutter Developer (nanti saat implement) Total components: 12 atoms + molecules + organisms


🧬 ATOMS

1. Button

Purpose: Primary action trigger dengan varian semantic dan size.

Component Properties:

PropertyTypeValuesDefault
variantVariantprimary, secondary, tertiary, danger, ghostprimary
sizeVariantxs, sm, md, lgmd
stateVariantdefault, hover, pressed, loading, disableddefault
iconVariantnone, leading, trailing, onlynone
widthVarianthug, fillhug
labelText"Button"
iconNameInstance swapAny icon

Sizing spec:

SizeHeightPadding HPadding VGapFontIcon
xs28px12px4px4pxbody-sm 50014px
sm36px16px8px6pxbody-sm 60016px
md44px20px12px8pxbody 60018px
lg52px24px14px10pxbody-lg 60020px

Style per variant (Light mode):

VariantBGTextBorderShadow
primarybrand/primary (emerald-600)text/on-primary (white)noneshadow/sm
secondarysurface/card (white)brand/primaryborder/defaultnone
tertiarytransparentbrand/primarynonenone
dangerfeedback/error (red-500)whitenoneshadow/sm
ghostsurface/variant (zinc-100)text/primarynonenone

State style modifiers:

  • hover: lighten BG 5%, add subtle shadow
  • pressed: darken BG 10%, remove shadow
  • loading: show spinner, disable click, opacity 0.8
  • disabled: opacity 0.4, cursor not-allowed, no hover effect

Border radius: radius/md (12px) for all sizes

Usage do's:

  • ✅ Use primary untuk ONE primary action per screen
  • ✅ Use secondary untuk alternative action (e.g. "Cancel", "Lihat Detail")
  • ✅ Use tertiary untuk inline text-style action
  • ✅ Use danger untuk destructive (delete, keluar)
  • ✅ Use ghost untuk tertiary action dalam form/list

Usage don'ts:

  • ❌ Jangan pakai 2 primary buttons berdampingan
  • ❌ Jangan pakai xs di primary CTA
  • ❌ Jangan override color manually — pakai variant

2. Chip

Purpose: Compact label untuk status, category, atau filter.

Component Properties:

PropertyTypeValuesDefault
semanticVarianthadir, izin, sakit, alpha, terlambat, lunas, belum-bayar, overdue, neutralneutral
styleVarianttonal, filled, outlinedtonal
sizeVariantsm, mdsm
hasIconBooleantrue/falsefalse
labelText"Chip"

Sizing spec:

SizeHeightPadding HPadding VGapFont
sm20px8px2px4px11px 600
md24px12px4px4px12px 600

Style per semantic (tonal variant):

Semua pattern: bg: {semantic}-bg, text: {semantic}, border: none

SemanticBGText
hadirstatus/hadir-bg (emerald-50)status/hadir (emerald-700)
izinstatus/izin-bg (amber-50)status/izin (amber-700)
sakitstatus/sakit-bg (blue-50)status/sakit (blue-700)
alphastatus/alpha-bg (red-50)status/alpha (red-700)
terlambatstatus/terlambat-bg (orange-50)status/terlambat (orange-700)
lunasstatus/lunas-bg (emerald-50)status/lunas (emerald-700)
belum-bayarstatus/belum-bayar-bg (amber-50)status/belum-bayar (amber-700)
overduestatus/overdue-bg (red-50)status/overdue (red-700)
neutralsurface/variant (zinc-100)text/secondary

Border radius: radius/sm (8px) atau radius/full untuk pill-style


3. Avatar

Purpose: Representasi user/student dengan foto atau inisial.

Component Properties:

PropertyTypeValuesDefault
sizeVariantxs, sm, md, lg, xlmd
typeVariantimage, initials, glassinitials
badgeVariantnone, dot, numbernone
borderVariantnone, solid, glassnone
initialsText"AF"
imageSrcImage fill
badgeContentText"1"

Sizing spec:

SizeDiameterFont (initials)Badge offset
xs24px10px 600top-right 2px
sm32px12px 700top-right 2px
md40px14px 700top-right 2px
lg56px18px 700top-right 4px
xl80px24px 700top-right 6px

Glass variant (digunakan di hero card di atas gradient):

  • BG: rgba(255, 255, 255, 0.18)
  • Border: 1px solid rgba(255, 255, 255, 0.3)
  • Backdrop blur: 10px
  • Text: white

Color generation logic (for initials): Pakai deterministic hash dari nama → pick dari palette:

  • emerald-100 / emerald-700
  • amber-100 / amber-700
  • blue-100 / blue-700
  • pink-100 / pink-700
  • purple-100 / purple-700

4. Icon

Purpose: Standardized icon wrapper dengan token-based sizing.

Component Properties:

PropertyTypeValuesDefault
sizeVariantsm (16), md (20), lg (24), xl (32)md
colorToken refAny color tokentext/primary
iconNameInstance swapMaterial Symbol

Rules:

  • Library: Material Symbols Rounded (recommended — modern + free) atau Phosphor
  • Stroke width konsisten: 2px
  • Color HARUS reference token (tidak hardcode)

🔬 MOLECULES

5. Card

Purpose: Container untuk konten grouped.

Component Properties:

PropertyTypeValuesDefault
variantVariantflat, elevated, outlinedflat
radiusVariantmd, lg, xllg
paddingVariantsm (12), md (16), lg (20)md
hasActionBooleanfalse
interactiveBooleanfalse

Style per variant:

VariantBGBorderShadow
flatsurface/cardnonenone
elevatedsurface/cardnoneshadow/card
outlinedsurface/cardborder/default 1pxnone

Interactive state:

  • Add hover shadow pada elevated
  • Add pressed scale 0.98 feedback

6. TextField

Purpose: Form input dengan 7 states.

Component Properties:

PropertyTypeValuesDefault
stateVariantempty, focused, filled, error, disabled, success, loadingempty
sizeVariantsm, md, lgmd
hasLabelBooleantrue
hasLeadingIconBooleanfalse
hasTrailingIconBooleanfalse
hasHelperTextBooleanfalse
hasCharCountBooleanfalse
labelText"Label"
valueText""
placeholderText"Placeholder"
helperTextText"Helper"

Sizing spec:

SizeHeightPaddingFont
sm36px12pxbody-sm
md48px14pxbody
lg56px16pxbody-lg

State colors:

StateBorderLabelTextBG
emptyborder/defaulttext/secondarysurface/card
focusedborder/focus 2pxborder/focustext/primarysurface/card
filledborder/defaulttext/secondarytext/primarysurface/card
errorfeedback/errorfeedback/error-texttext/primarysurface/card
disabledborder/defaulttext/disabledtext/disabledsurface/variant
successfeedback/successfeedback/success-texttext/primarysurface/card
loadingborder/defaulttext/secondarytext/primarysurface/card (shimmer overlay)

Border radius: radius/md (12px)


7. AppBar

Purpose: Top navigation bar per screen.

Component Properties:

PropertyTypeValuesDefault
variantVariantdefault, with-back, with-action, large-titledefault
titleText"Title"
hasSubtitleBooleanfalse
subtitleText"Subtitle"
trailingActionCountVariant0, 1, 20

Layout spec:

  • Height: 56px (default), 96px (large-title)
  • BG: surface/appbar
  • Shadow: 0 1px 4px rgba(0,0,0,0.04) (on scroll only)
  • Padding: 16px horizontal, 0 vertical (content centered vertically)

Status bar: match ke light/dark mode context.


8. BottomNav

Purpose: Persona-aware bottom navigation.

Component Properties:

PropertyTypeValuesDefault
personaVariantparent, guru, walikelas, bendahara, admin, kepsekparent
activeTabVariantdepends on persona
badgeOnTabVariantnone, tab1, tab2, tab3, tab4, tab5, tab6none

Layout per persona:

Parent (6 tabs):

TabIconLabelRoute
1homeBerandaparent.dashboard
2receipt-textTagihanparent.billing
3piggy-bankTabunganparent.savings
4schoolNilaiparent.grades
5calendar-checkAbsensiparent.attendance
6accountProfilparent.profile

Sizing:

  • Height: 68px (including safe area)
  • Bg: surface/bottomtab
  • Top border/shadow: shadow/bottomtab
  • Tab min-width: 100% / tab-count
  • Icon size: 22px
  • Label: 10-11px semibold
  • Active indicator: 28×3px pill di atas icon, color brand/primary

Safe area handling:

  • Android: adjust bottom padding via env(safe-area-inset-bottom) (CSS) atau MediaQuery.viewPadding.bottom (Flutter)
  • iOS: auto-handled via SafeArea widget

🧱 ORGANISMS

9. HeroCard (untuk Dashboard)

Purpose: Greeting + context hero block di top dashboard.

Component Properties:

PropertyTypeValuesDefault
personaVariantparent, guru, walikelasparent
hasChildSwitcherBooleantrue (parent)
greetingText"Assalamu'alaikum"
nameText"Fatimah"
subtitleText"Semoga hari Anda penuh keberkahan"
childNameText"Ahmad Fauzan"
childClassText"Kelas VII-A"
hijriDateText"8 Syawal 1447"

Layout spec:

  • Width: screen - 32 (16px margin tiap sisi)
  • Height: 168px
  • Border radius: radius/xl (20px)
  • Padding: 24px (all sides)
  • BG gradient (parent): linear-gradient(156deg, #057E6B 0%, #065F53 42%, #06443E 100%)
  • BG gradient (guru): linear-gradient(156deg, #0D9488 0%, #0F766E 42%, #115E59 100%)
  • Shadow: 0 8px 24px rgba(5, 150, 105, 0.25) (colored, brand)

Internal structure (Auto Layout):

HeroCard (VStack, gap 0)
├── Decor Layer (absolute, z-index below content)
│ ├── Rotated square 1 (top-right, 120×120, border alpha 0.08)
│ └── Rotated square 2 (top-right offset, 80×80, border alpha 0.08)
├── Top Row (VStack, gap 4)
│ ├── Greeting Label (micro-label, white/60)
│ ├── Name (display, bold, white)
│ └── Subtitle (body-sm, white/75)
├── Divider (1px, white/12, margin-y 16)
└── Bottom Row (HStack, space-between)
├── Child Switcher Card (glass, interactive)
│ ├── Avatar (glass xs, initials)
│ └── Info (VStack, gap 2)
│ ├── Label (micro-label, white/50)
│ └── Text (body-sm semibold, white)
└── Hijri Date Pill (glass, chip-like)
├── Icon (16px, white)
└── Text (micro-label, white)

10. QuickActionCard

Purpose: Grid item untuk quick action di Akses Cepat section.

Component Properties:

PropertyTypeValuesDefault
variantVariantdefault, activedefault
hasNotificationBooleanfalse
labelText"Tagihan"
iconNameInstance swapAny icon

Sizing spec:

  • Width: (screen - 32 - 3*8) / 4 ≈ 88px (for 4-col grid with 8px gap, 16px side margin)
  • Height: 84px
  • Border radius: radius/md (14px — special 14px)
  • Padding: 12px
  • Internal gap: 8px

Style per variant:

VariantBGBorderShadow
defaultsurface/cardborder/defaultnone
activesurface/success-bg (emerald-50)#86efac (emerald-300)shadow/sm tinted emerald

Notification dot:

  • 5×5 circle, feedback/error (red-500)
  • Position: top-right, offset 7px dari corner

11. EmptyState

Purpose: Consistent empty/error state pattern.

Component Properties:

PropertyTypeValuesDefault
variantVariantsuccess, waiting, offline, errorwaiting
headlineText"Tidak Ada Data"
subtextText"Subtext description"
hasPrimaryCTABooleanfalse
hasSecondaryCTABooleanfalse
primaryLabelText"Coba Lagi"
secondaryLabelText"Hubungi Support"

Icon & color per variant:

VariantIconIcon colorCircle BGUse case
successcheck-circle atau receiptfeedback/successfeedback/success-bg"Semua lunas — Alhamdulillah!"
waitingclock atau hourglassfeedback/infofeedback/info-bg"Nilai belum di-input"
offlinewifi-offfeedback/errorfeedback/error-bg"Tidak ada koneksi"
erroralert-trianglefeedback/warningfeedback/warning-bg"Server error"

CTA behavior:

  • success variant: tidak ada CTA (celebratory, terminal state)
  • waiting variant: tidak ada CTA (waiting on others) — opsional secondary "Hubungi Wali Kelas"
  • offline variant: primary CTA "Coba Lagi" (filled)
  • error variant: primary CTA "Coba Lagi" (filled) + secondary "Hubungi Support"

CTA style: SELALU primary filled (emerald-600). Jangan outline untuk retry action.

Layout spec:

EmptyState (VStack, centered, gap 16)
├── Circle icon wrapper (140×140, border-radius full)
│ └── Icon (64px)
├── Spacing (32px)
├── Headline (h2 semibold, text-primary, center)
├── Spacing (8px)
├── Subtext (body-sm, text-secondary, center, max 2 lines)
├── Spacing (24px)
├── Primary CTA (Button primary md, centered) [conditional]
├── Spacing (8px)
└── Secondary CTA (Button tertiary md, centered) [conditional]

12. SkeletonLoader

Purpose: Placeholder shimmer saat loading data.

Component Properties:

PropertyTypeValuesDefault
typeVariantlist-item, card, dashboard, detaillist-item

Visual spec:

  • Color: surface/variant (zinc-100) base
  • Shimmer: linear-gradient animation, 1.5s loop
  • Border radius: match actual content radius

Type variations:

list-item:

[Circle 40] [Rect 70% height 14] [Rect 50% height 12]

card:

[Rect 100% height 120]
[Rect 80% height 16]
[Rect 60% height 14]

dashboard:

[Hero rect 100% height 168]
[Grid 2x2 card: rect 100% height 100 × 4]
[List: list-item × 3]

detail:

[AppBar placeholder]
[Hero rect]
[Content blocks × 3]

🔄 COMPONENT DEPENDENCY GRAPH

Atoms Molecules Organisms
───── ───────── ─────────
Icon ─────┬─> Card ─────┬─> HeroCard
Button ────┤ TextField ────┤ QuickActionCard
Chip ─────┤ AppBar ────┤ EmptyState (uses Button)
Avatar ────┘ BottomNav ────┘ SkeletonLoader
(Future: BillCard, ScheduleWidget, etc)

Build order: Atoms → Molecules → Organisms. Never skip.


📖 Usage Pattern Examples

Example 1: Parent Dashboard

Screen Frame
├── AppBar (variant: default, hasAction: bell + avatar)
├── ScrollContent (VStack, gap 16, padding 16)
│ ├── HeroCard (persona: parent, hasChildSwitcher: true)
│ ├── AttendanceStrip (Card variant: outlined, emerald tint)
│ │ └── [Chip semantic: hadir] + Text
│ ├── Section "Akses Cepat"
│ │ └── Grid (4 columns, 8px gap)
│ │ └── QuickActionCard × 8 (2 dengan hasNotification)
│ ├── Section "Hari Ini"
│ │ └── LiveClassWidget (Card variant: elevated)
│ ├── HafalanWidget (Card)
│ └── ChatTeaser (Card)
└── BottomNav (persona: parent, activeTab: tab1)

Example 2: Empty Tagihan Screen

Screen Frame
├── AppBar (variant: default, title: "Tagihan")
├── EmptyState (variant: success, headline: "Tidak Ada Tagihan", subtext: "Semua tagihan sudah lunas. Alhamdulillah!")
└── BottomNav (persona: parent, activeTab: tab2)

✅ Validation Criteria

Component dianggap "done" jika:

  • Semua Component Properties defined
  • Semua variants ada (test dengan swap variants di Dev Mode)
  • Semua values pakai tokens (0 hardcode)
  • Auto Layout complete (no manual positioning)
  • Dark mode works via theme switch
  • Contrast check pass (use Stark plugin)
  • Documented di Component Library page
  • Published ke team library

Status: Spec ready untuk designer build Last updated: 2026-04-16 Version: 1.0