RestructureRequires Rework
Progress Bar Component link

A linear progress indicator showing completion percentage; supports determinate and indeterminate modes.

Restructure — collapse 11 percentage variants into one component with a continuous <code>progress</code> value
Progress is a scalar — not an enum. The current schema cannot represent 37% or 62%, and every variant ships two raster PNGs for what should be two token-bound rectangles. Rebuild as a single component: progress: Float (0–1), state: determinate | indeterminate | success | error. Replace the raster back / front layers with vector strokes bound to main/progress-bar/color/border-track and main/progress-bar/color/border. Native side maps 1:1 to ProgressView / LinearProgressIndicator.
In Context

Progress Bar appears above or below task content to show completion — KYC steps, file upload progress, multi-step form wizards.

Live Preview
Content
progress
value45%
Properties (proposed)
state
DS Health
Reusable
Pass
Generic task-progress primitive — fits anywhere a linear completion indicator is needed (KYC, uploads, wizards).
Self-contained
Warn
Renders via raster back / front image layers instead of shape layers. Ships 11 PNGs worth of assets for what should be two rectangles.
Consistent
Fail
Progress modelled as a discrete percentage enum with 11 variants — cannot express 37%, 62%, or any non-decile value. Every other slider-style value in the DS is continuous.
Composable
Partial
Fixed 312-px width with 2-px horizontal padding hugs a single canonical layout; doesn't stretch responsively inside a fill container today.
Behavior
State iOS Android Figma Property Notes
Determinate Yes Yes percentage=0…100 Fill grows left-to-right in 10% steps today. Should be continuous (0–1).
Indeterminate N/A N/A Not modeled Not modeled in Figma. Native primitives support it out of the box — add a variant so designers can spec it.
Success N/A N/A Not modeled Green fill at 100%. Used to confirm the task completed cleanly (file uploaded, verification passed).
Error N/A N/A Not modeled Red fill at the point of failure. Used when the task fails mid-progress (upload retry, network dropped).
Buffered N/A N/A Not modeled Compose supports a secondary buffered fill. Optional — only add if media streaming is a real use case.
Open Issues
  • Progress is an enum of 10% steps, not a value. The Figma component exposes percentage as 11 discrete options (0, 10, 20, …, 100). Consumers can't spec 37% or animate smoothly — they must pick the closest variant. Every scalar value in the DS should be continuous. C2 · Variant & Property Naming
  • Track and fill are raster PNGs. The back and front layers are <img> assets, not shape layers. Blocks token-driven theming, breaks at non-1× resolutions, and ships 11 PNG pairs for what should be two rectangles. C6 · Asset & Icon Quality
  • Layer names are structural (back / front), not semantic. Should be Track and Fill to match native parlance and make the inspector readable for handoff. C1 · Layer Structure & Naming
  • No indeterminate, success, or error state modeled. Native ProgressView and LinearProgressIndicator both support indeterminate natively; product flows (KYC failure, upload retry) need success / error color states. Today Figma has only the determinate-blue variants. C5 · Interaction State Coverage
  • Property name percentage reads as a unit, not a ratio. Native APIs use progress as a 0–1 Float. Renaming to progress (with a 0–1 range, or 0–100 if kept as integer) aligns the DS with iOS / Compose conventions. C2 · Variant & Property Naming
  • Code Connect mappings not registered. Cannot land until the progress value is parameterized and the raster layers are replaced with token-bound shapes. C7 · Code Connect Linkability
Design Recommendations
  • Collapse 11 percentage variants into a single component with a continuous progress value. Delete the percentage = 0 | 10 | … | 100 enum. Expose progress: Float (0–1). In Figma, drive the fill width by layout — either a single variant with a layer the designer resizes, or a published component that lives as a native primitive on the dev side. Variant math drops from 11 to 1 (+ state). Property
  • Replace raster back / front images with token-bound rectangles. Two filled rectangles (or stroked lines) bound to main/progress-bar/color/border-track and main/progress-bar/color/border. Same visual output, theme-able, resolution-independent, no PNG pairs to ship. Asset
  • Rename layers backTrack and frontFill. Matches native terminology (track / tint in SwiftUI, trackColor / color in Compose) and reads better in the inspector. Rename
  • Add state variant: determinate / indeterminate / success / error. Indeterminate is a looping animation designers should be able to spec. Success (positive green) and error (negative red) cover KYC / upload result states. Token references: main/progress-bar/color/success and main/progress-bar/color/error — add to the collection. State
  • Reuse existing semantic color tokens for success / error. Don't mint new hex values. Align with Alert / Badge semantic colors (text/positive, text/negative) so the progress fill reads the same as the rest of the system. Token
  • Evaluate whether a bespoke EBProgressBar is needed at all. SwiftUI ProgressView(value:) and Compose LinearProgressIndicator are 1:1 matches for this component. If the only custom requirement is token-bound colors, a lightweight theming wrapper suffices; otherwise use the native primitive directly. Document either way. Composition
  • Make the component width-flexible. Today it's locked to 312 px with 2-px horizontal padding. Spec as fill-container so a designer can drop it into any column width. Property
  • Document accessibility expectations. role="progressbar", aria-valuenow / aria-valuemin / aria-valuemax for determinate; announce a localized label for indeterminate ("Loading…"). Both native APIs handle this automatically, but the web/hybrid consumer needs the spec. A11y
