Yorkshire Systems

ButtonsFlow

See Button for the custom button class.

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import yorkshire.systems.resonance.R
import yorkshire.systems.resonance.ui.components.preview.PreviewContainer

private val flowSpacing = Arrangement.spacedBy(6.dp)

class FlowButton(@StringRes val stringRes: Int, val onClick: () -> Unit)

@Composable
fun ActionButtonsFlow(
    actions: List<FlowButton>,
    modifier: Modifier = Modifier,
) {
    FlowRow(
        modifier = modifier,
        horizontalArrangement = flowSpacing,
    ) {
        actions.forEach { action ->
            Button(
                text = stringResource(action.stringRes),
                onClick = action.onClick,
            )
        }
    }
}

@Composable
private fun <T> ChoiceButtonsFlow(
    items: List<T>,
    modifier: Modifier,
    role: Role,
    isSelected: (T) -> Boolean,
    label: @Composable (T) -> String,
    @DrawableRes selectedIconRes: Int?,
    onItem: (T) -> Unit,
) {
    FlowRow(
        modifier = modifier.selectableGroup(),
        horizontalArrangement = flowSpacing,
    ) {
        items.forEach { item ->
            SelectableFlowButton(
                text = label(item),
                selected = isSelected(item),
                selectedIconRes = selectedIconRes,
                role = role,
            ) { onItem(item) }
        }
    }
}

@Composable
fun <T> ButtonsFlow(
    items: List<T>,
    modifier: Modifier = Modifier,
    selected: T? = null,
    label: @Composable (T) -> String = { it.toString() },
    @DrawableRes selectedIconRes: Int? = null,
    onItem: (T) -> Unit,
) {
    ChoiceButtonsFlow(
        items = items,
        modifier = modifier,
        role = Role.RadioButton,
        isSelected = { it == selected },
        label = label,
        selectedIconRes = selectedIconRes,
        onItem = onItem,
    )
}

@Composable
fun <T> MultiChoiceButtonsFlow(
    items: List<T>,
    modifier: Modifier = Modifier,
    selected: Set<T> = emptySet(),
    label: @Composable (T) -> String = { it.toString() },
    @DrawableRes selectedIconRes: Int? = null,
    onItem: (T) -> Unit,
) {
    ChoiceButtonsFlow(
        items = items,
        modifier = modifier,
        role = Role.Checkbox,
        isSelected = { it in selected },
        label = label,
        selectedIconRes = selectedIconRes,
        onItem = onItem,
    )
}