package com.suno.android.common_ui.components.buttons import androidx.compose.animation.core.animateFloatAsState 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.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.defaultMinSize 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.LocalContentColor import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.suno.android.common_ui.theme.ExtendedTheme import com.suno.android.common_ui.theme.SunoTheme import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.seconds @Composable fun RoundedButton( buttonText: String, onClick: () -> Unit, modifier: Modifier = Modifier, backgroundColor: Color = ExtendedTheme.colors.backgroundInvert, contentColor: Color = ExtendedTheme.colors.backgroundPrimary, textStyle: TextStyle = ExtendedTheme.typography.body, shape: Shape = CircleShape, leadingPainter: Painter? = null, trailingPainter: Painter? = null, isLoading: Boolean = false, enabled: Boolean = true, maxLines: Int = 1, contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp), ) { RoundedButton( onClick = onClick, modifier = modifier, backgroundColor = backgroundColor, shape = shape, isLoading = isLoading, enabled = enabled, contentPadding = contentPadding, ) { if (leadingPainter != null) { Icon( modifier = Modifier.size(24.dp), painter = leadingPainter, tint = contentColor, contentDescription = buttonText, ) } Text( text = buttonText, style = textStyle, color = contentColor, maxLines = maxLines, ) if (trailingPainter != null) { Icon( modifier = Modifier.size(24.dp), painter = trailingPainter, tint = contentColor, contentDescription = buttonText, ) } } } @Composable fun RoundedButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, contentColor: Color = ExtendedTheme.colors.backgroundPrimary, backgroundColor: Color = ExtendedTheme.colors.backgroundInvert, shape: Shape = CircleShape, isLoading: Boolean = false, contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp), content: @Composable RowScope.() -> Unit, ) { Box( contentAlignment = Alignment.Center, modifier = modifier .defaultMinSize(minHeight = 64.dp) .clip(shape) .alpha( animateFloatAsState( if (isLoading || !enabled) 0.5f else 1f, ).value, ) .background(backgroundColor) .clickable( enabled = !isLoading && enabled, ) { onClick.invoke() } .padding(contentPadding), ) { val loadingAlpha by animateFloatAsState( targetValue = if (isLoading) { 1f } else { 0f }, ) CircularProgressIndicator( modifier = Modifier .alpha(loadingAlpha) .padding(horizontal = 8.dp) .size(24.dp), color = contentColor, ) CompositionLocalProvider( LocalContentColor provides contentColor, ) { Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.alpha(1 - loadingAlpha), ) { content() } } } } @Preview @Composable private fun RoundedBottomButton_Preview() { SunoTheme { RoundedButton( buttonText = "Looks Good", leadingPainter = painterResource(com.suno.android.common_ui.R.drawable.external_link), onClick = {}, ) } } @Preview @Composable private fun RoundedBottomButton_Clickable_Preview() { var isLoading by remember { mutableStateOf(false) } LaunchedEffect(isLoading) { if (isLoading) { delay(1.5.seconds) isLoading = false } } SunoTheme { RoundedButton( buttonText = "Looks Good", leadingPainter = painterResource(com.suno.android.common_ui.R.drawable.external_link), onClick = { isLoading = true }, isLoading = isLoading, ) } } @Preview @Composable private fun RoundedBottomButton_Loading_Preview() { SunoTheme { RoundedButton( buttonText = "Loading", leadingPainter = painterResource(com.suno.android.common_ui.R.drawable.external_link), isLoading = true, onClick = {}, ) } } @Preview @Composable private fun RoundedBottomButton_Disabled_Preview() { SunoTheme { RoundedButton( buttonText = "Disabled!", leadingPainter = painterResource(com.suno.android.common_ui.R.drawable.external_link), enabled = false, onClick = {}, ) } }