FixNeeds Refinement
Menu Grid Component link

A 2D grid of icon-and-label tiles used for top-level service navigation.

Open issues remain
Variant property values use pseudo-numeric strings ("by 4") instead of integers (C2). Service Item only ships an active color set — no pressed/disabled tokens (C5). Code Connect mappings not yet registered (C7).

Contexts are illustrative. Final screens will reference actual GCash patterns. Menu Grid sits on the dashboard as the primary service shortcut surface — typically Row=2, Column=4 (8 services) on the home screen.

GCash
LabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabel
Properties
Row
Column
Reusable
Pass
Used on dashboard surfaces and any screen needing a uniform service shortcut grid. 20 row/column combinations cover most layout needs from a single column list to a 5×5 grid.
Self-contained
Pass
Container carries its own background, padding (8h / 10t / 6b), gap (4×4), and bottom radius (6). All values bound to design tokens.
Consistent
Warn
Variant property values are pseudo-numeric strings ("by 4") instead of clean integer enums. Should be rows: 4 / columns: 4 for native parity. C2
Composable
Pass
Cleanly composes Service Item instances (node 17787:1700). Service Item is a separate canonical component — icon and label are easily overridable per cell.
State iOS Android Figma Property Notes
Default Yes Yes Row × Column Active state only — uses dashboard/service-item/color/active/{icon,label}
Pressed N/A N/A No pressed token defined for Service Item. Native may need to derive from icon brand color. C5
Disabled N/A N/A No disabled token defined. C5
  • Variant values use pseudo-numeric strings. Row="by 4", Column="by 4" can't map cleanly to native ints or enums. Should be plain integers (rows: 4, columns: 4). C2 · Variant & Property Naming
  • Service Item only defines an active color set. No pressed or disabled tokens exist — engineers must invent these colors on native. C5 · Interaction State Coverage
  • Code Connect mappings not registered. Blocked until the variant explosion and token gaps are addressed. C7 · Code Connect Linkability
  • Replace the 20-variant matrix with two integer props. rows and columns as ints. Variant explosion is a Figma-only construct; native uses a lazy grid that takes any int. Could collapse to ~1–2 variants. Property
  • Add pressed and disabled color tokens. Extend dashboard/service-item/color/* so all states are documented at the token layer, not improvised in code. Token
  • Promote Service Item to a first-class DS component. It's currently a child of Menu Grid but is reused independently across other surfaces. Publishing it standalone (same pattern as Avatar + Avatar Group) makes reuse explicit. Family
Styles
Row 2 × Column 4 — 8 services (most common)
DES DEV

The default dashboard layout — 2 rows × 4 columns = 8 services. Used on the home dashboard for primary service shortcuts.

LabelLabelLabelLabelLabelLabelLabelLabel
Properties
Row
Column
Properties
Row 2
Column 4
Grid 4-column
Colors
Active icon #005CE5
Active label #072592
Surface #FFFFFF
Divider #E5EBF4
Layout
Tile size square (auto by column count)
Icon size 40 × 40
Padding 10 vertical · 8 horizontal
Border radius radius/radius-2 (6px)
Typography
Label style Primary/Label/Fine
Label font Proxima Soft Bold · 12 / 12 · +0.5
Colors by State

Service Item ships only the active color set. Pressed and disabled are not yet defined at the token layer — see C5 in the Open Issues.

Role Token Value
Container bg bg/color-bg-main #FFFFFF
Service icon dashboard/service-item/color/active/icon #005CE5
Service label dashboard/service-item/color/active/label #072592
Border (weak) border/color-border-weak #E5EBF4
Row 4 × Column 4 — 16 services
DES DEV

Expanded grid for "All Services" sheets — 4 rows × 4 columns = 16 services. Used on category pages or full-list views.

LabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabel
Properties
Row
Column
Properties
Row 4
Column 4
Grid 4-column
Colors
Active icon #005CE5
Active label #072592
Surface #FFFFFF
Divider #E5EBF4
Layout
Tile size square (auto by column count)
Icon size 40 × 40
Padding 10 vertical · 8 horizontal
Border radius radius/radius-2 (6px)
Typography
Label style Primary/Label/Fine
Label font Proxima Soft Bold · 12 / 12 · +0.5
Layout
Role Token Value
Container width 336px (fixed)
Padding (horizontal) space/space-8 8px
Padding (top) space/space-10 10px
Padding (bottom) space/space-6 6px
Cell gap (row & col) space/space-4 4px
Bottom radius radius/radius-2 6px
Service Item min-width 64px
Service Item icon container 40 × 40
Icon padding space/space-4 4px
Icon → label gap space/space-6 6px
Row 5 × Column 5 — 25 services (max)
DES DEV

Maximum density — 5 rows × 5 columns = 25 services. Use sparingly; label legibility tightens at this density.

LabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabelLabel
Properties
Row
Column
Properties
Row 5
Column 5
Grid 5-column
Colors
Active icon #005CE5
Active label #072592
Surface #FFFFFF
Divider #E5EBF4
Layout
Tile size square (auto by column count)
Icon size 40 × 40
Padding 10 vertical · 8 horizontal
Border radius radius/radius-2 (6px)
Typography
Label style Primary/Label/Fine
Label font Proxima Soft Bold · 12 / 12 · +0.5
Typography (Service Item Label)
Role Token
DS text style Primary/Label/Fine
Font Proxima Soft
Weight 700 (Bold)
Size 12px
Line height 12px
Tracking +0.5
Alignment center

iOS — Swift Package Manager

// In Xcode: File → Add Package Dependencies
"https://github.com/AY-Org/eb-ds-ios"

Android — Gradle (Kotlin DSL)

dependencies {
    implementation("com.eastblue.ds:menu-grid:1.0.0")
}
Figma PropertySwiftUICompose
Row="by N" rows: Int rows: Int
Column="by N" columns: Int columns: Int
Service Item (instance) items: [EBServiceItem] items: List<EBServiceItem>
SwiftUI
ios/Components/MenuGrid/EBMenuGrid.swift
Jetpack Compose
android/components/menugrid/EBMenuGrid.kt
// Default dashboard grid — 2 rows × 4 columns
EBMenuGrid(columns: 4, items: services)

// Service Item child
EBServiceItem(
    icon: Image("send-money"),
    label: "Send Money",
    action: { /* tap */ }
)
// Default dashboard grid — 2 rows × 4 columns
EBMenuGrid(
    columns = 4,
    items = services
)

