Progress bar
Determinate: drag the slider; mark it complete or failed
Indeterminate: work of unknown length (streaming). Reduced-motion freezes it
Buffer: a lighter secondary track (e.g. received) ahead of the primary (played)
Segmented: discrete steps (step 3 of 5)
Sizes: thin (the app's 3 to 4dp) and thick
Status: complete and failed (icon + text, never color alone)
Circular: determinate ring with a center % (indeterminate circular is the spinner)
Track + fill are all var(--token). The track is a recessed well at radius-track (the app's 2dp squared shape), and the fill is the plain cyan accent with no threshold banding (that is the context gauge). The width grows; the fill never tweens. The island is live.
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
// Determinate: a value 0 to 100 drives the cyan fill width. The bar is the GENERAL// progress primitive: plain cyan, NO threshold banding (that is the ContextGauge).<ProgressBar value={64} label="Exporting session…" size="thick" />
// Indeterminate: omit `value` for work of unknown length (a sliding track).<ProgressBar label="Connecting to gateway…" indeterminate />
// Buffer: a lighter secondary track behind the primary fill.<ProgressBar value={48} buffer={70} label="Streaming response" />
// Segmented / stepped: discrete cells, `value` of `max`.<ProgressBar value={3} max={5} variant="segmented" label="Deploy pipeline" />
// Completion + failure. Color is never the only signal (icon + text follow).<ProgressBar value={100} tone="success" label="Snapshot uploaded" /><ProgressBar value={80} tone="error" label="Build artifacts" />
// Determinate ring with a center % (indeterminate circular = the NockerlSpinner).<ProgressBar value={64} variant="ring" label="Export" />// Android: Jetpack Compose (canonical). The determinate linear bar is Material's// LinearProgressIndicator styled to the Nockerl track, as shipped in// com.nockerl.app.chat.ui.TodoWidget / AgentWidget / ClusterSheet. The value is// animated (animateFloatAsState) so it interpolates; the track is squared to// NockerlProgressTrackShape (= RoundedCornerShape(2.dp), NockerlShapes.kt).import androidx.compose.material3.LinearProgressIndicatorimport androidx.compose.animation.core.animateFloatAsStateimport com.nockerl.app.core.theme.NockerlProgressTrackShape
val animatedProgress by animateFloatAsState( targetValue = completedCount.toFloat() / totalCount, label = "todoProgress",)LinearProgressIndicator( progress = { animatedProgress }, modifier = Modifier .fillMaxWidth() .height(3.dp) .clip(NockerlProgressTrackShape), color = colors.accentPrimary, // plain cyan accent, no threshold banding trackColor = colors.cardHairline, // the recessed track)
// Indeterminate: drop the `progress` lambda (the streaming/unknown-length form).LinearProgressIndicator( modifier = Modifier.fillMaxWidth().height(3.dp).clip(NockerlProgressTrackShape), color = colors.accentPrimary, trackColor = colors.cardHairline,)// macOS: SwiftUI, from the NockerlDesign SwiftPM package. `NockerlProgressBar` is a// PLAIN cyan fill on a recessed hairline track, NO threshold banding (that is the// ContextGauge). The track is SQUARED (2pt `NockerlRadius.track`), never a pill.// A REQUIRED label is the accessible name; determinate exposes its percent as the// accessibility value.import NockerlDesign
// Determinate: a 0…total value drives the fill (defaults to total 1).NockerlProgressBar(value: fraction, label: "Exporting session…", size: .thick)
// Indeterminate: omit `value` (a segment slides edge to edge; frozen under Reduce Motion).NockerlProgressBar(label: "Connecting to gateway…")
// Completion / failure tone. Pair with a text/icon signal (never color alone).NockerlProgressBar(value: 1, label: "Snapshot uploaded", tone: .success)NockerlProgressBar(value: 0.8, label: "Build artifacts", tone: .error)
// Determinate ring with a center % readout (indeterminate circular = the Spinner).NockerlProgressRing(value: fraction, label: "Export")
// Buffer + segmented forms are not in NockerlDesign yet (web/Android-first follow-ups).Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
value | number | Current progress (0 to max). Drives the cyan fill width / filled segments / ring sweep. Omit for indeterminate. | |
max | number | 100 | Upper bound. Use a small integer (e.g. 5) with the segmented variant for stepped progress. |
label * | string | Accessible name; rendered left of the % readout. Bound to the body.small type role. | |
variant | 'linear' | 'segmented' | 'ring' | 'linear' | Continuous bar, discrete cells, or a determinate ring with a center %. |
indeterminate | boolean | false | Unknown-length work: a sliding track. Omits aria-valuenow, sets aria-busy; the slide freezes under reduced-motion. |
buffer | number | Optional secondary progress (0 to max) shown as a lighter track behind the primary fill (e.g. received vs. played). | |
size | 'thin' | 'thick' | 'thin' | Track height. thin matches the app (3 to 4dp); thick is the chunkier readout form. |
tone | 'accent' | 'success' | 'error' | 'accent' | Fill color. accent is the plain cyan (no banding); success/error pair with an icon + message (never color alone). |
The bar is Material 3 LinearProgressIndicator styled to the Nockerl track. There
is no bespoke NockerlProgressBar composable yet (segmented / buffer / ring are
not shipped; see drift).
| Parameter | Type | Default | Description |
|---|---|---|---|
progress | () -> Float | Lambda returning the fraction (0f..1f). Feed it an animateFloatAsState value so it interpolates. Omit for the indeterminate overload. | |
modifier | Modifier | Modifier | Sizing + shape. Convention: .fillMaxWidth().height(3.dp).clip(NockerlProgressTrackShape) (the 2.dp squared track). |
color | Color | colors.accentPrimary | The fill color, the brand cyan accent. No threshold banding (that is the context gauge). |
trackColor | Color | colors.cardHairline | The recessed track behind the fill. |
NockerlProgressBar is determinate when value is set, indeterminate when it is
nil. NockerlProgressRing is determinate-only (indeterminate-circular is the
spinner). Both require a label. size / tone are the
package enums below.
| Parameter | Type | Default | Description |
|---|---|---|---|
value | Double? | Progress in 0...total. Omit / nil for the indeterminate slide (bar only; the ring takes a non-optional Double). | |
total | Double | 1 | The full extent of value. |
label * | String | The REQUIRED accessible name. Determinate exposes the percent as the a11y value. Empty is a runtime assert (law §13). | |
size | NockerlProgressSize | .thin | Bar track height: .thin (3pt) or .thick (4pt). Bar only. |
tone | NockerlProgressTone | .accent | .accent (plain cyan, no banding), .success, or .error. Pair success/error with a text/icon signal. |
diameter | CGFloat | NockerlSpace.space12 | Ring size (48pt default). Ring only. |
showsReadout | Bool | true | Render the centered percent text in the ring. Ring only. |