Styles
Determinate
DES DEV

Linear fill with a light-blue track and a brand-blue fill. The 11 Figma variants step through <code>percentage = 0, 10, 20, …, 100</code> — each variant swaps a pre-sized raster pair. The target implementation renders a single component with a continuous <code>progress</code> value.

Properties
State
Progress
Properties
Mode determinate
Progress 60%
Range 0–100%
Track style rounded
Colors
Track #D2E5FF
Fill #005CE5
Properties (today)
percentage 0 | 10 | 20 | … | 100
Fill implementation raster <img>
Track implementation raster <img>
Width 312 (fixed)
Layout
Total width 312
Horizontal padding 2
Inner track width 308
Stroke height 4 (raster-baked)
Corner radius 0 (radius/radius-0)
Typography
No text
Label pairing external
Progress Bar is a graphic-only primitive; labels and percentage text are the consumer's responsibility.
Track + Fill — Colors

Two-zone bar: a static track and an animated fill segment driven by the percentage variant.

Role Token Default
Track progress-bar/color/border-track #D2E5FF
Fill progress-bar/color/border #005CE5
Property Mapping
Figma PropertySwiftUICompose
percentage: 0 | 10 | … | 100 (enum) progress: Float (0–1) value: Double
(not modeled) state: determinate | indeterminate | success | error ProgressView() (indeterminate) / .tint(.green / .red)
(raster back) Track (vector, border-track) .progressViewStyle(.linear)
(raster front) Fill (vector, border) .tint(EBColors.progressFill)
312 fixed fill-container .frame(maxWidth: .infinity)
Accessibility
RequirementiOSAndroid
Progress role ProgressView exposes the progressbar trait automatically. Set .accessibilityLabel("Verification progress") for context. LinearProgressIndicator emits ProgressBarInfo via semantics automatically. Set Modifier.semantics { contentDescription = "Verification progress" }.
Value announcement VoiceOver reads the current value (0–100%). For non-percentage ranges, use .accessibilityValue("\(step) of \(total)"). TalkBack reads the progress fraction. For custom phrasing, set stateDescription.
Indeterminate Announce a localized label ("Loading…"). Avoid announcing a fake percentage. Same — LinearProgressIndicator() with no progress lambda handles this natively.
Contrast Fill #005CE5 on track #D2E5FF = 3.1:1 — passes 3:1 for non-text graphics (WCAG 1.4.11). OK. Same ratio.
Reduced motion Indeterminate animation should honor UIAccessibility.isReduceMotionEnabled. Native ProgressView does this automatically. Native LinearProgressIndicator already respects Animator.getDurationScale.
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Needs Refinement Rename backTrack, frontFill. Otherwise structurally clean.
C2 Variant & Property Naming Requires Rework percentage is a discrete enum; should be a continuous progress: Float (0–1).
C3 Token Coverage Ready Track + fill colors bound to main/progress-bar/color/*. Add success / error tokens once states are introduced.
C4 Native Mappability Ready Maps 1:1 to ProgressView(value:) / LinearProgressIndicator. No custom gesture or web-only patterns.
C5 Interaction State Coverage Requires Rework Missing indeterminate, success, error. Only determinate (in 10% steps) modeled today.
C6 Asset & Icon Quality Requires Rework Track + fill are raster <img>. Replace with token-bound rectangles or vector strokes.
C7 Code Connect Linkability Not Mapped Blocked until progress is parameterized and rasters replaced.
Variants Inventory (11 total)

A single percentage axis with 11 discrete values (0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100) = 11 variants. The target architecture collapses this axis into a continuous progress value — variant count drops to 1 (plus the new state axis for indeterminate / success / error).

#NodepercentageFill widthLayer pair
127:6494700 / 308back only (no front rendered)
227:6494910~31 / 308back + front raster
327:6495320~62 / 308back + front raster
427:6495730~92 / 308back + front raster
527:6496140~123 / 308back + front raster
627:6496550~154 / 308back + front raster
727:6496960~185 / 308back + front raster
827:6497370~216 / 308back + front raster
927:6497780~246 / 308back + front raster
1027:6498190~277 / 308back + front raster
1127:64985100308 / 308back + front raster
1.0.0 — April 2026Major
Initial Assessment · node 18577:13227
Verdict: Restructure — Collapse 11 percentage variants into a single component with continuous progress: Float (0–1). Add state axis (determinate / indeterminate / success / error). Replace raster back/front with token-bound rectangles. Open
Schema
C1 — Layer naming — Rename backTrack and frontFill. Aligns with native terminology. Open
C1
C2 — Continuous value — Replace percentage: 0 | 10 | … | 100 enum with progress: Float (0–1). Renaming from percentage to progress aligns with iOS / Compose conventions. Open
C2
C5 — Missing states — Add indeterminate, success, error variants. Native ProgressView / LinearProgressIndicator support these out of the box. Open
C5
C6 — Raster fills — Replace <img> back/front layers with token-bound rectangles using main/progress-bar/color/border-track and main/progress-bar/color/border. Open
C6
C7 — Code Connect — Mappings pending restructure. Blocked until progress is parameterized and rasters replaced. Open
C7