Coverage Summary for Class: SurferSelectableChipKt (com.georgeci.moneysurfer.uikit.components.base)

Class Class, % Method, % Branch, % Line, % Instruction, %
SurferSelectableChipKt 100% (1/1) 100% (1/1) 70% (14/20) 100% (35/35) 98.5% (407/413)


 package com.georgeci.moneysurfer.uikit.components.base
 
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.Icon
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.semantics.selected
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import com.georgeci.moneysurfer.uikit.icons.SurferIcons
 import com.georgeci.moneysurfer.uikit.semantics.SurferSemantics
 import com.georgeci.moneysurfer.uikit.theme.AppTheme
 
 /**
  * A single 32dp pill chip with a 10dp corner: when [selected] it fills with `secondaryContainer`
  * (and optionally shows a leading check); otherwise it stays outline-only. The one shared shape
  * behind both the mutually-exclusive [SurferFilterChipRow] and the transactions filter rail, so a
  * tweak to the selected fill or corner lands in one place.
  *
  * [showCheck] draws the leading check on selection — on for a single-select row where the check is
  * the selection cue, off for a value-carrying chip whose fill alone signals it is set.
  */
 @Composable
 fun SurferSelectableChip(
     label: String,
     selected: Boolean,
     onClick: () -> Unit,
     modifier: Modifier = Modifier,
     showCheck: Boolean = true,
 ) {
     val fg = if (selected) {
         AppTheme.materialColors.onSecondaryContainer
     } else {
         AppTheme.materialColors.onSurface
     }
     Row(
         modifier = modifier
             // Without this, selection is a fill colour and a deliberately decorative check —
             // nothing a screen reader, or a test, can read back. `this.` is load-bearing: the
             // bare name inside `semantics {}` is the parameter, not the property.
             .semantics { this.selected = selected }
             .height(32.dp)
             .clip(RoundedCornerShape(10.dp))
             .background(if (selected) AppTheme.materialColors.secondaryContainer else Color.Transparent)
             .border(
                 width = 1.dp,
                 color = if (selected) Color.Transparent else AppTheme.materialColors.outline,
                 shape = RoundedCornerShape(10.dp),
             )
             .clickable(onClick = onClick)
             .padding(horizontal = 12.dp),
         verticalAlignment = Alignment.CenterVertically,
         horizontalArrangement = Arrangement.spacedBy(4.dp),
     ) {
         if (selected && showCheck) {
             Icon(
                 imageVector = SurferIcons.Check,
                 contentDescription = SurferSemantics.Decorative,
                 tint = fg,
                 modifier = Modifier.size(14.dp),
             )
         }
         Text(
             text = label,
             style = AppTheme.typography.labelLarge,
             color = fg,
             maxLines = 1,
         )
     }
 }