KeepNeeds Refinement
Action Row Component link

A tappable list row with a leading asset slot, label and description, and a trailing chevron with optional counter. Merges the former Action List, Action List with Counter and Action List with Description.

Keep — all findings resolved
Rebuilt on node 4628:19843 in the 2026 Working File and renamed Action Row, merging the three former Action List siblings into TrailingContent (2) × State (4) × Density (2) = 16 variants, plus a hasDescription boolean. Interaction states now exist where there were none, the leading asset and counter are real Figma Slots, and layer and property naming matches the conventions the rest of the family settled on. All four DS Health traits pass; the only item still open is Code Connect, blocked until the native library exists.
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
Pass
Carries its own surface, dividers and state colors, and composes a chevron and counter from library instances. Nothing external required to render a complete row.
Consistent
Pass
TrailingContent, State and Density are orthogonal, Density is used exactly as §1 defines it, hasDescription carries the correct verb prefix, and TrailingContent matches View Only Field for the same concept. Every addressable layer is semantically named; the skeleton loader keeps working names by design.
Composable
Pass
Asset Slot and Counter Slot are real Figma Slots, and the chevron and counter come from library instances — teams drop in content without detaching. Stacks cleanly into lists.
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.
Issues
  • Code Connect mappings not registered. Blocked — no native library exists yet. The schema is otherwise clean: three enums plus two swappable slots. C7 · Code Connect Linkability
  • Three Action List components merged into Action Row. v2.0: Rebuilt on node 4628:19843 in the 2026 Working File and renamed Action Row. Action List, Action List with Counter and Action List with Description are now one set: the counter is a Trailing=Counter value, and the description is part of the row rather than a separate component. Confirmed as a permanent merge by the component owner. (C4 · Family) C4 · Native Mappability
  • Variant matrix is orthogonal and complete. v2.0: Trailing (CTA · Counter) × State (Default · Pressed · Disabled · Loading) × Density (Compact · Expanded) = 16 variants, all authored. Density is used exactly as §1 defines it — adjusting row height and padding, 56px against 64px — rather than gating content. (C2 · Property) C2 · Variant & Property Naming
  • Interaction states added. v2.0: State now covers Default, Pressed, Disabled and Loading, where the original components had no state coverage at all. Pressed carries its own #F6F9FD surface. (C5) C5 · Interaction State Coverage
  • Leading asset and counter are real Figma Slots. v2.0: Asset Slot and Counter Slot are SLOT nodes, and the chevron and counter are library instances. Teams can drop in real content without detaching — the composition pattern the rest of the family has converged on. (C6 · Slot) C6 · Asset & Icon Quality
  • Frame naming aligned to the family. v2.1: The two frames both called Container are now Row and TrailingGroup, and the spaced names are hyphenated to match the convention Toast, Upload File and Section Header settled on — Asset-Slot, Counter-Slot, Text-Container, Icon-Container, Bottom-Stroke. (C1) C1 · Layer Structure & Naming
  • Trailing renamed to TrailingContent. v2.1: The axis now carries the same name View Only Field uses for the same concept, satisfying §6 on consistent terminology. Any future component with a trailing area has one name to adopt rather than a choice between two. (C2 · Family) C2 · Variant & Property Naming
  • Text and action layer naming completed. v2.2: #labelLabel and #blurbDescription, mapping onto §3 — the content is supporting text beneath a label rather than the promotional summary Blurb denotes. leading iconLeading-Icon and Action ButtonAction-Button complete the hyphenated convention. (C1) C1 · Layer Structure & Naming
  • hasDescription boolean added. v2.3: Confirmed by the component owner — a hasDescription boolean now toggles the description line, restoring the label-only row the original Action List provided. Implemented as a boolean component property rather than a fourth variant axis, so the matrix stays at 16 rather than doubling. Not independently verifiable from the assessment tooling, which cannot read component property definitions. (C2 · Property) C2 · Variant & Property Naming
  • Nested Wrapper collision resolved. v2.3: The Wrapper frame nested inside another Wrapper in the Loading variants is now Skeleton-Trailing, naming what it actually holds. (C1) C1 · Layer Structure & Naming
  • Skeleton loader retained as authored. v2.3: Closed by owner decision — the Loading variants keep their skeleton geometry as built, including the repeated trailing icon and line rectangle names. These are internal placeholder shapes with no property surface and no override target, so their names never reach a consumer or a Code Connect mapping — the same reasoning applied to View Only Field's wrapper frames. (C1) C1 · Layer Structure & Naming
Recommendations
  • Record State=Loading under the existing State/Status exception. Loading is a process status rather than an interaction state, the same shape as Error on the form fields. It falls under the exception already documented for that family rather than needing its own justification. Docs
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