Skip to content

Commit 84fdba4

Browse files
committed
feat: new button styles
1 parent 88b9bc2 commit 84fdba4

File tree

5 files changed

+182
-92
lines changed

5 files changed

+182
-92
lines changed

app/src/main/java/to/bitkit/ui/components/Button.kt

Lines changed: 181 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package to.bitkit.ui.components
22

3+
import androidx.compose.animation.animateColorAsState
34
import androidx.compose.foundation.BorderStroke
5+
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.interaction.MutableInteractionSource
7+
import androidx.compose.foundation.interaction.collectIsPressedAsState
48
import androidx.compose.foundation.layout.Arrangement
59
import androidx.compose.foundation.layout.Box
610
import androidx.compose.foundation.layout.Column
@@ -13,22 +17,26 @@ import androidx.compose.foundation.layout.size
1317
import androidx.compose.material.icons.Icons
1418
import androidx.compose.material.icons.filled.Favorite
1519
import androidx.compose.material.icons.filled.Home
16-
import androidx.compose.material3.Button
1720
import androidx.compose.material3.CircularProgressIndicator
1821
import androidx.compose.material3.Icon
19-
import androidx.compose.material3.OutlinedButton
22+
import androidx.compose.material3.LocalContentColor
23+
import androidx.compose.material3.MaterialTheme
24+
import androidx.compose.material3.Surface
2025
import androidx.compose.material3.Text
21-
import androidx.compose.material3.TextButton
2226
import androidx.compose.runtime.Composable
27+
import androidx.compose.runtime.CompositionLocalProvider
28+
import androidx.compose.runtime.getValue
29+
import androidx.compose.runtime.remember
2330
import androidx.compose.ui.Alignment
2431
import androidx.compose.ui.Modifier
2532
import androidx.compose.ui.draw.alpha
33+
import androidx.compose.ui.draw.shadow
2634
import androidx.compose.ui.graphics.Color
2735
import androidx.compose.ui.text.style.TextOverflow
2836
import androidx.compose.ui.tooling.preview.Preview
2937
import androidx.compose.ui.unit.Dp
3038
import androidx.compose.ui.unit.dp
31-
import to.bitkit.ui.theme.AppButtonDefaults
39+
import to.bitkit.ui.shared.util.gradientBackground
3240
import to.bitkit.ui.theme.AppThemeSurface
3341
import to.bitkit.ui.theme.Colors
3442

