package com.suno.android.common_ui.components.omni import android.os.Build.VERSION import android.os.Build.VERSION_CODES import androidx.annotation.DrawableRes import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.paint import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import com.suno.android.common_ui.R import com.suno.android.common_ui.components.IconBadge import com.suno.android.common_ui.components.aura.auraBackground import com.suno.android.common_ui.extensions.conditional import com.suno.android.common_ui.theme.ExtendedTheme import com.suno.android.common_ui.theme.SunoTheme private const val BUTTON_SIZE = 48 private const val ICON_SIZE = 24 private const val DISABLED_ALPHA = 0.38f @Composable fun CircleIconButton( @DrawableRes vectorDrawableResId: Int, contentDescription: String?, modifier: Modifier = Modifier, inverted: Boolean = false, onClick: () -> Unit = {}, bgColor: Color? = null, auraBg: Boolean = false, enabled: Boolean = true, iconColor: Color? = null, displayText: String? = null, showProgressIndicator: Boolean = false, showBadge: Boolean = false, ) { val interactionSource = remember { MutableInteractionSource() } Box( modifier = modifier .semantics { role = Role.Button } .clickable( interactionSource = interactionSource, indication = null, enabled = enabled, onClick = onClick, ) .alpha(if (enabled) 1f else DISABLED_ALPHA), ) { val defaultIconTint = if (inverted) { ExtendedTheme.colors.backgroundQuarternary } else { ExtendedTheme.colors.textPrimary } val effectiveIconTint = iconColor ?: defaultIconTint Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .size(BUTTON_SIZE.dp) .clip(CircleShape) .then( if (auraBg) { Modifier.conditional( condition = VERSION.SDK_INT >= VERSION_CODES.TIRAMISU, ifTrue = { auraBackground(enabled = enabled) }, ifFalse = { paint( painter = painterResource(R.drawable.full_width_button_bg), contentScale = ContentScale.Crop, ) }, ) } else { val defaultBgColor = if (inverted) { ExtendedTheme.colors.backgroundInvert } else { ExtendedTheme.colors.backgroundSecondary } Modifier.background(bgColor ?: defaultBgColor) }, ) .clickable( interactionSource = interactionSource, indication = ripple(), enabled = enabled, onClick = onClick, ), ) { if (showProgressIndicator) { CircularProgressIndicator( modifier = Modifier.size(ICON_SIZE.dp), color = effectiveIconTint, ) } else { Icon( modifier = Modifier.size(ICON_SIZE.dp), imageVector = ImageVector.vectorResource( id = vectorDrawableResId, ), tint = effectiveIconTint, contentDescription = contentDescription, ) } if (!displayText.isNullOrEmpty()) { Text( modifier = Modifier.padding(top = 4.dp), text = displayText, style = ExtendedTheme.typography.cardMeta, color = effectiveIconTint, ) } } if (showBadge) { IconBadge( modifier = Modifier .align(Alignment.TopEnd) .offset(x = (-2).dp, y = 2.dp), ) } } } @PreviewLightDark @Composable private fun CircleIconButton_Preview() { SunoTheme { CircleIconButton( vectorDrawableResId = R.drawable.chevron_down, contentDescription = null, ) } } @PreviewLightDark @Composable private fun CircleIconButton_Inverted_Preview() { SunoTheme { CircleIconButton( inverted = true, vectorDrawableResId = R.drawable.chevron_down, contentDescription = null, ) } } @PreviewLightDark @Composable private fun CircleIconButton_Text_Preview() { SunoTheme { CircleIconButton( inverted = true, vectorDrawableResId = R.drawable.chevron_down, displayText = "100", contentDescription = null, ) } } @PreviewLightDark @Composable private fun CircleIconButton_Badged_Preview() { SunoTheme { CircleIconButton( vectorDrawableResId = R.drawable.chevron_down, contentDescription = null, showBadge = true, ) } } @PreviewLightDark @Composable private fun CircleIconButton_Disabled_Preview() { SunoTheme { CircleIconButton( vectorDrawableResId = R.drawable.chevron_down, contentDescription = null, enabled = false, ) } }