// Service Item child
EBServiceItem(
    icon = painterResource(R.drawable.send_money),
    label = "Send Money",
    onClick = { /* tap */ }
)
RequirementiOSAndroid
Tap target Service Item is 64+ px wide × ~64 px tall — meets HIG 44pt minimum Meets Material 48dp minimum
Accessibility label .accessibilityLabel(label) on each item contentDescription = label
Grid semantics Container exposes grid traits via LazyVGrid LazyVerticalGrid announces row/column position
Disabled state Currently undefined — needs token + .disabled(true) handling Currently undefined — needs token + enabled = false

Do

Use Row=2 × Column=4 for the primary dashboard surface — 8 services is the established home pattern.

Don't

Use Row=5 × Column=5 unless density is essential — 25 cells reduces label legibility.

Do

Pair Menu Grid with a section heading or container card so users understand the grouping.

Don't

Mix icon styles within a single grid — keep all Service Item icons in the same vector style.

ID Criterion Status Notes
C1 Layer Structure & Naming Ready Semantic names: Service Item, icon-container, Label. No Frame/Group debris.
C2 Variant & Property Naming Requires Rework Property values are pseudo-numeric strings ("by 4") instead of integers. Native takes Int.
C3 Token Coverage Ready All colors, spacing, radii, and typography bound to tokens.
C4 Native Mappability Needs Refinement Maps to LazyVGrid / LazyVerticalGrid. The 20-variant matrix is Figma-only — native uses one component with two int props.
C5 Interaction State Coverage Requires Rework Only active token defined. No pressed or disabled color tokens for Service Item.
C6 Asset & Icon Quality Ready Icon container is a vector instance, token-bound color.
C7 Code Connect Linkability Needs Refinement No CLI mappings registered yet.

4 Row × 5 Column = 20 variants. All variants share the same 336px container, 4×4 cell gap, and Service Item child.

RowColumnsCell rangeCount
by 2by 1, 2, 3, 4, 52 – 105
by 3by 1, 2, 3, 4, 53 – 155
by 4by 1, 2, 3, 4, 54 – 205
by 5by 1, 2, 3, 4, 55 – 255
Initial Assessment · node 18320:14332
Component assessed — 20 variants formed by Row × Column (Row 2/3/4/5, Column 1/2/3/4/5). Layout container of Service Item children. 336px fixed width. Documented
Initial
Variant property values are strings, not integersRow="by 4", Column="by 4". Native takes Int; the string prefix forces parsing. Open
C2 Open
Service Item missing pressed/disabled tokens — Only dashboard/service-item/color/active/{icon,label} defined. Other states must be improvised. Open
C5 Open
Code Connect mappings — No CLI mappings registered yet. Open
C7 Open