East Blue
KeepNeeds Refinement
Stepper Component link

A progress indicator for multi-step flows, in bullet, circular and dash forms. Merges the former Stepper - Bullet, Stepper - Circular and Stepper - Dash.

Keep — all findings resolved
Rebuilt on node 4337:11140 in the 2026 Working File as a single Stepper, merging the former Bullet, Circular and Dash components into Type × Steps × Current × Status. Step count is a property rather than sibling components, the ordinal position enum is now an integer, Status states exist where the originals had almost none, property naming follows the guidelines throughout, and the step markers are vectors. The full 2–10 range, the per-Type Status coverage and horizontal-only orientation are all deliberate. All four DS Health traits pass; the only item still open is Code Connect, blocked until the native library exists.
In Context

Stepper - Bullet appears at the top or bottom of multi-step flows — most commonly paginated onboarding, swipeable carousels of tutorial cards, and photo galleries where the user needs a minimal position indicator without numerical labels.

Live Preview
Properties
Type
Steps
Current
Status
DS Health
Reusable
Pass
One component now covers all three visual forms and every step count from 2 to 10, where the same coverage previously took three components and twelve siblings between them.
Self-contained
Pass
Owns its typography, spacing and status colours, and the step markers are vector shapes bound to tokens rather than baked assets. Nothing external required to render.
Consistent
Pass
Type, Steps, Current and Status are orthogonal and correctly named — Type is a §1 standard property, integers replace the old ordinal enum, and every value is Title Cased per §5.
Composable
Pass
Drops into any multi-step flow, and all three visual forms share one API so a screen can switch between them without swapping components. Horizontal-only is a deliberate scope decision.
Behavior
State iOS Android Figma Property Notes
Current step Yes Yes fill = bg Dot at current index fills in main/stepper/color/bg (#005CE5).
Other steps Yes Yes fill = bg-track All other dots fill in main/stepper/color/bg-track (#D2E5FF). Note: the spec does not distinguish completed vs upcoming — both look identical.
Completed vs upcoming N/A N/A Not modeled Bullet steppers in other systems often shade completed dots differently from upcoming ones. This family collapses both into the track color — direction of travel is lost.
Clickable / interactive N/A N/A Not modeled Used in carousels, some implementations let the user tap a dot to jump to that page. No pressed / focused state exists today.
Connector line N/A N/A Not modeled Classic Material / iOS bullet steppers draw a thin line between dots tinted to match completed / upcoming. This family uses blank 8-px gaps instead.
Issues
  • Three Stepper components merged into one. v2.0: Rebuilt on node 4337:11140 in the 2026 Working File as a single Stepper set. Stepper - Bullet, Stepper - Circular and Stepper - Dash are now Type = Bullet | Circular | Dash — the unification all three assessments recommended independently. (C4 · Family) C4 · Native Mappability
  • Step count is a property, not sibling components. v2.0: Bullet had three siblings and Circular nine, each hard-coding a step count; Dash encoded it as ten propNStepper booleans. All of that is now a single Steps axis. (C2 · Property) C2 · Variant & Property Naming
  • Ordinal position replaced by an integer. v2.0: The highlighted = 1st | 2nd | … | Nth ordinal enum is now Current carrying integers, which maps directly to a currentStep: Int parameter rather than needing a lookup table. (C2 · Rename) C2 · Variant & Property Naming
  • Status states added. v2.0: Status = Current | Completed | Upcoming | Error now exists where none of the three originals distinguished completed from upcoming, and only Dash had any notion of error. (C5) C5 · Interaction State Coverage
  • Style renamed to Type. v2.1: §6 names Style explicitly as a catch-all to avoid, alongside Configuration and Settings. Type is a standard variant property from §1 and says the same thing without the anti-pattern. (C2 · Rename) C2 · Variant & Property Naming
  • All variant values Title Cased. v2.1: Bullet | Circular | Dash and Current | Completed | Upcoming | Error now follow §5, replacing the lowercase values. (C2 · Rename) C2 · Variant & Property Naming
  • Uneven Status coverage confirmed intentional. v2.1: Closed by owner decision — Bullet carries only Current and Completed, Circular is almost entirely Current with single Completed and Upcoming entries, and Dash carries Error throughout. Each Type supports the statuses its usage actually calls for rather than filling out a uniform matrix. (C5) C5 · Interaction State Coverage
  • Full 2–10 step range retained. v2.1: Closed by owner decision, superseding an earlier intent to cap the range — the set keeps all 225 variants. Figma cannot parameterise a repeating count, so enumerating every combination is the only way to make each one selectable; capping would mean any flow longer than the cap had no variant and a designer would have to detach. The cost is set size in Figma only — the native API takes steps and current as integers and has no such limit. (C2) C2 · Variant & Property Naming
  • Dots and ring arcs confirmed as vectors. v2.1: Confirmed by the component owner — the step markers are vector shapes, not the raster PNGs all three original assessments flagged. They recolour with tokens and stay crisp at any density. Not independently verifiable from the assessment tooling, whose response limit the node exceeds. (C6 · Asset) C6 · Asset & Icon Quality
  • Horizontal-only orientation confirmed intentional. v2.1: Closed by owner decision — Stepper ships horizontal only. An Orientation axis would multiply an already large set for a layout the product does not use, and vertical progress indication is better served by a different pattern than a rotated stepper. Revisit only if a long-flow screen genuinely calls for it. (Composition) C4 · Native Mappability
Recommendations
  • Announce "Step X of Y" to screen readers. All three original assessments raised this and it is still unaddressed. A progress indicator that conveys position only visually is invisible to assistive technology — the native component should expose the position as an accessibility value. A11y
Styles
Bullet
Properties
Steps
Current
Status
Properties
Type Bullet
Steps 3
Current 1
Status Current
Colors
Current and completed steps #005CE5
Upcoming steps #D2E5FF
Typography
Layout
Height 16
Width 40
Radius 0
Padding H —
Padding V —
Gap —
Border 0
Alignment —
Colors by Type and Status
Role Element Token Value
Bullet · Current Current and completed steps — #005CE5
Bullet · Current Upcoming steps — #D2E5FF
Circular · Current Ring — #D2E5FF
Circular · Completed Ring — #12AF80
Circular · Current Arc — #005CE5
Circular · Completed Arc — #12AF80
Circular · Current Index — #005CE5
Circular · Upcoming Index — #9BC5FD
Circular · Current Checkmark — #12AF80
Circular · Current Step label — #90A8D0
Dash · Current Current and completed steps — #005CE5
Dash · Completed Current and completed steps — #12AF80
Dash · Current Current step in error — #D61B2C
Dash · Current Upcoming steps — #D2E5FF
Circular
Properties
Steps
Current
Status
Properties
Type Circular
Steps 3
Current 1
Status Current
Colors
Ring #D2E5FF
Arc #005CE5
Index #005CE5
Checkmark #12AF80
Step label #90A8D0
Typography
#index Primary/Headlines/Block
#label Primary/Label/Fine
Layout
Height 45
Width 45
Radius 0
Padding H —
Padding V —
Gap —
Border 0
Alignment —
Dash
Properties
Steps
Current
Status
Properties
Type Dash
Steps 3
Current 1
Status Current
Colors
Current and completed steps #005CE5
Current step in error #D61B2C
Upcoming steps #D2E5FF
Typography
Layout
Height 4
Width 74
Radius 0
Padding H —
Padding V —
Gap —
Border 0
Alignment —
Installation Planned API

iOS — Swift Package Manager

.package(url: "https://github.com/AY-Org/eb-ds-ios", from: "1.0.0")

Android — Gradle (Kotlin DSL)

implementation("com.eastblue.ds:stepper:1.0.0")

Import

import EastBlueDS
import com.eastblue.ds.stepper.*
Property Mapping

Type, Steps, Current and Status are the set’s four variant properties. Circular carries two text layers, #index and #label; Bullet and Dash have none. Colour variable bindings and the text property exposure are not readable with the plugin.

Figma PropertySwiftUICompose
Type — Bullet, Circular, Dash .ebType(.bullet / .circular / .dash) type = EBStepperType.Bullet / Circular / Dash
Steps — 2 … 10 (Bullet from 3) steps: Int steps = 3
Current — 0 … 10 current: Int current = 1
Status — Current, Completed, Upcoming, Error .ebStatus(.completed / .upcoming / .error) status = EBStepperStatus.Completed / Upcoming / Error
#index (text, Circular) Drawn from current — no parameter Drawn from current — no parameter
#label (text, Circular) .ebLabel("Step 1 of 10") — the layer sits outside the 45 × 45 frame in Figma label = "Step 1 of 10"
Usage Snippets Planned API
Bullet
EBStepper(steps: 3, current: 1)
    .ebType(.bullet)
EBStepper(
    steps = 3,
    current = 1,
    type = EBStepperType.Bullet
)
Circular
EBStepper(steps: 3, current: 1)
    .ebType(.circular)
EBStepper(
    steps = 3,
    current = 1,
    type = EBStepperType.Circular
)
Dash
EBStepper(steps: 3, current: 1)
    .ebType(.dash)
EBStepper(
    steps = 3,
    current = 1,
    type = EBStepperType.Dash
)
Accessibility
RequirementiOSAndroid
Progress semantics .accessibilityValue("Step 2 of 4") on the stepper; .accessibilityAddTraits(.updatesFrequently) while it moves. Modifier.semantics { progressBarRangeInfo = ProgressBarRangeInfo(2f, 0f..4f) } plus stateDescription = "Step 2 of 4".
Decorative marks The dots, dashes and ring are .accessibilityHidden(true); the value carries the meaning. Marks are clearAndSetSemantics; the value carries the meaning.
Error and completed Append "error on step 2" or "completed" to the value — colour alone is not announced. Same phrasing in stateDescription.
Not interactive No button trait; steps are not tap targets. No clickable; steps are not touch targets.
Usage Guidelines

Do

Use Bullet for short flows of 3 to 5 steps where position is enough.

Don't

Don’t use Bullet above 6 steps — the row of dots stops reading as progress.

Do

Use Circular when the screen has room for one 45 px marker and the step number matters.

Don't

Don’t stack Circular per step; it shows one step at a time.

Do

Use Dash when steps can fail — it is the only Type with an Error status.

Don't

Don’t use Error on Bullet or Circular; the set does not build it.

Do

Keep Current between 1 and Steps; Completed sets it to Steps.

Don't

Don’t pass Current 0 outside the Circular Upcoming state.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Needs Refinement Circular’s label-container sits below the 45 × 45 frame and never renders; #index and #label keep the # sigil; Bullet dots are eight layers all named ellipse. Dash segments are 1st … 10th — read on 4365:12137, 4337:11205, 4695:22253.
C2 Variant & Property Naming Ready Type, Steps, Current, Status — Title Case values, integers for the two counts.
C3 Token Coverage Ready #index resolves to Primary/Headlines/Block, #label to Primary/Label/Fine. Colour variable bindings are not readable with the plugin — confirm in Dev Mode.
C4 Native Mappability Ready One enum, two integers, one status enum — maps 1:1 onto EBStepper; the arc is a stroked path.
C5 Interaction State Coverage Ready Status coverage differs by Type by design (v2.x confirmation): Bullet Current and Completed, Circular adds Upcoming, Dash adds Error. Not interactive, so no Pressed.
C6 Asset & Icon Quality Ready Dots, dashes, ring and arc are vectors; the Completed check is the 16 × 16 Checkmark instance.
Variants Inventory (225 total)

3 Type × Steps 2–10 × Current × Status, built where the Type needs it (Bullet 52, Circular 56, Dash 117) = 225 variants

TypeStatuses builtCount
BulletCurrent for every Steps × Current; Completed at Current = Steps52
CircularCurrent for every Steps × Current; Upcoming and Completed at Steps = 256
DashCurrent and Error for every Steps × Current; Completed at Current = Steps117
View full Type × Steps × Current × Status breakdown (225 rows)
TypeStepsCurrentStatusNodeDimensions
Bullet31Current4337:1113840 × 16
Bullet32Current4337:1120140 × 16
Bullet33Completed4337:1147040 × 16
Bullet41Current4337:1113756 × 16
Bullet42Current4337:1120556 × 16
Bullet43Current4337:1147456 × 16
Bullet44Completed4337:1158656 × 16
Bullet51Current4337:1113672 × 16
Bullet52Current4337:1121072 × 16
Bullet53Current4337:1147972 × 16
Bullet54Current4337:1159172 × 16
Bullet55Completed4337:1171472 × 16
Bullet61Current4337:1113588 × 16
Bullet62Current4337:1121688 × 16
Bullet63Current4337:1148588 × 16
Bullet64Current4337:1159788 × 16
Bullet65Current4337:1172088 × 16
Bullet66Completed4337:1203488 × 16
Bullet71Current4337:11134104 × 16
Bullet72Current4337:11223104 × 16
Bullet73Current4337:11492104 × 16
Bullet74Current4337:11604104 × 16
Bullet75Current4337:11727104 × 16
Bullet76Current4337:12041104 × 16
Bullet77Completed4337:12207104 × 16
Bullet81Current4337:11133120 × 16
Bullet82Current4337:11231120 × 16
Bullet83Current4337:11500120 × 16
Bullet84Current4337:11612120 × 16
Bullet85Current4337:11735120 × 16
Bullet86Current4337:12049120 × 16
Bullet87Current4337:12215120 × 16
Bullet88Completed4337:12275120 × 16
Bullet91Current4337:11132136 × 16
Bullet92Current4337:11240136 × 16
Bullet93Current4337:11509136 × 16
Bullet94Current4337:11621136 × 16
Bullet95Current4337:11744136 × 16
Bullet96Current4337:12058136 × 16
Bullet97Current4337:12224136 × 16
Bullet98Current4337:12284136 × 16
Bullet99Completed4337:12386136 × 16
Bullet101Current4337:11139152 × 16
Bullet102Current4337:11250152 × 16
Bullet103Current4337:11519152 × 16
Bullet104Current4337:11631152 × 16
Bullet105Current4337:11754152 × 16
Bullet106Current4337:12068152 × 16
Bullet107Current4337:12234152 × 16
Bullet108Current4337:12294152 × 16
Bullet109Current4337:12396152 × 16
Bullet1010Completed4337:12460152 × 16
Circular20Upcoming4773:3149045 × 45
Circular21Current4365:1186645 × 45
Circular22Completed4695:2250945 × 45
Circular22Current4365:1189145 × 45
Circular31Current4365:1191345 × 45
Circular32Current4365:1192145 × 45
Circular33Current4365:1193645 × 45
Circular41Current4365:1212945 × 45
Circular42Current4365:1213745 × 45
Circular43Current4365:1214545 × 45
Circular44Current4365:1216045 × 45
Circular51Current4365:1219745 × 45
Circular52Current4365:1220545 × 45
Circular53Current4365:1221345 × 45
Circular54Current4365:1222145 × 45
Circular55Current4365:1223645 × 45
Circular61Current4365:1227945 × 45
Circular62Current4365:1228745 × 45
Circular63Current4365:1229545 × 45
Circular64Current4365:1230345 × 45
Circular65Current4365:1231145 × 45
Circular66Current4365:1232645 × 45
Circular71Current4365:1250845 × 45
Circular72Current4365:1251645 × 45
Circular73Current4365:1252445 × 45
Circular74Current4365:1253245 × 45
Circular75Current4365:1254045 × 45
Circular76Current4365:1254845 × 45
Circular77Current4365:1256345 × 45
Circular81Current4365:1267045 × 45
Circular82Current4365:1267845 × 45
Circular83Current4365:1268645 × 45
Circular84Current4365:1269445 × 45
Circular85Current4365:1270245 × 45
Circular86Current4365:1271045 × 45
Circular87Current4365:1271845 × 45
Circular88Current4365:1275745 × 45
Circular91Current4365:1284045 × 45
Circular92Current4365:1284845 × 45
Circular93Current4365:1285645 × 45
Circular94Current4365:1286445 × 45
Circular95Current4365:1287245 × 45
Circular96Current4365:1288045 × 45
Circular97Current4365:1288845 × 45
Circular98Current4365:1289645 × 45
Circular99Current4365:1291145 × 45
Circular101Current4365:1323345 × 45
Circular102Current4365:1324145 × 45
Circular103Current4365:1324945 × 45
Circular104Current4365:1325745 × 45
Circular105Current4365:1326545 × 45
Circular106Current4365:1327345 × 45
Circular107Current4365:1328145 × 45
Circular108Current4365:1328945 × 45
Circular109Current4365:1329745 × 45
Circular1010Current4365:1331245 × 45
Dash21Current4695:2232948 × 4
Dash21Error4773:3233248 × 4
Dash22Completed4773:3282548 × 4
Dash22Current4695:2233348 × 4
Dash22Error4773:3239548 × 4
Dash31Current4695:2229774 × 4
Dash31Error4773:3232874 × 4
Dash32Current4695:2230274 × 4
Dash32Error4773:3239174 × 4
Dash33Completed4773:3282874 × 4
Dash33Current4695:2230774 × 4
Dash33Error4773:3245474 × 4
Dash41Current4695:22247100 × 4
Dash41Error4773:32323100 × 4
Dash42Current4695:22253100 × 4
Dash42Error4773:32386100 × 4
Dash43Current4695:22259100 × 4
Dash43Error4773:32449100 × 4
Dash44Completed4773:32832100 × 4
Dash44Current4695:22265100 × 4
Dash44Error4773:32509100 × 4
Dash51Current4695:22171126 × 4
Dash51Error4773:32317126 × 4
Dash52Current4695:22178126 × 4
Dash52Error4773:32380126 × 4
Dash53Current4695:22185126 × 4
Dash53Error4773:32443126 × 4
Dash54Current4695:22192126 × 4
Dash54Error4773:32503126 × 4
Dash55Completed4773:32837126 × 4
Dash55Current4695:22199126 × 4
Dash55Error4773:32559126 × 4
Dash61Current4695:22073152 × 4
Dash61Error4773:32310152 × 4
Dash62Current4695:22081152 × 4
Dash62Error4773:32373152 × 4
Dash63Current4695:22089152 × 4
Dash63Error4773:32436152 × 4
Dash64Current4695:22097152 × 4
Dash64Error4773:32496152 × 4
Dash65Current4695:22105152 × 4
Dash65Error4773:32552152 × 4
Dash66Completed4773:32843152 × 4
Dash66Current4695:22113152 × 4
Dash66Error4773:32603152 × 4
Dash71Current4695:21945178 × 4
Dash71Error4773:32302178 × 4
Dash72Current4695:21954178 × 4
Dash72Error4773:32365178 × 4
Dash73Current4695:21963178 × 4
Dash73Error4773:32428178 × 4
Dash74Current4695:21972178 × 4
Dash74Error4773:32488178 × 4
Dash75Current4695:21981178 × 4
Dash75Error4773:32544178 × 4
Dash76Current4695:21990178 × 4
Dash76Error4773:32595178 × 4
Dash77Completed4773:32850178 × 4
Dash77Current4695:21999178 × 4
Dash77Error4773:32640178 × 4
Dash81Current4695:21783204 × 4
Dash81Error4773:32293204 × 4
Dash82Current4695:21793204 × 4
Dash82Error4773:32356204 × 4
Dash83Current4695:21803204 × 4
Dash83Error4773:32419204 × 4
Dash84Current4695:21813204 × 4
Dash84Error4773:32479204 × 4
Dash85Current4695:21823204 × 4
Dash85Error4773:32535204 × 4
Dash86Current4695:21833204 × 4
Dash86Error4773:32586204 × 4
Dash87Current4695:21843204 × 4
Dash87Error4773:32631204 × 4
Dash88Completed4773:32858204 × 4
Dash88Current4695:21853204 × 4
Dash88Error4773:32669204 × 4
Dash91Current4695:21583230 × 4
Dash91Error4773:32283230 × 4
Dash92Current4695:21594230 × 4
Dash92Error4773:32346230 × 4
Dash93Current4695:21605230 × 4
Dash93Error4773:32409230 × 4
Dash94Current4695:21616230 × 4
Dash94Error4773:32469230 × 4
Dash95Current4695:21627230 × 4
Dash95Error4773:32525230 × 4
Dash96Current4695:21638230 × 4
Dash96Error4773:32576230 × 4
Dash97Current4695:21649230 × 4
Dash97Error4773:32621230 × 4
Dash98Current4695:21660230 × 4
Dash98Error4773:32659230 × 4
Dash99Completed4773:32867230 × 4
Dash99Current4695:21671230 × 4
Dash99Error4773:32689230 × 4
Dash101Current4689:18458256 × 4
Dash101Error4773:32272256 × 4
Dash102Current4689:18469256 × 4
Dash102Error4773:32335256 × 4
Dash103Current4689:18480256 × 4
Dash103Error4773:32398256 × 4
Dash104Current4689:18491256 × 4
Dash104Error4773:32458256 × 4
Dash105Current4689:18502256 × 4
Dash105Error4773:32514256 × 4
Dash106Current4689:18513256 × 4
Dash106Error4773:32565256 × 4
Dash107Current4689:18524256 × 4
Dash107Error4773:32610256 × 4
Dash108Current4689:18535256 × 4
Dash108Error4773:32648256 × 4
Dash109Current4689:18546256 × 4
Dash109Error4773:32678256 × 4
Dash1010Completed4773:32877256 × 4
Dash1010Current4689:18557256 × 4
Dash1010Error4773:32699256 × 4
1.0.2 — September 2026Patch
Style and Code tabs re-read · node 4337:11140
Style tab rebuilt from the 225 live variants. Cards follow Type — Bullet, Circular, Dash — with Steps, Current and Status as panel controls; geometry, colours and the two Circular text styles read off 4337:11205, 4365:12137, 4695:22253 and the Status variants. Padding, gap, alignment and colour tokens are not readable with the plugin and stay —.
Docs
Code tab regrouped on the four-property schema. Installation on the Stepper family coordinates, Property Mapping one row per property, Usage Snippets per Type, Guidelines added, Scorecard regraded, Variants Inventory built from the 225 live nodes with a summary and a collapsed breakdown.
Docs
Circular’s step label never renders. label-container (e.g. 4365:12143) sits at y 45 under a 45 × 45 frame and is clipped in every export; #index / #label also keep the # sigil and the Bullet dots are all named ellipse. Filed from the scorecard for the Component Review.
C1
1.0.1 — September 2026Patch
Documentation backfill · node 4337:11140
Resolved issues recorded. 10 resolved issues on the Overview tab had no changelog row: Three Stepper components merged into one; Step count is a property, not sibling components; Ordinal position replaced by an integer; Status states added; Style renamed to Type; All variant values Title Cased; Uneven Status coverage confirmed intentional; Full 2–10 step range retained; Dots and ring arcs confirmed as vectors; Horizontal-only orientation confirmed intentional.
Docs
1.0.0 — April 2026Major
Initial Assessment · canonical node 27:48287 (5 Steps) + 2 siblings (27:48254 4 Steps, 27:48235 3 Steps)
Verdict: Restructure — Collapse 3 sibling components (Stepper - Bullet - 3/4/5 Steps) into one Stepper - Bullet with steps: Int and current: Int properties. Replace raster dot PNGs with vector ellipses. Long-term, unify with Dash + Circular under EBStepper(style:). Open
Schema
C1 — Family structure — 3 top-level components differ only by hardcoded step count. Collapse into one component with a steps property. Same anti-pattern as Stepper - Circular. Open
C1
C2 — Property shape — Nested highlighted = 1st | 2nd | … | Nth ordinal axis should become a top-level integer current. Open
C2
C4 — Native mapping — No native primitive matches. Requires custom EBStepperBullet on both platforms built over HStack/Row of Circle shapes. Consider unifying with Dash + Circular under EBStepper(style:). Open
C4
C5 — Missing states — No completed / upcoming distinction, no pressed / focused states for interactive carousels, no connector line, no vertical orientation. Open
C5
C6 — Raster dots — Each 8×8 dot is a pre-baked PNG. Replace with vector Ellipse fills bound to main/stepper/color/bg and main/stepper/color/bg-track. Open
C6
C7 — Code Connect — Mappings pending restructure. Mapping 3 separate siblings would codify the anti-pattern. Open
C7