Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-11 18:30:01 +05:00
commit 3c6fbf0b26
14 changed files with 602 additions and 79 deletions

View file

@ -2,6 +2,7 @@ package com.tangem.core.ui.components.audits
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -11,6 +12,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@ -30,41 +32,59 @@ import com.tangem.core.ui.res.TangemThemePreview
fun AuditLabel(state: AuditLabelUM, modifier: Modifier = Modifier) {
AuditLabelInternal(
textReference = state.text,
textColor = getColorByType(state.type),
backgroundColor = getColorByType(state.type).copy(alpha = 0.1f),
type = state.type,
modifier = modifier,
)
}
@Composable
private fun AuditLabelInternal(
textReference: TextReference,
textColor: Color,
backgroundColor: Color,
modifier: Modifier = Modifier,
) {
private fun AuditLabelInternal(textReference: TextReference, type: AuditLabelUM.Type, modifier: Modifier = Modifier) {
Box(
modifier = modifier.background(
color = backgroundColor,
color = getBackgroundColorByType(type),
shape = TangemTheme.shapes.roundedCornersSmall2,
),
) {
Text(
text = textReference.resolveReference(),
style = TangemTheme.typography.caption1,
color = textColor,
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing4),
color = getTextColorByType(type),
modifier = Modifier.padding(getPaddingByType(type)),
)
}
}
@ReadOnlyComposable
@Composable
private fun getColorByType(type: AuditLabelUM.Type): Color {
private fun getTextColorByType(type: AuditLabelUM.Type): Color {
return when (type) {
AuditLabelUM.Type.Prohibition -> TangemTheme.colors.text.warning
AuditLabelUM.Type.Warning -> TangemTheme.colors.text.attention
AuditLabelUM.Type.Permit -> TangemTheme.colors.text.accent
AuditLabelUM.Type.Info -> TangemTheme.colors.text.primary2
}
}
@ReadOnlyComposable
@Composable
private fun getBackgroundColorByType(type: AuditLabelUM.Type): Color {
return when (type) {
AuditLabelUM.Type.Prohibition -> TangemTheme.colors.text.warning.copy(alpha = 0.1f)
AuditLabelUM.Type.Warning -> TangemTheme.colors.text.attention.copy(alpha = 0.1f)
AuditLabelUM.Type.Permit -> TangemTheme.colors.text.accent.copy(alpha = 0.1f)
AuditLabelUM.Type.Info -> TangemTheme.colors.text.accent
}
}
@ReadOnlyComposable
@Composable
private fun getPaddingByType(type: AuditLabelUM.Type): PaddingValues {
return when (type) {
AuditLabelUM.Type.Prohibition,
AuditLabelUM.Type.Warning,
AuditLabelUM.Type.Permit,
-> PaddingValues(horizontal = 4.dp)
AuditLabelUM.Type.Info -> PaddingValues(horizontal = 6.dp, vertical = 1.dp)
}
}

View file

@ -22,5 +22,8 @@ data class AuditLabelUM(val text: TextReference, val type: Type) {
/** Blue. Like, "trusted" */
Permit,
/** Blue with white text. Like, "best rate" */
Info,
}
}

View file

