RestructureRequires Rework
Action List Component link

A row primitive used in lists of tappable rows — title, optional trailing CTA, and chevron.

Collapse 3 siblings into one slot-driven row
The three components differ by presence — a description line, a trailing counter — not by role. Replace with one List component with description?: String, trailing: .cta | .counter | .chevron | .none, plus a named leading slot for the icon. Align label typography across the family (currently Semibold 16 Neutral vs. Bold 18 Brand). Add a Pressed state — these rows are primary nav targets. Reconcile with List Item (display-only body rows) and clarify when to use which.
In Context

Action-list rows stack inside Settings / Profile / Help menus. A typical screen mixes variants with/without description and with/without trailing counter.

Settings View 3
Live Preview
Label
CTA
Shape
variant
state
density
Content
label
description
counter
DS Health
Reusable
Pass
Used across Settings, Help Center, Profile, Wallet sub-screens. Covers the main action-list row patterns.
Self-contained
Partial
Colors and padding bound to main/action-list/* tokens. Loading skeleton uses bg/color-bg-strong for placeholders. Leaked internal spacer annotations (_space_2, _space_16) are rendered inside production instances. C1
Consistent
Warn
Three sibling components encode a single row pattern by presence. Label typography diverges: List and List - with Description use Semibold 16 Neutral (#0A2757); List - with Counter uses Bold 18 Brand Blue (#005CE5). C2
Composable
Warn
Leading icon is an always-gray placeholder circle, not a Figma Slot. Trailing content is baked into each sibling rather than driven by a trailing enum. C4 C6
Behavior
State iOS Android Figma Property Notes
Default Yes Yes State=Default Baseline row. Label in Neutral Dark (or Brand Blue on the Counter variant).
Disabled Yes Yes State=Disabled Label → #C2CFE5, chevron → #9BC5FD, CTA → #9BC5FD, counter bg stays #EEF2F9 but label → #C2CFE5.
Loading Yes Yes State=Loading Icon becomes a neutral ring; label + trailing become 16 px pill placeholders filled with #EEF2F9.
Pressed N/A N/A Not built Action rows are tap targets — a pressed state (row tint + possibly label darken) is a baseline expectation for native.
Focused N/A N/A Not built TV / keyboard focus ring not defined. Android a11y also relies on it.
Open Issues
  • Three sibling components for one row pattern. List, List - with Counter, and List - with Description differ only by the presence of a description line and/or a trailing counter. Collapse into a single List component with optional description and a trailing union. C1 · Layer Structure & Naming
  • Label typography diverges across the family. List + List - with Description use Proxima Soft Semibold 16 / Neutral Dark (#0A2757). List - with Counter uses Proxima Soft Bold 18 / Brand Blue (#005CE5). Same row family should read as one thing. Pick one token (label or label-brand) and one size. C2 · Variant & Property Naming
  • Leaked spacer annotation layers. Internal _space_2 (4115:3220) and _space_16 (21:40139) annotation frames are rendered as opacity-0 layers inside every production instance. Artifacts of authoring, not part of the public component. Remove or move to a separate documentation artboard. C1 · Layer Structure & Naming
  • Leading icon is a gray placeholder. All three siblings default to a #C2C6CF filled 32 px circle under a frame named Placeholder. Same instance-swap anti-pattern as List Item. Adopt a Figma Slot so consumers can drop in a real icon (or an Avatar). C6 · Asset & Icon Quality
  • No Pressed state. These rows are the primary tap surface for navigation menus. The State enum exposes only Default / Disabled / Loading. Add Pressed (tinted bg and/or chevron darken). C5 · Interaction State Coverage
  • Trailing content is baked per sibling. CTA text lives on the base, a filled Counter lives on the Counter sibling, and a chevron appears only sometimes. Introduce a trailing enum (.cta(String) | .counter(Int) | .chevron | .none) so one component covers all three patterns. Maps cleanly to native enums. C4 · Native Mappability
  • Code Connect mappings not registered. Blocked on the consolidation + slot adoption. Adding mappings for three siblings would cement the wrong schema. C7 · Code Connect Linkability
Design Recommendations
  • Consolidate into one Action Row component. One component with properties title: String, subtitle?: String (replaces "with Description"), trailing: chevron | counter | switch | badge | none (replaces "with Counter"), state: default | pressed | disabled | loading, plus a leading slot for icon/avatar. Replaces 15 variants across 3 components with clean slot-based composition. Family
  • Add a leading Figma Slot for the icon. Maps 1:1 to @ViewBuilder (SwiftUI) and a @Composable slot (Compose). Accepts Icon, Avatar, or a custom 32 px component. Remove the placeholder fill entirely — empty slot means no leading. Slot
  • Reconcile label typography. Pick one: either Neutral Dark Semibold 16 (matches List Item + most action rows) or Brand Blue Bold 18 (matches the current Counter sibling). Neutral is the safer default — Brand Blue reads like a link, which the whole row already behaves as. Apply the choice to all three shapes. Token
  • Add Pressed (and ideally Focused) states. Pressed = bg tints to #F4F6FA, chevron / CTA darkens one step. Focused = 2 px brand ring at 2 px offset. Baseline for native row components. State
  • Remove _space_2 / _space_16 spacer annotations. These are authoring artifacts. Move to a separate "Annotations" artboard or delete once the auto-layout is settled. They export as opacity-0 layers to consumers. Composition
  • Disambiguate vs List Item. This component is tappable action navigation (icon + label + trailing CTA/counter/chevron). List Item is display body rows (bullet + text for terms/steps). Document the distinction and cross-link the two — today the names don't telegraph which is which. Docs
  • Rename the family to Action Row. "Action List" implies a collection, but each component here is a single row. Native name: EBActionRow. Disambiguates from the List container (scroll primitive) and the List Item display rows (terms/steps). Single-component consolidation eliminates the "with X" naming pattern entirely. Rename
Variants
List — icon + label + CTA + chevron
DES DEV

Baseline row. 6 variants (State × Density). Label in Neutral Dark Semibold 16. Trailing CTA text + 24 px chevron icon. 360 × 48 (compact) / 360 × 56 (expanded).

Label
CTA
Properties
State
Density
Properties
Variant List — icon + label + CTA + chevron
State Default
Density Compact
Colors
Bg #FFFFFF
Label #0A2757
Link #005CE5
Chevron #005CE5
Layout
Height 48px
Padding 8px 12px
Typography
Font Proxima Soft Semibold
Size 16px / 16px
Tracking +0.25
Colors by State
Role Token DefaultDisabledLoading
Row bg main/action-list/color/default/bg #FFFFFF #FFFFFF #FFFFFF
Label (base & with-description) main/action-list/color/default/label #0A2757 #C2CFE5
Label (with-counter) main/action-list/color/default/label-brand #005CE5 #C2CFE5
Description main/action-list/color/default/description #6780A9 #C2CFE5
Trailing CTA label main/action-list/color/default/label-link #005CE5 #9BC5FD
Chevron main/action-list/color/default/chevron #005CE5 #9BC5FD
Counter bg main/counter/color/filled/bg #EEF2F9 #EEF2F9
Counter label main/counter/color/filled/label #072592 #C2CFE5
Skeleton fill bg/color-bg-strong #EEF2F9
List - with Counter — icon + label + counter + chevron
DES DEV

Adds a trailing <a href="#" onclick="showPanelById('counter');return false;">Counter</a> pill. 6 variants (Density × State). Card-like container with <code>radius-2</code> (6 px) corners and <code>Depth/D0</code> drop-shadow — differs from the base's flat row. Label switches to Bold 18 Brand Blue. 360 × 56 / 360 × 64.

Label
3
Properties
State
Density
Properties
Variant List - with Counter — icon + label + counter + chevron
State Default
Density Compact
Colors
Bg #FFFFFF
Label #005CE5
Counter #005CE5
Chevron #005CE5
Layout
Height 56px
Padding 11px 12px
Typography
Font Proxima Soft Bold
Size 18px / 20px
Tracking +0.25
Layout
Role Token Value
Frame width 360px (fill container in product)
Row height — base 48 (compact) / 56 (expanded)
Row height — with Counter 56 (compact) / 64 (expanded)
Row height — with Description 60 (no density axis)
Icon size 32 × 32
Icon → label gap space/space-12 12px
Wrapper padding (compact) space/space-12 + 7/11 12px / 7px (compact) · 12px / 11px (expanded)
Description gap space/space-6 6px
Counter radius radius/radius-round 99999px (pill)
Counter size 24 × 24 (filled) / h24 (empty)
Card radius (with Counter) radius/radius-2 6px
Card shadow (with Counter) Depth/D0 0 1 3 0 · #E8EEF2C9
Chevron size 24 × 24 (base + with-description) / 32 × 32 (with-counter)
Spacer annotations _space_2, _space_16 leak through (opacity 0)
List - with Description — icon + label + description + CTA + chevron
DES DEV

Adds a secondary description line under the label. 3 variants (State only — no Density axis). Label matches the base (Semibold 16 Neutral). Description uses Semibold 12 / tracking-wider / <code>main/action-list/color/default/description</code> (<code>#6780A9</code>). 360 × 60.

Label
Description
CTA
Properties
State
Density
Properties
Variant List - with Description — icon + label + description + CTA + chevron
State Default
Colors
Bg #FFFFFF
Label #0A2757
Description #6780A9
Link #005CE5
Chevron #005CE5
Layout
Height 60px
Padding 8px 12px
Typography
Label font Proxima Soft Semibold · 16 / 18 · +0.25
Description font Proxima Soft Semibold · 12 / 16 · +0.4
Typography
Role Token Spec
Label — base & with-description Primary/Label/Light/Base Proxima Soft Semibold · 16 / 16 · +0.25
Label — with-counter Primary/Label/Large Proxima Soft Bold · 18 / 18 · +0.25
Description Primary/Multi-line Label/Light/Fine Proxima Soft Semibold · 12 / 14 · +0.5
Trailing CTA Primary/Label/Light/Base Proxima Soft Semibold · 16 / 16 · +0.25
Counter label Primary/Label/Small Proxima Soft Bold · 14 / 14 · +0.25
Installation Planned API

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:list:1.0.0")
}
Property Mapping
Figma PropertySwiftUICompose
3 sibling components 1 component: List EBActionListRow
icon (Placeholder) leading (Slot) @ViewBuilder leading
label: String label: String label: String
description (only on sibling) description?: String description: String?
trailingComponent (bool) / counter (bool) / chevron (bool) trailing: .cta(String) | .counter(Int) | .chevron | .none trailing: EBRowTrailing
density: Compact/Expanded density: .compact / .expanded .controlSize(.regular / .large)
state: Default/Disabled/Loading state: .default / .pressed / .disabled / .loading .disabled(Bool) + intrinsic press + loading: Bool
bottomBorder: Bool bottomBorder: Bool divider: Bool
(not modeled) onTap action: () -> Void
SwiftUI
ios/Components/List/EBActionListRow.swift
Jetpack Compose
android/components/list/EBActionListRow.kt
Usage Snippets Planned API
Usage
// Base — icon + label + CTA + chevron
EBActionListRow("Payment methods", trailing: .cta("View")) {
    Image(systemName: "creditcard.fill")
} action: { openPaymentMethods() }

// With counter — shows 3 pending items
EBActionListRow("Notifications", trailing: .counter(3)) {
    Image(systemName: "bell.fill")
} action: { openNotifications() }

// With description + chevron
EBActionListRow(
    "Profile",
    description: "Name, photo, and contact info",
    trailing: .chevron
) {
    Image(systemName: "person.crop.circle")
} action: { openProfile() }

// Loading
EBActionListRow.skeleton()
// Base — icon + label + CTA + chevron
EBActionListRow(
    label = "Payment methods",
    leading = { Icon(Icons.Default.CreditCard, contentDescription = null) },
    trailing = EBRowTrailing.Cta("View"),
    onClick = { openPaymentMethods() }
)

// With counter
EBActionListRow(
    label = "Notifications",
    leading = { Icon(Icons.Default.Notifications, contentDescription = null) },
    trailing = EBRowTrailing.Counter(3),
    onClick = { openNotifications() }
)

// With description + chevron
EBActionListRow(
    label = "Profile",
    description = "Name, photo, and contact info",
    leading = { Icon(Icons.Default.Person, contentDescription = null) },
    trailing = EBRowTrailing.Chevron,
    onClick = { openProfile() }
)

// Loading
EBActionListRow.Skeleton()
Accessibility
RequirementiOSAndroid
Row as button Wrap row in Button; mark decorative leading icon with .accessibilityHidden(true). Modifier.clickable { … }.semantics(mergeDescendants = true) { role = Role.Button }.
Combined label Announce label + description + trailing counter as one phrase: "Notifications, 3 unread". Same — build via contentDescription.
Touch target Minimum 44 × 44 — expanded density hits this; compact (48 px row) is safe; ensure whole row is the tap target, not just the chevron. Minimum 48 × 48dp — same.
Loading Announce "Loading" once; disable tap while loading. Same — enabled = false plus contentDescription = "Loading".
Focus ring Provide a focused treatment for external keyboards. Focus ring required for TV / external keyboards.
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Requires Rework 3 sibling components for one pattern. Spacer annotations leak into production.
C2 Variant & Property Naming Requires Rework Inconsistent label typography across siblings. Counter sibling uses a different text style than its peers.
C3 Token Coverage Ready All colors / paddings bound to main/action-list/*, space/*, radius/* tokens.
C4 Native Mappability Needs Refinement Maps cleanly once trailing is a single enum instead of three booleans across three components.
C5 Interaction State Coverage Requires Rework No Pressed / Focused. Disabled + Loading present.
C6 Asset & Icon Quality Needs Refinement Leading icon is a gray placeholder circle — move to a Figma Slot.
C7 Code Connect Linkability Not Mapped Blocked on consolidation. Mapping three siblings would cement the wrong schema.
Variants Inventory (0 total)

3 sibling components. Base + Counter multiply State (3) × Density (2) = 6 each. Description axis = State (3). Total 6 + 6 + 3 = 15 variants.

ComponentAxesCountNode
ListState (3) × Density (2)618577:14545
List - with CounterDensity (2) × State (3)618577:14637
List - with DescriptionState (3)318577:14604
1.0.0 — April 2026Major
Initial Assessment · nodes 18577:14545, 18577:14637, 18577:14604
Verdict: Restructure — Collapse 3 sibling components into one slot-driven List row. Reconcile label typography. Add Pressed state. Open
Architecture
C1 — 3 siblings for 1 pattern — Description and Counter are additive features, not different components. Open
C1
C1 — Spacer annotations leak_space_2 / _space_16 are authoring artifacts exported as opacity-0 layers. Open
C1
C2 — Divergent label typography — Semibold 16 Neutral vs. Bold 18 Brand across siblings. Same family must read as one. Open
C2
C4 — Trailing baked per sibling — Replace CTA / Counter / Chevron booleans with a single trailing enum. Open
C4
C5 — Missing Pressed state — Action rows are the primary nav tap target. Open
C5
C6 — Placeholder icon — Leading is a gray #C2C6CF circle. Adopt a Figma Slot. Open
C6
C7 — Code Connect — Blocked on consolidation. Open
C7
Tokens ✓ — Colors / paddings / radii all bound to main/action-list/*. Noted
Praise