Skip to content

ColorSwatchPicker

A horizontal row of circular color swatches with an animated selection ring, mirroring the ColorOS 16 icon mono-color selector (UxColorSelectableView): a 34dp color dot inside a 44dp cell, with a 2dp theme-colored ring that fades in on selection.

Import

kotlin
import io.github.suqi8.coui.kmp.basic.ColorSwatchPicker
import io.github.suqi8.coui.kmp.basic.ColorSwatchPickerDefaults

Basic Usage

kotlin
val colors = remember {
    listOf(
        Color(0xFF0066FF),
        Color(0xFF24B232),
        Color(0xFFF08222),
        Color(0xFFDB382C),
    )
}
var selectedIndex by remember { mutableIntStateOf(0) }

ColorSwatchPicker(
    colors = colors,
    selectedIndex = selectedIndex,
    onSwatchSelected = { selectedIndex = it },
)

Build the colors list inside a remember { } block (or keep the same instance across compositions): standard List is unstable to Compose and a fresh instance would defeat recomposition skipping.

Component States

No Selection

Pass a negative selectedIndex to render the row without any selection ring:

kotlin
ColorSwatchPicker(
    colors = colors,
    selectedIndex = -1,
    onSwatchSelected = { selectedIndex = it },
)

Disabled State

kotlin
ColorSwatchPicker(
    colors = colors,
    selectedIndex = selectedIndex,
    onSwatchSelected = { selectedIndex = it },
    enabled = false,
)

Properties

ColorSwatchPicker

PropertyTypeDescriptionDefault ValueRequired
colorsList<Color>Colors displayed as swatches-Yes
selectedIndexIntIndex of the selected swatch (negative for none)-Yes
onSwatchSelected(Int) -> UnitCallback with the index of the swatch the user selects-Yes
modifierModifierModifier applied to the pickerModifierNo
enabledBooleanWhether the picker is enabledtrueNo
swatchSizeDpDiameter of each color dotColorSwatchPickerDefaults.SwatchSizeNo
cellSizeDpTouch target / selection ring outer diameterColorSwatchPickerDefaults.CellSizeNo
ringStrokeWidthDpStroke width of the selection ringColorSwatchPickerDefaults.RingStrokeWidthNo
ringColorColorColor of the selection ringCOUITheme.colorScheme.primaryNo
spacingDpSpacing between adjacent cellsColorSwatchPickerDefaults.SpacingNo

ColorSwatchPickerDefaults

ConstantTypeDefault ValueCOUI Source
SwatchSizeDp34.dpux_icon_color_select_inside
CellSizeDp44.dpux_icon_color_select_out
RingStrokeWidthDp2.dpux_theme_shadow_stroke
SpacingDp0.dpcells laid edge to edge
RingFadeInDurationInt280selection animator duration
RingFadeOutDurationInt150deselection animator duration
RingEasingCubicBezierEasingCubicBezierEasing(0.33f, 0f, 0.67f, 1f)PathInterpolator(0.33, 0, 0.67, 1)

Behavior

  • Tapping a cell invokes onSwatchSelected with the cell index; the component is stateless and the caller owns the selection.
  • The selection ring fades in over 280ms and fades out over 150ms with the COUI easing curve.
  • Each cell exposes Role.RadioButton semantics inside a selectable group for accessibility.

Advanced Usage

Custom Sizing and Ring

All metrics and the ring color can be overridden. The example below spaces the cells apart and uses a custom ring:

kotlin
ColorSwatchPicker(
    colors = colors,
    selectedIndex = selectedIndex,
    onSwatchSelected = { selectedIndex = it },
    swatchSize = 28.dp,
    cellSize = 36.dp,
    ringStrokeWidth = 3.dp,
    ringColor = Color(0xFFDB382C),
    spacing = 8.dp,
)

Changelog

Released under the Apache-2.0 License