After PR #416 added a 4-dot overlay to the PIN entry field to show how many digits had been entered, the actual digit characters were visible as small numbers showing through the gaps between the dot circles.
The overlay approach used a transparent Row of Box circles drawn on top of an OutlinedTextField. In Compose, Arrangement.SpaceEvenly on 4 × 16dp circles inside a 100dp container leaves ~7.2dp gaps between each circle. The underlying OutlinedTextField was visible through those gaps.
Setting focusedTextColor = Color.Transparent is fragile: it does not suppress text rendered during selection, and on some Compose/platform versions the selection highlight or composition annotation rendering can bypass the text color and make digit shapes faintly visible. Additionally, the empty label = { Text("") } forced the floating-label animation slot even though no label text was present.
visualTransformation = PasswordVisualTransformation() to the OutlinedTextField. This is the idiomatic Compose approach: characters are replaced with • at the framework rendering layer before any color is applied, so even if transparency fails, no digit character shapes reach the screen.Box (containing the field and the dots overlay) in CompositionLocalProvider(LocalTextSelectionColors provides TextSelectionColors(handleColor = Color.Transparent, backgroundColor = Color.Transparent)). This suppresses the selection highlight that can make text visible when the user taps or long-presses inside the field.label = { Text("") } argument — it caused a redundant floating-label animation slot with no user benefit.Color.Transparent on text color) are brittle. Always pair with PasswordVisualTransformation() for defense in depth.PasswordVisualTransformation + transparent text color so there is nothing to expose even through gaps.CompositionLocalProvider(LocalTextSelectionColors …) with transparent colors to suppress selection leakage.