@ -0,0 +1,74 @@
package com.tangem.core.ui.components.badge
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
/**
* Badge component
*
* @param iconRes icon drawable resource
* @param text text reference
* @param modifier composable modifier
*
* @see <a href="https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=3467-2362&t=SnNQ4qhxwj2mhhra-4">Figma</a>
*/
@Composable
fun Badge(@DrawableRes iconRes: Int, text: TextReference, modifier: Modifier = Modifier) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = modifier
.border(1.dp, TangemTheme.colors.stroke.primary, RoundedCornerShape(4.dp))
.padding(horizontal = 4.dp),
) {
Icon(
painter = rememberVectorPainter(
ImageVector.vectorResource(iconRes),
),
contentDescription = null,
tint = TangemTheme.colors.icon.informative,
modifier = Modifier.size(12.dp),
)
Text(
text = text.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Badge_Preview() {
TangemThemePreview {
Badge(
iconRes = R.drawable.ic_star_mini_24,
text = stringReference("4.9"),
)
}
}
// endregion

View file

@ -0,0 +1,15 @@
package com.tangem.core.ui.components.badge.entity
import androidx.annotation.DrawableRes
import com.tangem.core.ui.extensions.TextReference
/**
* Badge component UI model
*
* @param iconRes icon drawable resource
* @param text text reference
*/
data class BadgeUM(
val text: TextReference,
@DrawableRes val iconRes: Int,
)

View file

@ -16,6 +16,7 @@ enum class TangemButtonSize {
RoundedAction,
WideAction,
TwoLines,
Small,
}
@Composable
@ -28,6 +29,7 @@ internal fun TangemButtonSize.toHeightDp(): Dp = when (this) {
TangemButtonSize.RoundedAction,
-> TangemTheme.dimens.size36
TangemButtonSize.WideAction -> TangemTheme.dimens.size40
TangemButtonSize.Small -> 24.dp
}
@Composable
@ -40,6 +42,7 @@ internal fun TangemButtonSize.toShape(): Shape = when (this) {
TangemButtonSize.Action -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.TwoLines -> TangemTheme.shapes.roundedCornersXMedium
TangemButtonSize.RoundedAction -> TangemTheme.shapes.roundedCornersLarge
TangemButtonSize.Small -> TangemTheme.shapes.roundedCornersXMedium
}
@Composable
@ -48,6 +51,7 @@ internal fun TangemButtonSize.toIconPadding(): Dp = when (this) {
TangemButtonSize.Default,
TangemButtonSize.WideAction,
TangemButtonSize.TwoLines,
TangemButtonSize.Small,
-> TangemTheme.dimens.spacing4
TangemButtonSize.Text -> TangemTheme.dimens.spacing8
TangemButtonSize.Selector -> 0.dp
@ -100,11 +104,18 @@ internal fun TangemButtonSize.toContentPadding(icon: TangemButtonIconPosition):
start = horizontalPadding.first,
end = horizontalPadding.second,
)
TangemButtonSize.Small -> PaddingValues(
top = TangemTheme.dimens.spacing4,
bottom = TangemTheme.dimens.spacing4,
start = horizontalPadding.first,
end = horizontalPadding.second,
)
}
}
@Composable
@ReadOnlyComposable
@Suppress("CyclomaticComplexMethod")
internal fun TangemButtonSize.toHorizontalContentPadding(icon: TangemButtonIconPosition): Pair<Dp, Dp> {
return when (this) {
TangemButtonSize.Default,
@ -124,5 +135,10 @@ internal fun TangemButtonSize.toHorizontalContentPadding(icon: TangemButtonIconP
is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing16 to TangemTheme.dimens.spacing24
is TangemButtonIconPosition.End -> TangemTheme.dimens.spacing24 to TangemTheme.dimens.spacing16
}
TangemButtonSize.Small -> when (icon) {
is TangemButtonIconPosition.None -> TangemTheme.dimens.spacing12 to TangemTheme.dimens.spacing12
is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing8 to TangemTheme.dimens.spacing12
is TangemButtonIconPosition.End -> TangemTheme.dimens.spacing12 to TangemTheme.dimens.spacing8
}
}
}

View file

