Updated on 2026-08-14

This commit is contained in:
Tangem 2022-11-11 21:25:42 +04:00
parent 9cff1bbb89
commit 48ce9b4fd2
15 changed files with 1429 additions and 149 deletions

View file

@ -30,6 +30,8 @@ android {
}
dependencies {
/** AndroidX libraries */
implementation(AndroidX.fragmentKtx)
/** Compose */
implementation(Compose.foundation)
@ -38,4 +40,5 @@ dependencies {
/** Other libraries */
implementation(Library.accompanistSystemUiController)
implementation(Library.materialComponent)
}

View file

@ -1,183 +1,582 @@
package com.tangem.core.ui.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.Button
import androidx.compose.material.ButtonColors
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ButtonElevation
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.State
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
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.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import com.tangem.core.ui.R
import com.tangem.core.ui.res.ButtonColorType
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TextColorType
import com.tangem.core.ui.res.buttonColor
import com.tangem.core.ui.res.textColor
import com.tangem.core.ui.res.TangemTypography
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=97%3A103&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun Preview_PrimaryStartIconButton_Enabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryStartIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Enabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryStartIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Disabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryStartIconButton(
text = "Manage tokens",
iconResId = R.drawable.ic_tangem,
enabled = false,
onClicked = {},
)
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Disabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryStartIconButton(
text = "Manage tokens",
iconResId = R.drawable.ic_tangem,
enabled = false,
onClicked = {},
)
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Enabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Enabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Disabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = false, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Disabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = false, onClicked = {})
}
fun TextButton(
modifier: Modifier = Modifier,
text: String,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
onClick = onClick,
enabled = enabled,
showProgress = false,
colors = TangemButtonsDefaults.textButtonColors,
size = TangemButtonSize.Text,
)
}
/**
* Primary button with an icon at the beginning of the layout
*
* @param modifier button modifier
* @param text button text
* @param iconResId button icon res id
* @param enabled controls the enabled state of the button
* @param onClicked the lambda to be invoked when this button is pressed
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=233%3A258&t=WdN5XpixzZLlQAZO-4"
* >Figma component</a>
*/
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=97%3A62&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun PrimaryStartIconButton(
fun TextButtonIconLeft(
modifier: Modifier = Modifier,
text: String,
@DrawableRes iconResId: Int,
icon: Painter,
enabled: Boolean = true,
onClicked: () -> Unit,
onClick: () -> Unit,
) {
PrimaryButtonRow(modifier = modifier, enabled = enabled, onClicked = onClicked) {
Icon(
painter = painterResource(id = iconResId),
contentDescription = null,
)
Spacer(modifier = Modifier.width(dimensionResource(R.dimen.spacing8)))
Text(text = text)
}
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Left(icon),
onClick = onClick,
enabled = enabled,
showProgress = false,
colors = TangemButtonsDefaults.textButtonColors,
size = TangemButtonSize.Text,
)
}
@Composable
fun PrimaryButton(
modifier: Modifier = Modifier,
text: String,
showProgress: Boolean = false,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
/**
* Primary button with an icon at the end of the layout
*
* @param modifier button modifier
* @param text button text
* @param iconResId button icon res id
* @param enabled controls the enabled state of the button
* @param onClicked the lambda to be invoked when this button is pressed
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=68%3A47&t=WdN5XpixzZLlQAZO-4"
* >Figma component</a>
*/
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=68%3A47&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun PrimaryEndIconButton(
fun PrimaryButtonIconRight(
modifier: Modifier = Modifier,
text: String,
@DrawableRes iconResId: Int,
icon: Painter,
showProgress: Boolean = false,
enabled: Boolean = true,
onClicked: () -> Unit,
onClick: () -> Unit,
) {
PrimaryButtonRow(modifier = modifier, enabled = enabled, onClicked = onClicked) {
Text(text = text)
Spacer(modifier = Modifier.width(dimensionResource(R.dimen.spacing8)))
Icon(
painter = painterResource(id = iconResId),
contentDescription = null,
)
}
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Right(icon),
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=233%3A258&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun PrimaryButtonIconLeft(
modifier: Modifier = Modifier,
text: String,
icon: Painter,
showProgress: Boolean = false,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Left(icon),
onClick = onClick,
colors = TangemButtonsDefaults.primaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
@Composable
private fun PrimaryButtonRow(
modifier: Modifier,
fun SecondaryButton(
modifier: Modifier = Modifier,
text: String,
showProgress: Boolean = false,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.None,
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=99%3A50&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun SecondaryButtonIconRight(
modifier: Modifier = Modifier,
text: String,
icon: Painter,
showProgress: Boolean = false,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Right(icon),
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=233%3A262&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun SecondaryButtonIconLeft(
modifier: Modifier = Modifier,
text: String,
icon: Painter,
showProgress: Boolean = false,
enabled: Boolean = true,
onClick: () -> Unit,
) {
TangemButton(
modifier = modifier,
text = text,
icon = TangemButtonIcon.Left(icon),
onClick = onClick,
colors = TangemButtonsDefaults.secondaryButtonColors,
enabled = enabled,
showProgress = showProgress,
)
}
// region Defaults
@Composable
private fun TangemButton(
modifier: Modifier = Modifier,
text: String,
icon: TangemButtonIcon,
onClick: () -> Unit,
colors: ButtonColors,
showProgress: Boolean,
enabled: Boolean,
onClicked: () -> Unit,
content: @Composable (RowScope.() -> Unit),
size: TangemButtonSize = TangemButtonSize.Default,
elevation: ButtonElevation = TangemButtonsDefaults.elevation,
) {
Button(
onClick = onClicked,
modifier = modifier
.fillMaxWidth()
.height(dimensionResource(R.dimen.size48)),
.width(IntrinsicSize.Min)
.height(IntrinsicSize.Min)
.heightIn(size.toHeightDp()),
onClick = {
if (!showProgress) {
onClick()
}
},
enabled = enabled,
shape = RoundedCornerShape(dimensionResource(id = R.dimen.radius12)),
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.buttonColor(type = ButtonColorType.PRIMARY),
contentColor = MaterialTheme.colors.textColor(type = TextColorType.PRIMARY2),
disabledBackgroundColor = MaterialTheme.colors.buttonColor(type = ButtonColorType.DISABLED),
disabledContentColor = MaterialTheme.colors.textColor(type = TextColorType.DISABLED),
),
content = content,
)
}
elevation = elevation,
shape = size.toShape(),
colors = colors,
) {
ButtonContent(
text = text,
buttonIcon = icon,
colors = colors,
showProgress = showProgress,
enabled = enabled,
)
}
}
@Composable
private fun ButtonContent(
text: String,
buttonIcon: TangemButtonIcon,
colors: ButtonColors,
enabled: Boolean,
showProgress: Boolean,
) {
val icon = @Composable { painter: Painter ->
Icon(
modifier = Modifier.size(TangemTheme.dimens.size20),
painter = painter,
tint = colors.contentColor(enabled = enabled).value,
contentDescription = null,
)
}
if (showProgress) Box(
modifier = Modifier.wrapContentSize(),
) {
CircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center)
.size(TangemTheme.dimens.size24),
color = colors.contentColor(enabled = enabled).value,
strokeWidth = TangemTheme.dimens.size4,
)
} else Row {
if (buttonIcon is TangemButtonIcon.Left) {
icon(buttonIcon.painter)
Spacer(modifier = Modifier.width(TangemTheme.dimens.size8))
}
Text(
text = text,
style = TangemTypography.button,
color = colors.contentColor(enabled = enabled).value,
)
if (buttonIcon is TangemButtonIcon.Right) {
Spacer(modifier = Modifier.width(TangemTheme.dimens.size8))
icon(buttonIcon.painter)
}
}
}
sealed interface TangemButtonIcon {
val painter: Painter?
@Immutable
data class Left(override val painter: Painter) : TangemButtonIcon
@Immutable
data class Right(override val painter: Painter) : TangemButtonIcon
object None : TangemButtonIcon {
override val painter: Painter? = null
}
}
enum class TangemButtonSize {
Default,
Text,
}
@Composable
private fun TangemButtonSize.toHeightDp(): Dp = when (this) {
TangemButtonSize.Default -> TangemTheme.dimens.size48
TangemButtonSize.Text -> TangemTheme.dimens.size40
}
@Composable
private fun TangemButtonSize.toShape(): Shape = when (this) {
TangemButtonSize.Default -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.Text -> TangemTheme.shapes.roundedCornersSmall
}
private object TangemButtonsDefaults {
val elevation: ButtonElevation
@Composable get() = ButtonDefaults
.elevation(
defaultElevation = TangemTheme.dimens.elevation0,
pressedElevation = TangemTheme.dimens.elevation0,
)
val primaryButtonColors: ButtonColors
@Composable get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.primary,
contentColor = TangemTheme.colors.text.primary2,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val secondaryButtonColors: ButtonColors
@Composable get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.button.secondary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val textButtonColors: ButtonColors
@Composable get() = TangemButtonColors(
backgroundColor = Color.Transparent,
contentColor = TangemTheme.colors.text.secondary,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
}
@Immutable
private class TangemButtonColors(
private val backgroundColor: Color,
private val contentColor: Color,
private val disabledBackgroundColor: Color,
private val disabledContentColor: Color,
) : ButtonColors {
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(newValue = if (enabled) contentColor else disabledContentColor)
}
}
// endregion Defaults
// region Preview
@Composable
private fun PrimaryButtonSample(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary),
) {
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
showProgress = true,
text = "Manage tokens",
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconRight(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconLeft(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
enabled = false,
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconRight(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
enabled = false,
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
PrimaryButtonIconLeft(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
enabled = false,
onClick = { /* no-op */ },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun PrimaryButtonPreview_Light() {
TangemTheme {
PrimaryButtonSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun PrimaryButtonPreview_Dark() {
TangemTheme(isDark = true) {
PrimaryButtonSample()
}
}
@Composable
private fun SecondaryButtonSample(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary),
) {
SecondaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButton(
modifier = Modifier.fillMaxWidth(),
showProgress = true,
text = "Manage tokens",
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconRight(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconLeft(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButton(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
enabled = false,
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconRight(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
enabled = false,
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
SecondaryButtonIconLeft(
modifier = Modifier.fillMaxWidth(),
text = "Manage tokens",
icon = painterResource(id = R.drawable.ic_tangem),
enabled = false,
onClick = { /* no-op */ },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SecondaryButtonPreview_Light() {
TangemTheme {
SecondaryButtonSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SecondaryButtonPreview_Dark() {
TangemTheme(isDark = true) {
SecondaryButtonSample()
}
}
@Composable
private fun TextButtonSample(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary),
) {
TextButton(
text = "Enabled",
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
TextButtonIconLeft(
text = "Enabled",
icon = painterResource(id = R.drawable.ic_plus),
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
TextButton(
text = "Enabled",
enabled = false,
onClick = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8))
TextButtonIconLeft(
text = "Enabled",
icon = painterResource(id = R.drawable.ic_plus),
enabled = false,
onClick = { /* no-op */ },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun TextButtonPreview_Light() {
TangemTheme {
TextButtonSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun TextButtonPreview_Dark() {
TangemTheme(isDark = true) {
TextButtonSample()
}
}
// endregion Preview

View file

@ -0,0 +1,185 @@
package com.tangem.core.ui.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.res.ButtonColorType
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TextColorType
import com.tangem.core.ui.res.buttonColor
import com.tangem.core.ui.res.textColor
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Enabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryStartIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Enabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryStartIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Disabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryStartIconButton(
text = "Manage tokens",
iconResId = R.drawable.ic_tangem,
enabled = false,
onClicked = {},
)
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryStartIconButton_Disabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryStartIconButton(
text = "Manage tokens",
iconResId = R.drawable.ic_tangem,
enabled = false,
onClicked = {},
)
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Enabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Enabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = true, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Disabled_InLightTheme() {
TangemTheme(isDark = false) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = false, onClicked = {})
}
}
@Preview(widthDp = 328, heightDp = 48, showBackground = true)
@Composable
fun Preview_PrimaryEndIconButton_Disabled_InDarkTheme() {
TangemTheme(isDark = true) {
PrimaryEndIconButton(text = "Manage tokens", iconResId = R.drawable.ic_tangem, enabled = false, onClicked = {})
}
}
/**
* Primary button with an icon at the beginning of the layout
*
* @param modifier button modifier
* @param text button text
* @param iconResId button icon res id
* @param enabled controls the enabled state of the button
* @param onClicked the lambda to be invoked when this button is pressed
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=233%3A258&t=WdN5XpixzZLlQAZO-4"
* >Figma component</a>
*/
@Deprecated("Use PrimaryButtonIconRight instead")
@Composable
fun PrimaryStartIconButton(
modifier: Modifier = Modifier,
text: String,
@DrawableRes iconResId: Int,
enabled: Boolean = true,
onClicked: () -> Unit,
) {
PrimaryButtonRow(modifier = modifier, enabled = enabled, onClicked = onClicked) {
Icon(
painter = painterResource(id = iconResId),
contentDescription = null,
)
Spacer(modifier = Modifier.width(dimensionResource(R.dimen.spacing8)))
Text(text = text)
}
}
/**
* Primary button with an icon at the end of the layout
*
* @param modifier button modifier
* @param text button text
* @param iconResId button icon res id
* @param enabled controls the enabled state of the button
* @param onClicked the lambda to be invoked when this button is pressed
*
* @see <a href = "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=68%3A47&t=WdN5XpixzZLlQAZO-4"
* >Figma component</a>
*/
@Deprecated("Use PrimaryButtonIconLeft instead")
@Composable
fun PrimaryEndIconButton(
modifier: Modifier = Modifier,
text: String,
@DrawableRes iconResId: Int,
enabled: Boolean = true,
onClicked: () -> Unit,
) {
PrimaryButtonRow(modifier = modifier, enabled = enabled, onClicked = onClicked) {
Text(text = text)
Spacer(modifier = Modifier.width(dimensionResource(R.dimen.spacing8)))
Icon(
painter = painterResource(id = iconResId),
contentDescription = null,
)
}
}
@Composable
private fun PrimaryButtonRow(
modifier: Modifier,
enabled: Boolean,
onClicked: () -> Unit,
content: @Composable (RowScope.() -> Unit),
) {
Button(
onClick = onClicked,
modifier = modifier
.fillMaxWidth()
.height(dimensionResource(R.dimen.size48)),
enabled = enabled,
shape = RoundedCornerShape(dimensionResource(id = R.dimen.radius12)),
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.buttonColor(type = ButtonColorType.PRIMARY),
contentColor = MaterialTheme.colors.textColor(type = TextColorType.PRIMARY2),
disabledBackgroundColor = MaterialTheme.colors.buttonColor(type = ButtonColorType.DISABLED),
disabledContentColor = MaterialTheme.colors.textColor(type = TextColorType.DISABLED),
),
content = content,
)
}

View file

@ -0,0 +1,14 @@
package com.tangem.core.ui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@Composable
fun SystemBarsEffect(
block: SystemUiController.() -> Unit,
) {
val systemUiController = rememberSystemUiController()
SideEffect { block(systemUiController) }
}

View file

@ -0,0 +1,414 @@
package com.tangem.core.ui.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextFieldColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
/**
* [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=213%3A218&t=TmfD6UBHPg9uYfev-4)
* */
@Composable
fun OutlineTextField(
modifier: Modifier = Modifier,
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
label: String? = null,
placeholder: String? = null,
caption: String? = null,
enabled: Boolean = true,
isError: Boolean = false,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) {
TangemTextField(
modifier = modifier,
value = value,
onValueChange = onValueChange,
singleLine = true,
label = label,
placeholder = placeholder,
caption = caption,
enabled = enabled,
isError = isError,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
interactionSource = interactionSource,
)
}
// region Defaults
@Composable
private fun TangemTextField(
modifier: Modifier = Modifier,
value: TextFieldValue,
singleLine: Boolean,
onValueChange: (TextFieldValue) -> Unit,
label: String? = null,
placeholder: String? = null,
caption: String? = null,
enabled: Boolean = true,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: TangemTextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
size: TangemTextFieldSize = TangemTextFieldSize.Default,
onClear: () -> Unit = { onValueChange(TextFieldValue()) },
) {
Column(modifier = modifier) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.heightIn(size.toHeightDp()),
value = value,
textStyle = TangemTypography.body1,
onValueChange = onValueChange,
singleLine = singleLine,
enabled = enabled,
isError = isError,
visualTransformation = visualTransformation,
keyboardActions = keyboardActions,
keyboardOptions = keyboardOptions,
interactionSource = interactionSource,
shape = size.toShape(),
colors = colors,
label = {
if (!label.isNullOrEmpty()) {
Text(
text = label,
style = TangemTypography.caption,
color = colors.labelColor(
enabled = enabled,
error = isError,
interactionSource = interactionSource,
).value,
)
}
},
placeholder = {
if (!placeholder.isNullOrEmpty()) {
Text(
text = placeholder,
style = TangemTypography.body1,
color = colors.placeholderColor(enabled = enabled).value,
)
}
},
trailingIcon = {
val iconRes by rememberUpdatedState(
newValue = if (isError) R.drawable.ic_alert else R.drawable.ic_close,
)
IconButton(
modifier = Modifier.size(32.dp),
onClick = onClear,
enabled = !isError && enabled,
) {
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = iconRes),
tint = colors.trailingIconColor(enabled = enabled, isError = isError).value,
contentDescription = "Clear input",
)
}
},
)
AnimatedVisibility(
visible = !caption.isNullOrEmpty(),
enter = fadeIn(),
exit = fadeOut(),
) {
if (caption.isNullOrEmpty()) return@AnimatedVisibility
Column {
Spacer(modifier = Modifier.height(4.dp))
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
text = caption,
style = TangemTypography.body1,
color = colors.captionColor(enabled = enabled, isError = isError).value,
)
}
}
}
}
private enum class TangemTextFieldSize {
Default
}
@Composable
private fun TangemTextFieldSize.toHeightDp(): Dp = when (this) {
TangemTextFieldSize.Default -> TangemTheme.dimens.size56
}
@Composable
private fun TangemTextFieldSize.toShape(): Shape = when (this) {
TangemTextFieldSize.Default -> TangemTheme.shapes.roundedCornersSmall2
}
private object TangemTextFieldsDefault {
val defaultTextFieldColors: TangemTextFieldColors
@Composable @Stable get() = TangemTextFieldColors(
textColor = TangemTheme.colors.text.primary1,
disabledTextColor = TangemTheme.colors.text.disabled,
backgroundColor = Color.Transparent,
cursorColor = TangemTheme.colors.icon.primary1,
errorCursorColor = TangemTheme.colors.icon.warning,
focusedIndicatorColor = TangemTheme.colors.icon.primary1,
unfocusedIndicatorColor = TangemTheme.colors.stroke.primary,
disabledIndicatorColor = TangemTheme.colors.stroke.primary,
errorIndicatorColor = TangemTheme.colors.icon.warning,
leadingIconColor = TangemTheme.colors.icon.informative,
disabledLeadingIconColor = Color.Transparent,
errorLeadingIconColor = TangemTheme.colors.icon.warning,
trailingIconColor = TangemTheme.colors.icon.informative,
disabledTrailingIconColor = Color.Transparent,
errorTrailingIconColor = TangemTheme.colors.icon.warning,
focusedLabelColor = TangemTheme.colors.text.primary1,
unfocusedLabelColor = TangemTheme.colors.text.secondary,
disabledLabelColor = TangemTheme.colors.text.disabled,
errorLabelColor = TangemTheme.colors.icon.warning,
placeholderColor = TangemTheme.colors.text.secondary,
disabledPlaceholderColor = TangemTheme.colors.text.disabled,
captionColor = TangemTheme.colors.text.tertiary,
disabledCaptionColor = TangemTheme.colors.text.disabled,
errorCaptionColor = TangemTheme.colors.icon.warning,
)
}
@Immutable
private data class TangemTextFieldColors(
private val textColor: Color,
private val disabledTextColor: Color,
private val cursorColor: Color,
private val errorCursorColor: Color,
private val focusedIndicatorColor: Color,
private val unfocusedIndicatorColor: Color,
private val errorIndicatorColor: Color,
private val disabledIndicatorColor: Color,
private val leadingIconColor: Color,
private val disabledLeadingIconColor: Color,
private val errorLeadingIconColor: Color,
private val trailingIconColor: Color,
private val disabledTrailingIconColor: Color,
private val errorTrailingIconColor: Color,
private val backgroundColor: Color,
private val focusedLabelColor: Color,
private val unfocusedLabelColor: Color,
private val disabledLabelColor: Color,
private val errorLabelColor: Color,
private val placeholderColor: Color,
private val disabledPlaceholderColor: Color,
private val captionColor: Color,
private val disabledCaptionColor: Color,
private val errorCaptionColor: Color,
) : TextFieldColors {
@Composable
override fun leadingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledLeadingIconColor
isError -> errorLeadingIconColor
else -> leadingIconColor
},
)
}
@Composable
override fun trailingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledTrailingIconColor
isError -> errorTrailingIconColor
else -> trailingIconColor
},
)
}
@Composable
override fun indicatorColor(
enabled: Boolean,
isError: Boolean,
interactionSource: InteractionSource,
): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledIndicatorColor
isError -> errorIndicatorColor
focused -> focusedIndicatorColor
else -> unfocusedIndicatorColor
}
return if (enabled) {
animateColorAsState(targetValue, tween(durationMillis = 120))
} else {
rememberUpdatedState(targetValue)
}
}
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(backgroundColor)
}
@Composable
override fun placeholderColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) placeholderColor else disabledPlaceholderColor)
}
@Composable
override fun labelColor(
enabled: Boolean,
error: Boolean,
interactionSource: InteractionSource,
): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledLabelColor
error -> errorLabelColor
focused -> focusedLabelColor
else -> unfocusedLabelColor
}
return rememberUpdatedState(targetValue)
}
@Composable
override fun textColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) textColor else disabledTextColor)
}
@Composable
override fun cursorColor(isError: Boolean): State<Color> {
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
}
@Composable
fun captionColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
newValue = when {
!enabled -> disabledCaptionColor
isError -> errorCaptionColor
else -> captionColor
},
)
}
}
// endregion Defaults
// region Preview
@Composable
private fun OutlineTextFieldSample(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary)
.padding(horizontal = 16.dp),
) {
val text = TextFieldValue(text = "Input")
OutlineTextField(
value = text,
onValueChange = { /* no-op */ },
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
OutlineTextField(
value = text,
onValueChange = { /* no-op */ },
label = "Default",
placeholder = "Placeholder",
caption = "Supporting text",
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
OutlineTextField(
value = text,
onValueChange = { /* no-op */ },
enabled = false,
label = "Disabled",
placeholder = "Placeholder",
caption = "Supporting text",
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
OutlineTextField(
value = text,
onValueChange = { /* no-op */ },
isError = true,
label = "Error",
placeholder = "Placeholder",
caption = "Supporting text",
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
OutlineTextField(
value = TextFieldValue(),
onValueChange = { /* no-op */ },
label = "Default without value",
placeholder = "Placeholder",
caption = "Supporting text",
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun OutlineTextFieldPreview_Light() {
TangemTheme {
OutlineTextFieldSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun OutlineTextFieldPreview_Dark() {
TangemTheme(isDark = true) {
OutlineTextFieldSample()
}
}
// endregion Preview

View file

@ -23,6 +23,7 @@ import com.tangem.core.ui.res.iconColor
* @see <a href="https://www.figma.com/file/17JyRbuUEZ42DluaFEuGQk/Atoms?node-id=135%3A25&t=3dvxYMZBox4jxJc1-4">
* Figma Component</a>
*/
@Deprecated(message = "Use Hand component instead")
@Composable
fun BottomSheetIndicator() {
Box(

View file

@ -0,0 +1,72 @@
package com.tangem.core.ui.components.atoms
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.res.TangemTheme
/**
* [Show in Figma](https://www.figma.com/file/17JyRbuUEZ42DluaFEuGQk/Atoms?node-id=135%3A25&t=Jo68S6ilyewVU8MV-4)
* */
@Composable
fun Hand(
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier
.padding(vertical = TangemTheme.dimens.spacing8)
.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
Box(
modifier = Modifier
.width(TangemTheme.dimens.size32)
.height(TangemTheme.dimens.size4)
.background(
color = TangemTheme.colors.icon.inactive,
shape = TangemTheme.shapes.roundedCornersSmall,
),
)
}
}
// region Preview
@Composable
private fun HandSample(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary)
.padding(TangemTheme.dimens.spacing12),
verticalArrangement = Arrangement.SpaceBetween,
) {
Hand()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun HandPreview_Light() {
TangemTheme {
HandSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun HandPreview_Dark() {
TangemTheme(isDark = true) {
HandSample()
}
}
// endregion Preview

View file

@ -0,0 +1,87 @@
package com.tangem.core.ui.fragments
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.FloatRange
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
abstract class ComposeBottomSheetFragment<ScreenState> : BottomSheetDialogFragment() {
open val initialBottomSheetState = BottomSheetBehavior.STATE_EXPANDED
@FloatRange(from = 0.0, to = 1.0)
open val expandedHeightFraction: Float? = null
override fun getTheme(): Int = R.style.AppTheme_TransparentBottomSheetDialog
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
return createComposeView(inflater.context)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
(dialog as BottomSheetDialog).behavior.apply {
state = initialBottomSheetState
skipCollapsed = true
}
return dialog
}
private fun createComposeView(context: Context): View {
return ComposeView(context).apply {
setContent {
TangemTheme {
val backgroundColor = TangemTheme.colors.background.plain
SystemBarsEffect {
setSystemBarsColor(
color = backgroundColor,
)
}
ScreenContent(
modifier = Modifier
.fillMaxWidth()
.let {
if (expandedHeightFraction != null) it.fillMaxHeight(expandedHeightFraction!!) else it
}
.background(
color = backgroundColor,
shape = TangemTheme.shapes.bottomSheet,
),
state = provideState().value,
)
}
}
}
}
@Composable
protected abstract fun provideState(): State<ScreenState>
@Composable
protected abstract fun ScreenContent(
modifier: Modifier,
state: ScreenState,
)
}

View file

@ -0,0 +1,57 @@
package com.tangem.core.ui.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
abstract class ComposeFragment<ScreenState> : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
return createComposeView(inflater.context)
}
private fun createComposeView(context: Context): View {
return ComposeView(context).apply {
setContent {
TangemTheme {
val backgroundColor = TangemTheme.colors.background.primary
SystemBarsEffect {
setSystemBarsColor(
color = backgroundColor,
)
}
ScreenContent(
modifier = Modifier
.fillMaxSize()
.background(color = backgroundColor),
state = provideState().value,
)
}
}
}
}
@Composable
protected abstract fun provideState(): State<ScreenState>
@Composable
protected abstract fun ScreenContent(
modifier: Modifier,
state: ScreenState,
)
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M11,15H13V17H11V15ZM11,7H13V13H11V7ZM12,2C6.47,2 2,6.5 2,12C2,14.652 3.054,17.196 4.929,19.071C5.858,20 6.96,20.736 8.173,21.239C9.386,21.741 10.687,22 12,22C14.652,22 17.196,20.946 19.071,19.071C20.946,17.196 22,14.652 22,12C22,10.687 21.741,9.386 21.239,8.173C20.736,6.96 20,5.858 19.071,4.929C18.142,4 17.04,3.264 15.827,2.761C14.614,2.259 13.313,2 12,2ZM12,20C9.878,20 7.843,19.157 6.343,17.657C4.843,16.157 4,14.122 4,12C4,9.878 4.843,7.843 6.343,6.343C7.843,4.843 9.878,4 12,4C14.122,4 16.157,4.843 17.657,6.343C19.157,7.843 20,9.878 20,12C20,14.122 19.157,16.157 17.657,17.657C16.157,19.157 14.122,20 12,20Z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
</vector>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.TransparentBottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">@style/TransparentBottomSheetDialog</item>
<item name="backgroundTint">@android:color/transparent</item>
</style>
<style name="TransparentBottomSheetDialog" parent="Widget.MaterialComponents.BottomSheet">
<item name="backgroundTint">@android:color/transparent</item>
</style>
</resources>