Pith - shim
package com.vgmlr.shim

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
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.graphics.vector.ImageVector
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntRect
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupPositionProvider
import androidx.compose.ui.window.PopupProperties
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border

internal val TOP_BAR_H = 64.dp
internal val BAR_GAP = 8.dp
internal val SEARCH_FIELD_H = 48.dp
internal val BAR_EDGE = 12.dp
internal val BAR_EDGE_ACTIONS = 8.dp

internal val LIST_PAD_START = BAR_EDGE
internal val LIST_PAD_END = BAR_EDGE_ACTIONS
internal val LIST_PAD_V = 8.dp
internal val LIST_PAD_TOP = 12.dp

internal val ROUND_END = 6.dp
internal val ROUND_LESS = 4.dp

internal val EDGE = BorderStroke(1.dp, Color(0xFF868D97).copy(alpha = 0.30f))
internal val WARN_BG = Color(0xFF880000)
internal const val ARM_HOLD = 3_000L

internal val BTN_SIZE = 48.dp
internal val BTN_ICON = 26.dp
internal val BTN_PAD = 11.dp
internal val BTN_ICON_LG = 30.dp
internal val BTN_PAD_LG = 9.dp
internal val BTN_ICON_SM = 25.dp
internal val DOCK_PAD = 16.dp

private val TITLE_PAD = 16.dp
private val TITLE_FS = 18.sp

private val BelowAnchorEnd = object : PopupPositionProvider {
    override fun calculatePosition(
        anchorBounds: IntRect,
        windowSize: IntSize,
        layoutDirection: LayoutDirection,
        popupContentSize: IntSize
    ) = IntOffset(anchorBounds.right - popupContentSize.width, anchorBounds.bottom)
}

@Composable
fun ShimButton(
    icon: ImageVector,
    desc: String?,
    modifier: Modifier = Modifier,
    iconSize: Dp = BTN_ICON,
    iconPad: Dp = BTN_PAD,
    enabled: Boolean = true,
    bg: Color = Color.Unspecified,
    onClick: () -> Unit
) {
    val fill = if (bg == Color.Unspecified) colorResource(id = R.color.primary_color) else bg
    Box(
        modifier = modifier
            .size(BTN_SIZE)
            .clip(RoundedCornerShape(ROUND_END))
            .background(fill)
            .clickable(enabled = enabled, onClick = onClick)
            .padding(iconPad),
        contentAlignment = Alignment.Center
    ) {
        Icon(
            icon,
            contentDescription = desc,
            modifier = Modifier.size(iconSize),
            tint = colorResource(id = R.color.title_color)
                .copy(alpha = if (enabled) 1f else 0.3f)
        )
    }
}

@Composable
fun ShimTitle(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = colorResource(id = R.color.primary_color)
) {
    Box(
        modifier = modifier
            .height(BTN_SIZE)
            .clip(RoundedCornerShape(ROUND_END))
            .background(color)
            .border(EDGE, RoundedCornerShape(ROUND_END))
            .padding(horizontal = TITLE_PAD),
        contentAlignment = Alignment.CenterStart
    ) {
        Text(
            text = text,
            color = colorResource(id = R.color.title_color),
            fontSize = TITLE_FS,
            maxLines = 1
        )
    }
}

@Composable
fun ShimMenu(
    expanded: Boolean,
    onDismiss: () -> Unit,
    content: @Composable ColumnScope.() -> Unit
) {
    if (!expanded) return
    Popup(
        popupPositionProvider = BelowAnchorEnd,
        onDismissRequest = onDismiss,
        properties = PopupProperties(focusable = true)
    ) {
        Column(
            modifier = Modifier.padding(top = BAR_GAP),
            verticalArrangement = Arrangement.spacedBy(BAR_GAP),
            content = content
        )
    }
}

@Composable
fun ShimMenuItem(
    label: String,
    icon: ImageVector,
    iconSize: Dp = BTN_ICON,
    iconPad: Dp = BTN_PAD,
    enabled: Boolean = true,
    onClick: () -> Unit
) {
    ShimButton(
        icon = icon,
        desc = label,
        iconSize = iconSize,
        iconPad = iconPad,
        enabled = enabled,
        onClick = onClick
    )
}

@Composable
fun BoxScope.ShimDock(content: @Composable RowScope.() -> Unit) {
    Row(
        Modifier
            .align(Alignment.BottomCenter)
            .navigationBarsPadding()
            .padding(bottom = DOCK_PAD),
        horizontalArrangement = Arrangement.spacedBy(BAR_GAP),
        verticalAlignment = Alignment.CenterVertically,
        content = content
    )
}