@@ -57,41 +65,72 @@ fun PrimaryButton(
5765
size: ButtonSize = ButtonSize.Large,
5866
enabled: Boolean = true,
5967
fullWidth: Boolean = true,
60-
color: Color = Colors.White16,
6168
) {
69+
val interactionSource = remember { MutableInteractionSource() }
70+
val isPressed by interactionSource.collectIsPressedAsState()
71+
6272
val contentPadding = PaddingValues(horizontal = size.horizontalPadding.takeIf { text != null } ?: 0.dp)
63-
Button(
64-
onClick = onClick,
65-
enabled = enabled && !isLoading,
66-
colors = AppButtonDefaults.primaryColors.copy(containerColor = color),
67-
contentPadding = contentPadding,
73+
val shape = MaterialTheme.shapes.extraLarge
74+
75+
Surface(
76+
shape = shape,
77+
color = Color.Transparent,
6878
modifier = Modifier
6979
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
7080
.requiredHeight(size.height)
7181
.then(modifier)
72-
) {
73-
if (isLoading) {
74-
CircularProgressIndicator(
75-
color = Colors.White32,
76-
strokeWidth = 2.dp,
77-
modifier = Modifier.size(size.height / 2)
82+
.shadow(
83+
elevation = 4.dp,
84+
shape = shape,
85+
ambientColor = Colors.White.copy(alpha = if (isPressed) 0.4f else 0.25f),
86+
spotColor = Colors.White.copy(alpha = if (isPressed) 0.4f else 0.25f)
7887
)
79-
} else {
80-
Row(
81-
verticalAlignment = Alignment.CenterVertically,
82-
horizontalArrangement = Arrangement.spacedBy(8.dp),
83-
) {
84-
if (icon != null) {
85-
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
86-
icon()
87-
}
88+
.then(
89+
if (isPressed) {
90+
Modifier.gradientBackground(startColor = Colors.Gray4, endColor = Colors.Gray5)
91+
} else {
92+
Modifier.gradientBackground(startColor = Colors.Gray5, endColor = Colors.Black)
8893
}
89-
text?.let {
90-
Text(
91-
text = text,
92-
maxLines = 1,
93-
overflow = TextOverflow.Ellipsis,
94-
)
94+
)
95+
.then(if (enabled) Modifier else Modifier.alpha(0.32f))
96+
.clickable(
97+
onClick = onClick,
98+
enabled = enabled && !isLoading,
99+
interactionSource = interactionSource,
100+
indication = null
101+
)
102+
) {
103+
Box(
104+
contentAlignment = Alignment.Center,
105+
modifier = Modifier
106+
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
107+
.padding(contentPadding)
108+
) {
109+
if (isLoading) {
110+
CircularProgressIndicator(
111+
color = Colors.White32,
112+
strokeWidth = 2.dp,
113+
modifier = Modifier.size(size.height / 2)
114+
)
115+
} else {
116+
CompositionLocalProvider(LocalContentColor provides Colors.White) {
117+
Row(
118+
verticalAlignment = Alignment.CenterVertically,
119+
horizontalArrangement = Arrangement.spacedBy(8.dp),
120+
) {
121+
if (icon != null) {
122+
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
123+
icon()
124+
}
125+
}
126+
text?.let {
127+
Text(
128+
text = text,
129+
maxLines = 1,
130+
overflow = TextOverflow.Ellipsis,
131+
)
132+
}
133+
}
95134
}
96135
}
97136
}
@@ -109,42 +148,70 @@ fun SecondaryButton(
109148
enabled: Boolean = true,
110149
fullWidth: Boolean = true,
111150
) {
151+
val interactionSource = remember { MutableInteractionSource() }
152+
val isPressed by interactionSource.collectIsPressedAsState()
153+
154+
val backgroundColor by animateColorAsState(
155+
targetValue = if (isPressed) Colors.White10 else Colors.White01,
156+
label = "secondaryButtonBackground"
157+
)
158+
val borderColor by animateColorAsState(
159+
targetValue = if (enabled) Colors.Gray4 else Color.Transparent,
160+
label = "secondaryButtonBorder"
161+
)
162+
112163
val contentPadding = PaddingValues(horizontal = size.horizontalPadding.takeIf { text != null } ?: 0.dp)
113-
val border = BorderStroke(2.dp, if (enabled) Colors.White16 else Color.Transparent)
114-
OutlinedButton(
115-
onClick = onClick,
116-
enabled = enabled && !isLoading,
117-
colors = AppButtonDefaults.secondaryColors,
118-
contentPadding = contentPadding,
119-
border = border,
164+
val shape = MaterialTheme.shapes.extraLarge
165+
166+
Surface(
167+
shape = shape,
168+
color = backgroundColor,
169+
border = BorderStroke(2.dp, borderColor),
120170
modifier = Modifier
121171
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
122172
.requiredHeight(size.height)
123173
.then(modifier)
124-
) {
125-
if (isLoading) {
126-
CircularProgressIndicator(
127-
color = Colors.White32,
128-
strokeWidth = 2.dp,
129-
modifier = Modifier.size(size.height / 2)
174+
.clickable(
175+
onClick = onClick,
176+
enabled = enabled && !isLoading,
177+
interactionSource = interactionSource,
178+
indication = null
130179
)
131-
} else {
132-
Row(
133-
verticalAlignment = Alignment.CenterVertically,
134-
horizontalArrangement = Arrangement.spacedBy(8.dp),
135-
) {
136-
if (icon != null) {
137-
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
138-
icon()
180+
) {
181+
Box(
182+
contentAlignment = Alignment.Center,
183+
modifier = Modifier
184+
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
185+
.padding(contentPadding)
186+
) {
187+
if (isLoading) {
188+
CircularProgressIndicator(
189+
color = Colors.White32,
190+
strokeWidth = 2.dp,
191+
modifier = Modifier.size(size.height / 2)
192+
)
193+
} else {
194+
CompositionLocalProvider(
195+
LocalContentColor provides if (enabled) Colors.White80 else Colors.White32
196+
) {
197+
Row(
198+
verticalAlignment = Alignment.CenterVertically,
199+
horizontalArrangement = Arrangement.spacedBy(8.dp),
200+
) {
201+
if (icon != null) {
202+
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
203+
icon()
204+
}
205+
}
206+
text?.let {
207+
Text(
208+
text = text,
209+
maxLines = 1,
210+
overflow = TextOverflow.Ellipsis,
211+
)
212+
}
139213
}
140214
}
141-
text?.let {
142-
Text(
143-
text = text,
144-
maxLines = 1,
145-
overflow = TextOverflow.Ellipsis,
146-
)
147-
}
148215
}
149216
}
150217
}
@@ -161,35 +228,67 @@ fun TertiaryButton(
161228
enabled: Boolean = true,
162229
fullWidth: Boolean = true,
163230
) {
231+
val interactionSource = remember { MutableInteractionSource() }
232+
val isPressed by interactionSource.collectIsPressedAsState()
233+
234+
val textColor by animateColorAsState(
235+
targetValue = when {
236+
!enabled -> Colors.White32
237+
isPressed -> Colors.White
238+
else -> Colors.White80
239+
},
240+
label = "tertiaryButtonText"
241+
)
242+
164243
val contentPadding = PaddingValues(horizontal = size.horizontalPadding.takeIf { text != null } ?: 0.dp)
165-
TextButton(
166-
onClick = onClick,
167-
enabled = enabled && !isLoading,
168-
colors = AppButtonDefaults.tertiaryColors,
169-
contentPadding = contentPadding,
244+
val shape = MaterialTheme.shapes.extraLarge
245+
246+
Surface(
247+
shape = shape,
248+
color = Color.Transparent,
170249
modifier = Modifier
171250
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
172251
.requiredHeight(size.height)
173252
.then(modifier)
174-
) {
175-
if (isLoading) {
176-
CircularProgressIndicator(
177-
color = Colors.White32,
178-
strokeWidth = 2.dp,
179-
modifier = Modifier.size(size.height / 2)
253+
.clickable(
254+
onClick = onClick,
255+
enabled = enabled && !isLoading,
256+
interactionSource = interactionSource,
257+
indication = null
180258
)
181-
} else {
182-
if (icon != null) {
183-
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
184-
icon()
185-
}
186-
}
187-
text?.let {
188-
Text(
189-
text = text,
190-
maxLines = 1,
191-
overflow = TextOverflow.Ellipsis,
259+
) {
260+
Box(
261+
contentAlignment = Alignment.Center,
262+
modifier = Modifier
263+
.then(if (fullWidth) Modifier.fillMaxWidth() else Modifier)
264+
.padding(contentPadding)
265+
) {
266+
if (isLoading) {
267+
CircularProgressIndicator(
268+
color = Colors.White32,
269+
strokeWidth = 2.dp,
270+
modifier = Modifier.size(size.height / 2)
192271
)
272+
} else {
273+
CompositionLocalProvider(LocalContentColor provides textColor) {
274+
Row(
275+
verticalAlignment = Alignment.CenterVertically,
276+
horizontalArrangement = Arrangement.spacedBy(8.dp),
277+
) {
278+
if (icon != null) {
279+
Box(modifier = if (enabled) Modifier else Modifier.alpha(0.5f)) {
280+
icon()
281+
}
282+
}
283+
text?.let {
284+
Text(
285+
text = text,
286+
maxLines = 1,
287+
overflow = TextOverflow.Ellipsis,
288+
)
289+
}
290+
}
291+
}
193292
}
194293
}
195294
}
@@ -241,11 +340,10 @@ private fun PrimaryButtonPreview() {
241340
onClick = {},
242341
)
243342
PrimaryButton(
244-
text = "Primary Small Color Not Full",
343+
text = "Primary Small Not Full",
245344
size = ButtonSize.Small,
246345
onClick = {},
247346
fullWidth = false,
248-
color = Colors.Brand,
249347
)
250348
PrimaryButton(
251349
text = "Primary Small Loading",

app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ private fun ReceiveQrSlide(
265265
size = ButtonSize.Small,
266266
onClick = onClickEditInvoice,
267267
fullWidth = false,
268-
color = Colors.White10,
269268
icon = {
270269
Icon(
271270
painter = painterResource(R.drawable.ic_pencil_simple),
@@ -288,7 +287,6 @@ private fun ReceiveQrSlide(
288287
coroutineScope.launch { qrButtonTooltipState.show() }
289288
},
290289
fullWidth = false,
291-
color = Colors.White10,
292290
icon = {
293291
Icon(
294292
painter = painterResource(R.drawable.ic_copy),
@@ -309,7 +307,6 @@ private fun ReceiveQrSlide(
309307
} ?: shareText(context, uri)
310308
},
311309
fullWidth = false,
312-
color = Colors.White10,
313310
icon = {
314311
Icon(
315312
painter = painterResource(R.drawable.ic_share),
@@ -412,7 +409,6 @@ private fun CopyAddressCard(
412409
coroutineScope.launch { tooltipState.show() }
413410
},
414411
fullWidth = false,
415-
color = Colors.White10,
416412
icon = {
417413
Icon(
418414
painter = painterResource(R.drawable.ic_copy),
@@ -428,7 +424,6 @@ private fun CopyAddressCard(
428424
size = ButtonSize.Small,
429425
onClick = { shareText(context, address) },
430426
fullWidth = false,
431-
color = Colors.White10,
432427
icon = {
433428
Icon(
434429
painter = painterResource(R.drawable.ic_share),

app/src/main/java/to/bitkit/ui/settings/advanced/AddressViewerScreen.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,11 @@ private fun AddressViewerContent(
165165
text = stringResource(R.string.settings__addr__addr_change),
166166
size = ButtonSize.Small,
167167
onClick = { onSwitchAddressType(false) },
168-
color = if (uiState.showReceiveAddresses) Colors.White16 else Colors.Brand,
169168
modifier = Modifier.weight(1f)
170169
)
171170
PrimaryButton(
172171
text = stringResource(R.string.settings__addr__addr_receiving),
173172
size = ButtonSize.Small,
174-
color = if (uiState.showReceiveAddresses) Colors.Brand else Colors.White16,
175173
onClick = { onSwitchAddressType(true) },
176174
modifier = Modifier.weight(1f)
177175
)

0 commit comments

Comments
 (0)