EARHORNMUSIC UPnP · Android TV · Phones · Android Auto · GNU/Linux
Release 0.5.0

StaveFocus.kt

33 lines · 1.4 KB

Changed in: 0.5.0

1package dev.stave.ui.theme
2
3import androidx.compose.foundation.border
4import androidx.compose.foundation.interaction.MutableInteractionSource
5import androidx.compose.foundation.interaction.collectIsFocusedAsState
6import androidx.compose.foundation.shape.RoundedCornerShape
7import androidx.compose.runtime.Composable
8import androidx.compose.runtime.getValue
9import androidx.compose.runtime.remember
10import androidx.compose.ui.Modifier
11import androidx.compose.ui.draw.clip
12import androidx.compose.ui.unit.dp
13
14/**
15 * Earhorn's keyboard-focus visual, ported from Android's `staveFocusable`: a
16 * 2dp [FocusRing] border while focused, nothing otherwise (the caller paints its
17 * own background and hover wash). Amber on SurfaceBase is 8.50:1, well over the
18 * 3:1 WCAG 2.4.11 asks of a focus indicator; a translucent amber wash is ~1.3:1.
19 *
20 * Pass the same [interactionSource] to the clickable/toggleable/selectable that
21 * makes the element focusable.
22 */
23@Composable
24fun Modifier.staveFocusRing(
25 interactionSource: MutableInteractionSource,
26 cornerRadiusDp: Int = 8,
27): Modifier {
28 val focused by interactionSource.collectIsFocusedAsState()
29 val shape = remember(cornerRadiusDp) { RoundedCornerShape(cornerRadiusDp.dp) }
30 return this
31 .clip(shape)
32 .then(if (focused) Modifier.border(2.dp, FocusRing, shape) else Modifier)
33}