StrengthBar.kt

2.3 KB · raw

1package com.peachpasswords.ui.security23import androidx.compose.foundation.background4import androidx.compose.foundation.layout.Box5import androidx.compose.foundation.layout.Row6import androidx.compose.foundation.layout.fillMaxWidth7import androidx.compose.foundation.layout.height8import androidx.compose.foundation.layout.padding9import androidx.compose.foundation.shape.RoundedCornerShape10import androidx.compose.runtime.Composable11import androidx.compose.ui.Modifier12import androidx.compose.ui.draw.clip13import androidx.compose.ui.graphics.Color14import androidx.compose.ui.unit.dp15import com.peachpasswords.ui.theme.LocalPeachAccent16import com.peachpasswords.ui.theme.peachColors1718/**19 * Amber for the mid-range ("weak"/"fair") fill. PeachColors has no amber token,20 * and the spec calls for one distinct from breach (low) and health (high), so it21 * is defined locally rather than hardcoded inline at each call site.22 */23private val StrengthAmber = Color(0xCCE0A040)2425/**26 * Fill color for a given [score], per spec §E1:27 *   0 → breach, 1–2 → amber, 3 → health, 4 → accent.28 */29@Composable30fun strengthColor(score: Int): Color {31    val accent = LocalPeachAccent.current32    return when (score.coerceIn(0, 4)) {33        0 -> peachColors.Breach34        1, 2 -> StrengthAmber35        3 -> peachColors.HealthOk36        else -> accent37    }38}3940/**41 * Four-segment strength bar, 4dp tall, full width. The number of *lit* segments42 * follows the spec ramp (1/2/3/4/4 for scores 0..4); unlit segments use T3.43 *44 * Filled-segment count differs from the raw score so score 0 still shows one lit45 * (breach-colored) segment as feedback rather than an empty bar.46 */47@Composable48fun StrengthBar(score: Int, modifier: Modifier = Modifier) {49    val s = score.coerceIn(0, 4)50    val lit = when (s) {51        0 -> 152        1 -> 253        2 -> 354        else -> 455    }56    val fill = strengthColor(s)57    Row(modifier = modifier.fillMaxWidth()) {58        repeat(4) { i ->59            Box(60                modifier = Modifier61                    .weight(1f)62                    .height(4.dp)63                    .padding(end = if (i < 3) 4.dp else 0.dp)64                    .clip(RoundedCornerShape(2.dp))65                    .background(if (i < lit) fill else peachColors.T3),66            )67        }68    }69}