@@ -10,15 +10,24 @@ import androidx.compose.material.ripple.RippleAlpha
1010import androidx.compose.material.ripple.RippleTheme
1111import androidx.compose.runtime.Composable
1212import androidx.compose.runtime.CompositionLocalProvider
13+ import androidx.compose.runtime.derivedStateOf
14+ import androidx.compose.runtime.getValue
1315import androidx.compose.runtime.remember
1416import androidx.compose.ui.Alignment
1517import androidx.compose.ui.Modifier
1618import androidx.compose.ui.graphics.Color
1719import androidx.compose.ui.graphics.Shape
20+ import androidx.compose.ui.graphics.takeOrElse
21+ import androidx.compose.ui.platform.LocalLayoutDirection
1822import androidx.compose.ui.res.painterResource
23+ import androidx.compose.ui.unit.Dp
1924import androidx.compose.ui.unit.dp
2025import com.getcode.R
2126import com.getcode.theme.*
27+ import com.getcode.util.calculateHorizontalPadding
28+ import com.getcode.util.calculateVerticalPadding
29+ import com.getcode.util.minus
30+ import com.getcode.util.plus
2231
2332enum class ButtonState {
2433 Bordered ,
@@ -27,6 +36,7 @@ enum class ButtonState {
2736 Subtle
2837}
2938
39+ @OptIn(ExperimentalMaterialApi ::class )
3040@Composable
3141fun CodeButton (
3242 modifier : Modifier = Modifier ,
@@ -38,75 +48,66 @@ fun CodeButton(
3848 enabled : Boolean = true,
3949 buttonState : ButtonState = ButtonState .Bordered ,
4050 isPaddedVertical : Boolean = true,
41- textColor : Color ? = null,
42- isMaxWidth : Boolean = true,
51+ textColor : Color = Color .Unspecified ,
4352 shape : Shape = CodeTheme .shapes.small,
4453) {
45- val isEnabledC = enabled && ! isLoading && ! isSuccess
54+ val isEnabled by remember(enabled, isLoading, isSuccess) {
55+ derivedStateOf { enabled && ! isLoading && ! isSuccess }
56+ }
57+ val isSuccessful by remember(isSuccess, isTextSuccess) {
58+ derivedStateOf { isSuccess || isTextSuccess }
59+ }
4660 val colors = getButtonColors(buttonState, textColor)
47- val border = getButtonBorder(buttonState, isEnabledC )
61+ val border = getButtonBorder(buttonState, isEnabled )
4862 val ripple = getRipple(
4963 buttonState = buttonState,
50- contentColor = colors.contentColor(enabled = isEnabledC ).value
64+ contentColor = colors.contentColor(enabled = isEnabled ).value
5165 )
5266
53- CompositionLocalProvider (LocalRippleTheme provides ripple) {
67+ CompositionLocalProvider (
68+ LocalMinimumInteractiveComponentEnforcement provides false ,
69+ LocalRippleTheme provides ripple
70+ ) {
5471 Button (
55- onClick = { onClick() },
56- modifier = modifier
57- .let { if (isMaxWidth) it.fillMaxWidth() else it },
72+ onClick = onClick,
73+ modifier = modifier,
5874 colors = colors,
5975 border = border,
60- enabled = isEnabledC ,
76+ enabled = isEnabled ,
6177 elevation = elevation(
6278 defaultElevation = 0 .dp,
6379 pressedElevation = 0 .dp
6480 ),
6581 shape = shape,
82+ contentPadding = ButtonDefaults .ContentPadding .plus(
83+ top = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp,
84+ bottom = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp,
85+ )
6686 ) {
67- Box {
68- Text (
69- text = " " ,
70- style = CodeTheme .typography.button,
71- modifier = Modifier .padding(
72- vertical = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp,
73- ),
74- )
87+ when {
88+ isLoading -> {
89+ CodeCircularProgressIndicator (
90+ strokeWidth = CodeTheme .dimens.thickBorder,
91+ color = White ,
92+ modifier = Modifier
93+ .size(CodeTheme .dimens.grid.x3)
94+ )
95+ }
7596
76- Row {
77- if (isLoading) {
78- CodeCircularProgressIndicator (
79- strokeWidth = CodeTheme .dimens.thickBorder,
80- color = White ,
81- modifier = Modifier
82- .padding(vertical = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp)
83- .size(CodeTheme .dimens.grid.x4)
84- .align(Alignment .CenterVertically )
85- )
86- } else {
87- if (isSuccess || isTextSuccess) {
88- Image (
89- painter = painterResource(id = R .drawable.ic_check),
90- contentDescription = " " ,
91- modifier = Modifier
92- .padding(
93- horizontal = CodeTheme .dimens.grid.x1,
94- vertical = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp
95- )
96- .align(Alignment .CenterVertically )
97- )
98- }
99- if (! isSuccess) {
100- Text (
101- text = text,
102- style = CodeTheme .typography.button,
103- modifier = Modifier .padding(
104- vertical = if (isPaddedVertical) CodeTheme .dimens.grid.x3 else 0 .dp,
105- horizontal = CodeTheme .dimens.grid.x2,
106- )
107- )
108- }
109- }
97+ isSuccessful -> {
98+ Icon (
99+ modifier = Modifier .requiredSize(CodeTheme .dimens.grid.x3),
100+ painter = painterResource(id = R .drawable.ic_check),
101+ tint = Color .Unspecified ,
102+ contentDescription = " " ,
103+ )
104+ }
105+
106+ else -> {
107+ Text (
108+ text = text,
109+ style = CodeTheme .typography.button,
110+ )
110111 }
111112 }
112113 }
@@ -144,32 +145,35 @@ fun getRipple(
144145@Composable
145146fun getButtonColors (
146147 buttonState : ButtonState = ButtonState .Bordered ,
147- textColor : Color ? = null ,
148+ textColor : Color = Color . Unspecified ,
148149): ButtonColors {
149150 return when (buttonState) {
150151 ButtonState .Filled -> ButtonDefaults .buttonColors(
151152 backgroundColor = White ,
152- contentColor = textColor ? : Color (0XFF121212 ),
153+ contentColor = textColor.takeOrElse { Color (0XFF121212 ) } ,
153154 disabledBackgroundColor = White10 ,
154155 disabledContentColor = White10 ,
155156 )
157+
156158 ButtonState .Bordered ->
157159 ButtonDefaults .outlinedButtonColors(
158160 backgroundColor = Brand ,
159161 disabledContentColor = Color .LightGray ,
160- contentColor = textColor ? : Color .LightGray ,
162+ contentColor = textColor.takeOrElse { Color .LightGray }
161163 )
164+
162165 ButtonState .Filled10 ->
163166 ButtonDefaults .outlinedButtonColors(
164167 backgroundColor = White10 ,
165168 disabledContentColor = White50 ,
166- contentColor = textColor ? : White50 ,
169+ contentColor = textColor.takeOrElse { White50 } ,
167170 )
171+
168172 ButtonState .Subtle ->
169173 ButtonDefaults .outlinedButtonColors(
170174 backgroundColor = Transparent ,
171175 disabledContentColor = Transparent ,
172- contentColor = textColor ? : BrandLight ,
176+ contentColor = textColor.takeOrElse { BrandLight } ,
173177 )
174178 }
175179}
@@ -181,7 +185,7 @@ fun getButtonBorder(buttonState: ButtonState, isEnabled: Boolean = true): Border
181185 if (buttonState == ButtonState .Bordered && isEnabled) {
182186 BorderStroke (border, White50 )
183187 } else {
184- BorderStroke (border, Color . Transparent )
188+ null
185189 }
186190 }
187191}
0 commit comments