@ -0,0 +1,323 @@
package com.tangem.core.ui.components.provider
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import androidx.constraintlayout.compose.Visibility
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.R
import com.tangem.core.ui.components.audits.AuditLabel
import com.tangem.core.ui.components.audits.AuditLabelUM
import com.tangem.core.ui.components.badge.Badge
import com.tangem.core.ui.components.badge.entity.BadgeUM
import com.tangem.core.ui.components.provider.entity.ProviderChooseUM
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import kotlinx.collections.immutable.persistentListOf
/**
* Provider Row - Choose Crypto component
*
* @param providerChooseUM component ui model
* @param onClick click listener
* @param modifier composable modifier
*
* @see <a href="https://www.figma.com/design/JJuqr3gX9IC4WBv3C95uqj/Android--Copy-?node-id=3467-2643&t=Tg0OOJTQK9H4KBWL-4">Figma</a>
*/
@Composable
@Suppress("DestructuringDeclarationWithTooManyEntries")
fun ProviderChooseCrypto(providerChooseUM: ProviderChooseUM, onClick: () -> Unit, modifier: Modifier = Modifier) {
ConstraintLayout(
modifier = modifier
.background(TangemTheme.colors.background.action)
.clip(RoundedCornerShape(14.dp))
.selectedBorder(isSelected = providerChooseUM.isSelected)
.clickable(enabled = true, onClick = onClick)
.fillMaxWidth()
.padding(all = 12.dp),
) {
val (iconRef, titleRef, badgeRef, infoRef, labelRef) = createRefs()
val titleEndRef = createStartBarrier(infoRef, labelRef)
IconContent(
iconUrl = providerChooseUM.iconUrl,
modifier = Modifier
.constrainAs(iconRef) {
start.linkTo(parent.start)
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
},
)
TitleContent(
providerChooseUM = providerChooseUM,
modifier = Modifier.constrainAs(titleRef) {
start.linkTo(iconRef.end, 12.dp)
end.linkTo(titleEndRef, 4.dp)
top.linkTo(parent.top)
bottom.linkTo(badgeRef.top)
width = Dimension.fillToConstraints
},
)
BadgeContent(
providerChooseUM = providerChooseUM,
modifier = Modifier.constrainAs(badgeRef) {
start.linkTo(iconRef.end, 12.dp)
end.linkTo(labelRef.start, 4.dp)
top.linkTo(titleRef.bottom, 4.dp)
bottom.linkTo(parent.bottom)
width = Dimension.fillToConstraints
visibility = if (providerChooseUM.badgeList.isEmpty()) {
Visibility.Gone
} else {
Visibility.Visible
}
},
)
InfoContent(
text = providerChooseUM.infoText,
modifier = Modifier.constrainAs(infoRef) {
end.linkTo(parent.end)
top.linkTo(parent.top)
bottom.linkTo(labelRef.top, 4.dp)
},
)
LabelContent(
labelUM = providerChooseUM.labelUM,
modifier = Modifier.constrainAs(labelRef) {
end.linkTo(parent.end)
top.linkTo(infoRef.bottom)
bottom.linkTo(parent.bottom)
visibility = if (providerChooseUM.labelUM == null) {
Visibility.Gone
} else {
Visibility.Visible
}
},
)
}
}
@Composable
private fun IconContent(iconUrl: String, modifier: Modifier = Modifier) {
SubcomposeAsyncImage(
modifier = modifier
.size(40.dp)
.clip(RoundedCornerShape(8.dp))
.background(TangemColorPalette.Light1),
model = ImageRequest.Builder(context = LocalContext.current)
.data(iconUrl)
.crossfade(enable = true)
.allowHardware(false)
.build(),
contentDescription = null,
)
}
@Composable
private fun TitleContent(providerChooseUM: ProviderChooseUM, modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = modifier,
) {
Text(
text = providerChooseUM.title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
)
Text(
text = providerChooseUM.subtitle.resolveReference(),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
)
}
}
@Composable
private fun InfoContent(text: TextReference, modifier: Modifier = Modifier) {
Text(
text = text.resolveReference(),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
)
}
@Composable
private fun BadgeContent(providerChooseUM: ProviderChooseUM, modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = modifier,
) {
providerChooseUM.badgeList.fastForEach { badge ->
Badge(
iconRes = badge.iconRes,
text = badge.text,
)
}
}
}
@Composable
private fun LabelContent(labelUM: ProviderChooseUM.LabelUM?, modifier: Modifier = Modifier) {
Box(
modifier = modifier,
) {
when (labelUM) {
is ProviderChooseUM.LabelUM.Info -> AuditLabel(labelUM.auditLabelUM)
is ProviderChooseUM.LabelUM.Text -> Text(
text = labelUM.text.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.warning,
)
null -> Unit
}
}
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun ProviderChooseCrypto_Preview(
@PreviewParameter(ProviderChooseCryptoPreviewProvider::class) params: ProviderChooseUM,
) {
TangemThemePreview {
ProviderChooseCrypto(
providerChooseUM = params,
onClick = {},
)
}
}
private class ProviderChooseCryptoPreviewProvider : PreviewParameterProvider<ProviderChooseUM> {
override val values: Sequence<ProviderChooseUM>
get() = sequenceOf(
ProviderChooseUM(
title = stringReference("ChangeHero"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 800,00 POL"),
iconUrl = "",
badgeList = persistentListOf(
BadgeUM(
text = stringReference("4.9"),
iconRes = R.drawable.ic_star_outline_24,
),
BadgeUM(
text = stringReference("5 mins"),
iconRes = R.drawable.ic_speed_24,
),
BadgeUM(
text = stringReference("$3.45"),
iconRes = R.drawable.ic_gas_24,
),
),
isSelected = true,
labelUM = ProviderChooseUM.LabelUM.Info(
auditLabelUM = AuditLabelUM(
text = resourceReference(R.string.express_provider_best_rate),
type = AuditLabelUM.Type.Info,
),
),
),
ProviderChooseUM(
title = stringReference("Changelly"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 799,12 POL"),
iconUrl = "",
badgeList = persistentListOf(
BadgeUM(
text = stringReference("4.9"),
iconRes = R.drawable.ic_star_outline_24,
),
BadgeUM(
text = stringReference("5 mins"),
iconRes = R.drawable.ic_speed_24,
),
BadgeUM(
text = stringReference("$3.45"),
iconRes = R.drawable.ic_gas_24,
),
),
isSelected = false,
labelUM = ProviderChooseUM.LabelUM.Text(
text = stringReference("0.2%"),
),
),
ProviderChooseUM(
title = stringReference("Changelly"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 799,12 POL"),
iconUrl = "",
badgeList = persistentListOf(),
isSelected = false,
labelUM = ProviderChooseUM.LabelUM.Text(
text = stringReference("0.2%"),
),
),
ProviderChooseUM(
title = stringReference("Changelly"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 POL"),
iconUrl = "",
badgeList = persistentListOf(),
isSelected = false,
labelUM = ProviderChooseUM.LabelUM.Text(
text = stringReference("0.2%"),
),
),
ProviderChooseUM(
title = stringReference("Changelly"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 POL"),
iconUrl = "",
badgeList = persistentListOf(),
isSelected = false,
labelUM = null,
),
ProviderChooseUM(
title = stringReference("Changelly"),
subtitle = stringReference("CEX"),
infoText = stringReference("1 POL"),
iconUrl = "",
badgeList = persistentListOf(
BadgeUM(
text = stringReference("4.9"),
iconRes = R.drawable.ic_star_outline_24,
),
BadgeUM(
text = stringReference("5 mins"),
iconRes = R.drawable.ic_speed_24,
),
BadgeUM(
text = stringReference("$3.45"),
iconRes = R.drawable.ic_gas_24,
),
),
isSelected = false,
labelUM = null,
),
)
}
// endregion

View file

@ -0,0 +1,39 @@
package com.tangem.core.ui.components.provider.entity
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.audits.AuditLabelUM
import com.tangem.core.ui.components.badge.entity.BadgeUM
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
/**
* Provider Row - Choose Crypto component UI Model
*
* @property title title text
* @property subtitle subtitle text
* @property infoText info text
* @property iconUrl icon url
* @property isSelected indicated whether component is selected (border outline)
* @property badgeList list of badge components
* @property labelUM label component (whether AuditLabel or text)
*/
data class ProviderChooseUM(
val title: TextReference,
val subtitle: TextReference,
val infoText: TextReference,
val iconUrl: String,
val isSelected: Boolean,
val badgeList: ImmutableList<BadgeUM>,
val labelUM: LabelUM?,
) {
@Immutable
sealed class LabelUM {
data class Info(
val auditLabelUM: AuditLabelUM,
) : LabelUM()
data class Text(
val text: TextReference,
) : LabelUM()
}
}

View file

@ -1,12 +1,21 @@
package com.tangem.core.ui.extensions
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.MultipleClickPreventer
/**
@ -38,4 +47,51 @@ fun Modifier.conditional(condition: Boolean, modifier: Modifier.() -> Modifier):
} else {
this
}
}
}
/**
* Conditionally applies a modifier based on a boolean condition.
*/
@Composable
fun Modifier.conditionalCompose(
condition: Boolean,
modifier: @Composable Modifier.() -> Modifier = { Modifier },
otherModifier: @Composable Modifier.() -> Modifier = { this },
): Modifier {
return if (condition) {
then(modifier(Modifier))
} else {
otherModifier()
}
}
/**
* Border with accent outline when selected
*/
@Composable
fun Modifier.selectedBorder(
isSelected: Boolean,
width: Dp = 2.5.dp,
color: Color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
radius: Dp = 16.dp,
) = conditionalCompose(
condition = isSelected,
modifier = {
border(
width = width,
color = color,
shape = RoundedCornerShape(radius),
)
.padding(2.5.dp)
.border(
width = 1.dp,
color = TangemTheme.colors.text.accent,
shape = RoundedCornerShape(radius - 2.dp),
)
.clip(RoundedCornerShape(radius - 2.dp))
},
otherModifier = {
padding(2.dp)
.clip(RoundedCornerShape(radius - 2.dp))
},
)

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M19.77,7.23L19.78,7.22L16.06,3.5L15,4.56L17.11,6.67C16.17,7.03 15.5,7.93 15.5,9C15.5,10.38 16.62,11.5 18,11.5C18.36,11.5 18.69,11.42 19,11.29V18.5C19,19.05 18.55,19.5 18,19.5C17.45,19.5 17,19.05 17,18.5V14C17,12.9 16.1,12 15,12H14V5C14,3.9 13.1,3 12,3H6C4.9,3 4,3.9 4,5V21H14V13.5H15.5V18.5C15.5,19.88 16.62,21 18,21C19.38,21 20.5,19.88 20.5,18.5V9C20.5,8.31 20.22,7.68 19.77,7.23ZM12,13.5V19H6V12H12V13.5ZM12,10H6V5H12V10ZM18,10C17.45,10 17,9.55 17,9C17,8.45 17.45,8 18,8C18.55,8 19,8.45 19,9C19,9.55 18.55,10 18,10Z"
android:fillColor="#1E1E1E"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M19.15,10.42L20.38,8.57L20.39,8.56C21.393,10.106 21.948,11.9 21.996,13.742C22.044,15.584 21.581,17.404 20.66,19C20.484,19.305 20.23,19.558 19.924,19.734C19.619,19.91 19.272,20.001 18.92,20H5.07C4.721,19.998 4.379,19.904 4.077,19.729C3.775,19.554 3.524,19.302 3.35,19C2.24,17.057 1.813,14.799 2.138,12.585C2.463,10.371 3.522,8.33 5.143,6.789C6.765,5.248 8.857,4.295 11.085,4.083C13.312,3.871 15.547,4.412 17.43,5.62L15.58,6.85C14.042,6.081 12.297,5.827 10.604,6.128C8.91,6.428 7.359,7.266 6.179,8.517C5,9.769 4.255,11.367 4.055,13.075C3.855,14.783 4.211,16.51 5.07,18H18.93C19.591,16.853 19.957,15.561 19.995,14.238C20.034,12.915 19.743,11.603 19.15,10.42ZM11.239,15.844C10.996,15.743 10.776,15.596 10.59,15.41C10.404,15.224 10.257,15.004 10.156,14.761C10.055,14.518 10.003,14.258 10.003,13.995C10.003,13.732 10.055,13.472 10.156,13.229C10.257,12.986 10.404,12.766 10.59,12.58L19.08,6.92L13.42,15.41C13.234,15.596 13.014,15.743 12.771,15.844C12.528,15.945 12.268,15.997 12.005,15.997C11.742,15.997 11.482,15.945 11.239,15.844Z"
android:fillColor="#1E1E1E"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22,9.24L14.81,8.62L12,2L9.19,8.63L2,9.24L7.46,13.97L5.82,21L12,17.27L18.18,21L16.55,13.97L22,9.24ZM12,15.4L8.24,17.67L9.24,13.39L5.92,10.51L10.3,10.13L12,6.1L13.71,10.14L18.09,10.52L14.77,13.4L15.77,17.68L12,15.4Z"
android:fillColor="#000000"/>
</vector>

View file

@ -14,11 +14,11 @@ import androidx.compose.ui.draw.clip
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.selectedBorder
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.paymentmethod.entity.PaymentMethodUM
import com.tangem.features.onramp.paymentmethod.entity.PaymentMethodsBottomSheetConfig
import com.tangem.features.onramp.utils.selectedBorder
import kotlinx.collections.immutable.ImmutableList
@Composable
@ -59,27 +59,16 @@ private fun SelectPaymentMethodBottomSheetContent(
val isSelected = remember(item, selectedMethodId) {
item.id == selectedMethodId
}
val itemModifier = if (isSelected) {
Modifier
.fillMaxWidth()
.selectedBorder()
.clickable(onClick = item.onSelect)
.padding(
start = TangemTheme.dimens.spacing12,
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
} else {
Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
.clickable(onClick = item.onSelect)
.padding(
start = TangemTheme.dimens.spacing12,
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
}
val itemModifier = Modifier
.fillMaxWidth()
.selectedBorder(isSelected = isSelected)
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
.clickable(onClick = item.onSelect)
.padding(
start = TangemTheme.dimens.spacing12,
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
PaymentMethodItem(
modifier = itemModifier,
paymentMethod = item,

View file

@ -26,13 +26,10 @@ import androidx.compose.ui.util.fastForEach
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.domain.onramp.model.OnrampPaymentMethod
@ -41,7 +38,6 @@ import com.tangem.features.onramp.paymentmethod.ui.PaymentMethodIcon
import com.tangem.features.onramp.providers.entity.ProviderListItemUM
import com.tangem.features.onramp.providers.entity.SelectPaymentAndProviderUM
import com.tangem.features.onramp.providers.model.previewData.SelectProviderPreviewData
import com.tangem.features.onramp.utils.selectedBorder
@Composable
internal fun SelectProviderBottomSheet(config: TangemBottomSheetConfig, content: @Composable () -> Unit) {
@ -151,13 +147,7 @@ private fun ProviderItem(state: ProviderListItemUM, modifier: Modifier = Modifie
private fun AvailableProviderItem(state: ProviderListItemUM.Available.Content, modifier: Modifier = Modifier) {
Row(
modifier = modifier
.then(
if (state.isSelected) {
Modifier.selectedBorder()
} else {
Modifier.clip(RoundedCornerShape(16.dp))
},
)
.selectedBorder(isSelected = state.isSelected)
.clickable(onClick = state.onClick)
.padding(all = TangemTheme.dimens.spacing12),
verticalAlignment = Alignment.CenterVertically,
@ -227,13 +217,7 @@ private fun UnavailableProviderItem(
) {
Row(
modifier = modifier
.then(
if (isSelected) {
Modifier.selectedBorder()
} else {
Modifier.clip(RoundedCornerShape(16.dp))
},
)
.selectedBorder(isSelected = isSelected)
.padding(all = TangemTheme.dimens.spacing12),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),

View file

@ -1,24 +0,0 @@
package com.tangem.features.onramp.utils
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
@Composable
internal fun Modifier.selectedBorder() = border(
width = 2.5.dp,
color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
shape = RoundedCornerShape(18.dp),
)
.padding(2.5.dp)
.border(
width = 1.dp,
color = TangemTheme.colors.text.accent,
shape = RoundedCornerShape(16.dp),
)
.clip(RoundedCornerShape(16.dp))