Pantrix UI

Progress Circle

A ring that fills as something gets done: how much of an upload has gone, how many steps of a set-up are behind, how much of a quota is used. It shows a share of a whole that is known; for work whose end is not known there is the spinner.

import com.pantrixui.components.chart.progresscircle.PantrixProgressCircle

Examples

A share of a whole

At its plainest: a piece of work seventy-two per cent done. max is a hundred where it is not given.

PantrixProgressCircle(value = 72, contentDescription = "Uploaded", tagKey = "plain")

With its share in the middle

The share is written in the middle of the ring and changes with the buttons: the ring goes to the new value. The writing in the middle is hidden from the screen reader (clearAndSetSemantics): the ring itself says the share.

var done by remember { mutableStateOf(3) }
Row(
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.md),
    verticalAlignment = Alignment.CenterVertically
) {
    PantrixProgressCircle(
        value = done,
        max = 8,
        contentDescription = "Set-up",
        style = ProgressCircleStyle(size = 72.dp, strokeWidth = 8.dp),
        tagKey = "share"
    ) {
        PantrixText(text = "$done/8", modifier = Modifier.clearAndSetSemantics { })
    }
    PantrixButton(
        text = "Back",
        onClick = { done = (done - 1).coerceAtLeast(0) },
        variant = ButtonVariant.Outline,
        tagKey = "progress_back"
    )
    PantrixButton(text = "Next", onClick = { done = (done + 1).coerceAtMost(8) }, tagKey = "progress_next")
}

Sizes

Three sizes, with ProgressCircleStyle: small in a row, medium on a card, large at the head of a summary. The ring's thickness is given with its size.

Row(
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
    verticalAlignment = Alignment.CenterVertically
) {
    PantrixProgressCircle(
        value = 40,
        contentDescription = "Small",
        style = ProgressCircleStyle(size = 32.dp, strokeWidth = 4.dp),
        tagKey = "small"
    )
    PantrixProgressCircle(value = 40, contentDescription = "Medium", tagKey = "medium")
    PantrixProgressCircle(
        value = 40,
        contentDescription = "Large",
        style = ProgressCircleStyle(size = 96.dp, strokeWidth = 10.dp),
        tagKey = "large"
    )
}

Colours

The ring's colour can say what it shows: a quota that is running low in the warning colour, one that is full in the danger colour. On a filled surface a ring that is given no colour is drawn in the surface's content colour.

val colors = PantrixTheme.colors
Row(
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
    verticalAlignment = Alignment.CenterVertically
) {
    PantrixProgressCircle(value = 35, color = colors.success.color, contentDescription = "Quota", tagKey = "ok")
    PantrixProgressCircle(value = 80, color = colors.warning.color, contentDescription = "Quota", tagKey = "warn")
    PantrixProgressCircle(value = 97, color = colors.danger.color, contentDescription = "Quota", tagKey = "full")
    PantrixSurface(color = colors.primary.color) {
        PantrixProgressCircle(
            value = 60,
            modifier = Modifier.padding(PantrixTheme.spacing.md),
            contentDescription = "Uploaded",
            tagKey = "on_fill"
        )
    }
}

Export

export = ChartExport(...) puts an export button over the chart: press it and choose the kind (PNG, SVG or PDF). The chart makes the file and hands it to onExport; below, its name and size show, and a PNG's picture, and "Save the file" hands it over in the platform's way.

The file draws the ring as far as it is filled; what stands in it by content is not in the file. export comes before content: the trailing lambda is still what stands in the middle.

var file by remember { mutableStateOf<ChartExportFile?>(null) }
PantrixProgressCircle(
    value = 72,
    contentDescription = "Uploaded",
    tagKey = "exported",
    export = ChartExport(fileName = "uploaded") { file = it }
) {
    PantrixText(text = PantrixTheme.strings.percent(0.72), style = PantrixTheme.typography.caption)
}
ExportedFile(file, tagKey = "exported")

API

value

A ring that fills as something gets done: how much of an upload has gone, how many steps of a set-up are behind, how much of a quota is used. It shows a share of a whole that is known; for work whose end is not known there is the spinner.

ParameterTypeDefaultWhat it is
valueNumberhow much is done, between nought and max. What is no number counts as nought.
modifierModifierModifierthe circle's modifier. A size here is the circle's.
maxNumber100how much the whole is: more than nought.
colorColorColor.Unspecifiedthe colour of the ring.
trackColorColorColor.Unspecifiedthe colour of the ring's track, the whole it fills.
contentDescriptionString?nullwhat is progressing, in a word or two, for a screen reader.
styleProgressCircleStyle?nullthis circle's own geometry: its size and how thick its ring is.
tagKeyString?nullthe circle's automation key: the circle is ProgressCircle_<tagKey>.
exportChartExport?nullwhat lets the reader take the circle out of the app as a PNG, an SVG or a PDF: a button over it makes the file of it as it is and hands it over (see ChartExport). null, it has no such button. What stands in the circle, content, is not in the file. It comes before content, which stays last.
content(@Composable () -> Unit)?nullwhat stands in the middle of the ring. It has the room inside the ring.

ProgressCircleStyle

PantrixProgressCircle's geometry.

ParameterTypeDefaultWhat it is
sizeDpDp.UnspecifiedThe circle's width and height: 56dp on every platform, unless a brand or a theme sets another.
strokeWidthDpDp.UnspecifiedHow thick the ring is: 6dp. A ring is no thicker than a quarter of its circle.

Accessibility