From d84f383cf88c559b88b764e2e88a99e10d8612fd Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 24 Jul 2026 16:07:06 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/common/ui/earn/EarnBlock.kt | 334 ++++++++++-------- .../com/tangem/common/ui/earn/EarnBlockUM.kt | 26 +- .../tangem/core/ui/ds/TangemPagerIndicator.kt | 13 +- .../core/ui/ds/button/action/ActionButtons.kt | 11 +- .../token/block/impl/ui/TokenMarketBlock.kt | 10 +- .../promobanners/impl/ui/PromoBannersBlock.kt | 7 +- .../state/TokenDetailsStateController.kt | 6 +- .../ui/AddAndManageBottomSheetContent.kt | 8 +- .../items/OrganizeTokenItemConverter.kt | 20 +- .../organizetokens/ui/OrganizeDropDownMenu.kt | 30 +- .../ui/OrganizeTokensContent.kt | 52 +-- .../ui/preview/OrganizeTokensPreview.kt | 15 +- .../child/tokenActions/TokenActionContent.kt | 32 +- .../preview/WalletBalancePreview.kt | 4 +- .../wallet/state/model/WalletActionButtons.kt | 12 +- .../SetTokenListErrorTransformer.kt | 4 +- .../MultiWalletBalanceUMTransformer.kt | 4 +- .../presentation/wallet/ui/WalletScreen2.kt | 47 ++- .../wallet/ui/components/MarketsHint.kt | 6 +- .../wallet/ui/components/MarketsTooltip.kt | 34 +- .../wallet/ui/components/WalletItemBlocks.kt | 19 +- .../wallet/ui/components/WalletNFTItem2.kt | 49 ++- .../ui/components/common/WalletBalance.kt | 46 +-- .../ui/components/common/WalletContent.kt | 8 +- .../ui/components/common/WalletTopBar.kt | 140 ++++---- .../multicurrency/MultiCurrencyContent.kt | 52 ++- .../YieldSupplyToEarnBlockConverter.kt | 53 +-- .../impl/main/model/YieldSupplyModelTest.kt | 32 +- .../YieldSupplyToEarnBlockConverterTest.kt | 40 ++- 29 files changed, 567 insertions(+), 547 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlock.kt b/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlock.kt index d71390173d..6bebb22216 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlock.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlock.kt @@ -15,11 +15,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.BlurredEdgeTreatment import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.innerShadow -import androidx.compose.ui.platform.testTag import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.shadow.Shadow import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString @@ -43,6 +43,8 @@ import com.tangem.core.ui.ds.row.TangemRowLayoutId import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreviewRedesign +import com.tangem.core.ui.res.generated.icons.Icons +import com.tangem.core.ui.res.generated.icons.ic_chevron_right_24 import com.tangem.core.ui.test.TokenDetailsScreenTestTags import dev.chrisbanes.haze.HazeStyle import dev.chrisbanes.haze.HazeTint @@ -55,8 +57,8 @@ private const val GLOW_ALPHA = 0.7f private val BorderWidth = 1.dp private val InnerShadowBlur = 20.dp private val ShimmerSubtitleWidth = 78.dp -private val LoaderSize = 12.dp -private val LoaderStrokeWidth = 1.5.dp +private val LoaderSize = 20.dp +private val LoaderStrokeWidth = 2.dp @Composable fun EarnBlock(state: EarnBlockUM, modifier: Modifier = Modifier) { @@ -69,31 +71,31 @@ fun EarnBlock(state: EarnBlockUM, modifier: Modifier = Modifier) { @Composable private fun EarnBlockLoading(modifier: Modifier = Modifier) { - val shape = RoundedCornerShape(TangemTheme.dimens2.x5) + val shape = RoundedCornerShape(24.dp) TangemRowContainer( modifier = modifier .clip(shape) - .background(TangemTheme.colors2.surface.level3) - .border(width = BorderWidth, color = TangemTheme.colors2.border.neutral.primary, shape = shape), - contentPadding = PaddingValues(all = TangemTheme.dimens2.x3), + .background(TangemTheme.colors3.bg.secondary) + .border(width = BorderWidth, color = TangemTheme.colors3.border.primary, shape = shape), + contentPadding = PaddingValues(all = 16.dp), content = { CircleShimmer( modifier = Modifier .layoutId(TangemRowLayoutId.HEAD) - .padding(end = TangemTheme.dimens2.x3) - .size(TangemTheme.dimens2.x10), + .padding(end = 12.dp) + .size(40.dp), ) RectangleShimmer( modifier = Modifier .layoutId(TangemRowLayoutId.START_TOP) - .size(width = ShimmerSubtitleWidth, height = TangemTheme.dimens2.x4), - radius = TangemTheme.dimens2.x2, + .size(width = ShimmerSubtitleWidth, height = 16.dp), + radius = 8.dp, ) RectangleShimmer( modifier = Modifier .layoutId(TangemRowLayoutId.START_BOTTOM) - .size(width = TangemTheme.dimens2.x16, height = TangemTheme.dimens2.x5), - radius = TangemTheme.dimens2.x2, + .size(width = 64.dp, height = 20.dp), + radius = 8.dp, ) }, ) @@ -101,7 +103,7 @@ private fun EarnBlockLoading(modifier: Modifier = Modifier) { @Composable private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Modifier) { - val shape = RoundedCornerShape(TangemTheme.dimens2.x5) + val shape = RoundedCornerShape(24.dp) val clickModifier = state.onClick?.let { Modifier.clickable(onClick = it) } ?: Modifier @@ -109,14 +111,14 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo modifier = modifier .clip(shape) .then(clickModifier.backgroundModifier(state.type, state.backgroundUM, shape)), - contentPadding = PaddingValues(all = TangemTheme.dimens2.x4), + contentPadding = PaddingValues(all = 16.dp), content = { EarnBlockIcon( type = state.type, iconUM = state.iconUM, modifier = Modifier .layoutId(TangemRowLayoutId.HEAD) - .padding(end = TangemTheme.dimens2.x3), + .padding(end = 12.dp), ) EarnBlockTitle( @@ -124,12 +126,12 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo type = state.type, modifier = Modifier .layoutId(TangemRowLayoutId.START_TOP) - .padding(end = TangemTheme.dimens2.x2), + .padding(end = 8.dp), ) val subtitleModifier = Modifier .layoutId(TangemRowLayoutId.START_BOTTOM) - .padding(end = TangemTheme.dimens2.x2) + .padding(end = 8.dp) when (val subtitle = state.subtitleUM) { is EarnBlockUM.SubtitleUM.Text -> EarnBlockSubtitle( subtitle = subtitle, @@ -151,37 +153,37 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo @Composable private fun EarnBlockPromo(state: EarnBlockUM.Promo, modifier: Modifier = Modifier) { - val shape = RoundedCornerShape(TangemTheme.dimens2.x5) + val shape = RoundedCornerShape(24.dp) Column( modifier = modifier .clip(shape) .backgroundModifier(state.type, state.backgroundUM, shape) - .padding(all = TangemTheme.dimens2.x4), - verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x3), + .padding(all = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), ) { Row(verticalAlignment = Alignment.CenterVertically) { EarnBlockIcon( type = state.type, iconUM = state.iconUM, - modifier = Modifier.padding(end = TangemTheme.dimens2.x3), + modifier = Modifier.padding(end = 12.dp), ) Column( - verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1), + verticalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.weight(1f), ) { Text( text = state.title.resolveAnnotatedReference(), - style = TangemTheme.typography2.bodyMedium16, - color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography3.body.medium, + color = TangemTheme.colors3.text.primary, ) Text( text = state.subtitle.resolveReference(), - style = TangemTheme.typography2.captionMedium12, + style = TangemTheme.typography3.caption.medium, color = state.type.accentText(), ) } } - Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2)) { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { EarnBlockPromoButton( text = resourceReference(CoreResR.string.common_learn_more), type = TangemButtonType.Secondary, @@ -225,8 +227,8 @@ private fun Modifier.backgroundModifier( ): Modifier { return when (backgroundUM) { is EarnBlockUM.BackgroundUM.Surface -> this - .background(TangemTheme.colors2.surface.level3) - .border(width = BorderWidth, color = TangemTheme.colors2.border.neutral.primary, shape = shape) + .background(TangemTheme.colors3.bg.secondary) + .border(width = BorderWidth, color = TangemTheme.colors3.border.primary, shape = shape) is EarnBlockUM.BackgroundUM.AccentSoft -> tintedBackground(type.accentSoftTint(), shape) is EarnBlockUM.BackgroundUM.AccentStrong -> tintedBackground(type.accentStrongTint(), shape) } @@ -260,77 +262,84 @@ private fun EarnBlockTrailing(type: Type, trailingUM: EarnBlockUM.TrailingUM?, o modifier = Modifier.layoutId(TangemRowLayoutId.TAIL), ) } - is EarnBlockUM.TrailingUM.Balance -> { - val fiatModifier = Modifier.layoutId(TangemRowLayoutId.END_TOP).let { - if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_FIAT_AMOUNT) else it - } - val cryptoModifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM).let { - if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_TOKEN_AMOUNT) else it - } - Text( - text = trailingUM.fiatValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveAnnotatedReference(), - style = TangemTheme.typography2.bodySemibold16, - color = TangemTheme.colors2.text.neutral.primary, - modifier = fiatModifier, + is EarnBlockUM.TrailingUM.Balance -> EarnBlockBalance(type = type, trailingUM = trailingUM) + is EarnBlockUM.TrailingUM.Chevron -> { + TangemIcon( + tangemIconUM = TangemIconUM.Icon( + imageVector = Icons.ic_chevron_right_24, + tintReference = { TangemTheme.colors3.icon.secondary }, + ), + modifier = Modifier + .layoutId(TangemRowLayoutId.TAIL) + .size(24.dp), ) - Text( - text = trailingUM.cryptoValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveReference(), - style = TangemTheme.typography2.captionMedium12, - color = TangemTheme.colors2.text.neutral.secondary, - modifier = cryptoModifier, + } + is EarnBlockUM.TrailingUM.StatusIcon -> { + TangemIcon( + tangemIconUM = TangemIconUM.Icon( + iconRes = trailingUM.tone.iconRes(), + tintReference = { trailingUM.tone.tint() }, + ), + modifier = Modifier + .layoutId(TangemRowLayoutId.TAIL) + .size(24.dp) + .testTag(TokenDetailsScreenTestTags.EARN_BLOCK_TITLE_ICON), + ) + } + is EarnBlockUM.TrailingUM.Loader -> { + CircularProgressIndicator( + color = trailingUM.tone.color(), + strokeWidth = LoaderStrokeWidth, + strokeCap = StrokeCap.Round, + modifier = Modifier + .layoutId(TangemRowLayoutId.TAIL) + .size(LoaderSize), ) } null -> Unit } } +@Composable +private fun EarnBlockBalance(type: Type, trailingUM: EarnBlockUM.TrailingUM.Balance) { + val fiatModifier = Modifier.layoutId(TangemRowLayoutId.END_TOP).let { + if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_FIAT_AMOUNT) else it + } + val cryptoModifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM).let { + if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_TOKEN_AMOUNT) else it + } + Text( + text = trailingUM.fiatValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveAnnotatedReference(), + style = TangemTheme.typography3.body.medium, + color = TangemTheme.colors3.text.primary, + modifier = fiatModifier, + ) + Text( + text = trailingUM.cryptoValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveReference(), + style = TangemTheme.typography3.caption.medium, + color = TangemTheme.colors3.text.secondary, + modifier = cryptoModifier, + ) +} + @Composable private fun EarnBlockTitle(titleUM: EarnBlockUM.TitleUM, type: Type, modifier: Modifier = Modifier) { - val titleText: @Composable () -> Unit = { - Text( - text = titleUM.text.resolveReference(), - style = titleUM.style.textStyle, - color = titleUM.tone.color(type), - ) - } - val icon = titleUM.iconUM - if (icon == null) { - Box(modifier = modifier) { titleText() } - return - } - Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { - titleText() - Spacer(modifier = Modifier.width(TangemTheme.dimens2.x1)) - TangemIcon( - tangemIconUM = TangemIconUM.Icon( - iconRes = icon.tone.iconRes(), - tintReference = { icon.tone.tint() }, - ), - modifier = Modifier - .size(TangemTheme.dimens2.x4) - .testTag(TokenDetailsScreenTestTags.EARN_BLOCK_TITLE_ICON), - ) - } + Text( + text = titleUM.text.resolveReference(), + style = titleUM.style.textStyle, + color = titleUM.tone.color(type), + modifier = modifier, + ) } @Composable private fun EarnBlockSubtitle(subtitle: EarnBlockUM.SubtitleUM.Text, type: Type, modifier: Modifier = Modifier) { - val textStyle = subtitle.style.textStyle - val textColor = subtitle.tone.color(type) - if (subtitle.loader == null) { - Text(text = subtitle.text.resolveReference(), style = textStyle, color = textColor, modifier = modifier) - return - } - Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { - Text(text = subtitle.text.resolveReference(), style = textStyle, color = textColor) - Spacer(modifier = Modifier.width(3.dp)) - CircularProgressIndicator( - color = subtitle.loader.tone.color(), - strokeWidth = LoaderStrokeWidth, - strokeCap = StrokeCap.Round, - modifier = Modifier.size(LoaderSize), - ) - } + Text( + text = subtitle.text.resolveReference(), + style = subtitle.style.textStyle, + color = subtitle.tone.color(type), + modifier = modifier, + ) } @Composable @@ -351,7 +360,7 @@ private fun EarnBlockAccentedSubtitle( } }, style = subtitle.style.textStyle, - color = TangemTheme.colors2.text.neutral.tertiary, + color = TangemTheme.colors3.text.secondary, modifier = modifier, ) } @@ -360,32 +369,40 @@ private fun EarnBlockAccentedSubtitle( private fun EarnBlockIcon(type: Type, iconUM: EarnBlockUM.IconUM, modifier: Modifier = Modifier) { Box( contentAlignment = Alignment.Center, - modifier = modifier.size(TangemTheme.dimens2.x10), + modifier = modifier.size(40.dp), ) { - if (iconUM is EarnBlockUM.IconUM.Glowing) { - val glowShape = RoundedCornerShape(percent = 50) + val glowColor = when (iconUM) { + is EarnBlockUM.IconUM.Glowing -> iconUM.tone.glowColor(type) + is EarnBlockUM.IconUM.Plain -> null + } + if (glowColor != null) { Box( modifier = Modifier - .size(TangemTheme.dimens2.x6) + .size(24.dp) .hazeForegroundEffectTangem( style = HazeStyle( backgroundColor = Color.Transparent, tint = HazeTint(Color.Transparent), - blurRadius = TangemTheme.dimens2.x4, + blurRadius = 16.dp, ), ) { blurredEdgeTreatment = BlurredEdgeTreatment.Unbounded } - .background(color = type.accentGlow().copy(alpha = GLOW_ALPHA), shape = glowShape), + .background(color = glowColor.copy(alpha = GLOW_ALPHA), shape = RoundedCornerShape(percent = 50)), ) } + val isWarningTone = (iconUM as? EarnBlockUM.IconUM.Glowing)?.tone == EarnBlockUM.IconUM.Tone.Warning val iconRes = when (iconUM) { is EarnBlockUM.IconUM.Glowing -> iconUM.iconRes is EarnBlockUM.IconUM.Plain -> iconUM.iconRes } TangemIcon( - tangemIconUM = TangemIconUM.Image(imageRes = iconRes), - modifier = Modifier.size(TangemTheme.dimens2.x10), + tangemIconUM = if (isWarningTone) { + TangemIconUM.Icon(iconRes = iconRes, tintReference = { TangemTheme.colors3.icon.status.warning }) + } else { + TangemIconUM.Image(imageRes = iconRes) + }, + modifier = Modifier.size(40.dp), ) } } @@ -394,29 +411,36 @@ private fun EarnBlockIcon(type: Type, iconUM: EarnBlockUM.IconUM, modifier: Modi @Composable @ReadOnlyComposable private fun Type.accentText(): Color = when (this) { - Type.Staking -> TangemTheme.colors2.text.status.accent - Type.YieldSupply -> TangemTheme.colors2.text.status.positive + Type.Staking -> TangemTheme.colors3.text.brand + Type.YieldSupply -> TangemTheme.colors3.text.accent.green +} + +@Composable +@ReadOnlyComposable +private fun EarnBlockUM.IconUM.Tone.glowColor(type: Type): Color = when (this) { + EarnBlockUM.IconUM.Tone.Accent -> type.accentGlow() + EarnBlockUM.IconUM.Tone.Warning -> TangemTheme.colors3.icon.status.warning } @Composable @ReadOnlyComposable private fun Type.accentGlow(): Color = when (this) { - Type.Staking -> TangemTheme.colors2.border.status.accent - Type.YieldSupply -> TangemTheme.colors2.text.status.positive + Type.Staking -> TangemTheme.colors3.text.brand + Type.YieldSupply -> TangemTheme.colors3.text.accent.green } @Composable @ReadOnlyComposable private fun Type.accentSoftTint(): Color = when (this) { - Type.Staking -> TangemTheme.colors2.markers.backgroundTintedBlue - Type.YieldSupply -> TangemTheme.colors2.markers.backgroundTintedGreen + Type.Staking -> TangemTheme.colors3.text.brand + Type.YieldSupply -> TangemTheme.colors3.text.accent.green } @Composable @ReadOnlyComposable private fun Type.accentStrongTint(): Color = when (this) { - Type.Staking -> TangemTheme.colors2.text.status.accent - Type.YieldSupply -> TangemTheme.colors2.text.status.positive + Type.Staking -> TangemTheme.colors3.text.brand + Type.YieldSupply -> TangemTheme.colors3.text.accent.green } private fun EarnBlockUM.TrailingUM.Button.Style.buttonType(type: Type): TangemButtonType = when (this) { @@ -430,53 +454,53 @@ private fun EarnBlockUM.TrailingUM.Button.Style.buttonType(type: Type): TangemBu @Composable @ReadOnlyComposable private fun EarnBlockUM.TitleUM.Tone.color(type: Type): Color = when (this) { - EarnBlockUM.TitleUM.Tone.Primary -> TangemTheme.colors2.text.neutral.primary - EarnBlockUM.TitleUM.Tone.Secondary -> TangemTheme.colors2.text.neutral.secondary - EarnBlockUM.TitleUM.Tone.Disabled -> TangemTheme.colors2.text.neutral.tertiary + EarnBlockUM.TitleUM.Tone.Primary -> TangemTheme.colors3.text.primary + EarnBlockUM.TitleUM.Tone.Secondary -> TangemTheme.colors3.text.secondary + EarnBlockUM.TitleUM.Tone.Disabled -> TangemTheme.colors3.text.tertiary EarnBlockUM.TitleUM.Tone.Accent -> type.accentText() } @Composable @ReadOnlyComposable private fun EarnBlockUM.SubtitleUM.Tone.color(type: Type): Color = when (this) { - EarnBlockUM.SubtitleUM.Tone.Primary -> TangemTheme.colors2.text.neutral.primary - EarnBlockUM.SubtitleUM.Tone.Disabled -> TangemTheme.colors2.text.neutral.tertiary + EarnBlockUM.SubtitleUM.Tone.Primary -> TangemTheme.colors3.text.primary + EarnBlockUM.SubtitleUM.Tone.Disabled -> TangemTheme.colors3.text.tertiary EarnBlockUM.SubtitleUM.Tone.Accent -> type.accentText() } -private fun EarnBlockUM.TitleUM.IconTone.iconRes(): Int = when (this) { - EarnBlockUM.TitleUM.IconTone.Warning -> R.drawable.ic_attention_default_24 - EarnBlockUM.TitleUM.IconTone.Info -> R.drawable.ic_alert_circle_24 +private fun EarnBlockUM.TrailingUM.StatusIcon.Tone.iconRes(): Int = when (this) { + EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning -> R.drawable.ic_attention_default_24 + EarnBlockUM.TrailingUM.StatusIcon.Tone.Info -> R.drawable.ic_alert_circle_24 } @Composable @ReadOnlyComposable -private fun EarnBlockUM.TitleUM.IconTone.tint(): Color = when (this) { - EarnBlockUM.TitleUM.IconTone.Warning -> TangemTheme.colors2.graphic.status.attention - EarnBlockUM.TitleUM.IconTone.Info -> TangemTheme.colors2.graphic.neutral.secondary +private fun EarnBlockUM.TrailingUM.StatusIcon.Tone.tint(): Color = when (this) { + EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning -> TangemTheme.colors3.icon.status.warning + EarnBlockUM.TrailingUM.StatusIcon.Tone.Info -> TangemTheme.colors3.icon.secondary } @Composable @ReadOnlyComposable -private fun EarnBlockUM.SubtitleUM.LoaderTone.color(): Color = when (this) { - EarnBlockUM.SubtitleUM.LoaderTone.Positive -> TangemTheme.colors2.text.status.positive - EarnBlockUM.SubtitleUM.LoaderTone.Muted -> TangemTheme.colors2.graphic.neutral.tertiaryConstant +private fun EarnBlockUM.TrailingUM.Loader.LoaderTone.color(): Color = when (this) { + EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive -> TangemTheme.colors3.icon.accent.green + EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted -> TangemTheme.colors3.icon.tertiary } private val EarnBlockUM.TitleUM.Style.textStyle: TextStyle @Composable @ReadOnlyComposable get() = when (this) { - EarnBlockUM.TitleUM.Style.Large -> TangemTheme.typography2.bodyMedium16 - EarnBlockUM.TitleUM.Style.Small -> TangemTheme.typography2.captionMedium12 + EarnBlockUM.TitleUM.Style.Large -> TangemTheme.typography3.body.medium + EarnBlockUM.TitleUM.Style.Small -> TangemTheme.typography3.caption.medium } private val EarnBlockUM.SubtitleUM.Style.textStyle: TextStyle @Composable @ReadOnlyComposable get() = when (this) { - EarnBlockUM.SubtitleUM.Style.Large -> TangemTheme.typography2.bodyMedium16 - EarnBlockUM.SubtitleUM.Style.Small -> TangemTheme.typography2.captionMedium12 + EarnBlockUM.SubtitleUM.Style.Large -> TangemTheme.typography3.body.medium + EarnBlockUM.SubtitleUM.Style.Small -> TangemTheme.typography3.caption.medium } // endregion @@ -488,7 +512,7 @@ private fun EarnBlock_Staking_Preview(@PreviewParameter(EarnBlockStakingPreviewP TangemThemePreviewRedesign { EarnBlock( state = state, - modifier = Modifier.padding(TangemTheme.dimens2.x4), + modifier = Modifier.padding(16.dp), ) } } @@ -502,7 +526,7 @@ private fun EarnBlock_YieldSupply_Preview( TangemThemePreviewRedesign { EarnBlock( state = state, - modifier = Modifier.padding(TangemTheme.dimens2.x4), + modifier = Modifier.padding(16.dp), ) } } @@ -612,7 +636,7 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr ), onClick = {}, ), - // Content — yield enabled, "Details" button + // Content — yield enabled, chevron EarnBlockUM.Content( type = Type.YieldSupply, backgroundUM = EarnBlockUM.BackgroundUM.Surface, @@ -630,13 +654,10 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr style = EarnBlockUM.SubtitleUM.Style.Large, tone = EarnBlockUM.SubtitleUM.Tone.Accent, ), - trailingUM = EarnBlockUM.TrailingUM.Button( - text = resourceReference(CoreResR.string.details_title), - style = EarnBlockUM.TrailingUM.Button.Style.Secondary, - ), + trailingUM = EarnBlockUM.TrailingUM.Chevron, onClick = {}, ), - // Content with Warning title icon + // Content with Warning status icon in trailing EarnBlockUM.Content( type = Type.YieldSupply, backgroundUM = EarnBlockUM.BackgroundUM.Surface, @@ -645,7 +666,6 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr text = resourceReference(CoreResR.string.common_yield_mode), style = EarnBlockUM.TitleUM.Style.Small, tone = EarnBlockUM.TitleUM.Tone.Primary, - iconUM = EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Warning), ), subtitleUM = EarnBlockUM.SubtitleUM.Text( text = resourceReference( @@ -655,13 +675,12 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr style = EarnBlockUM.SubtitleUM.Style.Large, tone = EarnBlockUM.SubtitleUM.Tone.Accent, ), - trailingUM = EarnBlockUM.TrailingUM.Button( - text = resourceReference(CoreResR.string.details_title), - style = EarnBlockUM.TrailingUM.Button.Style.Secondary, + trailingUM = EarnBlockUM.TrailingUM.StatusIcon( + tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning, ), onClick = {}, ), - // Content with Info title icon + // Content with Info status icon in trailing EarnBlockUM.Content( type = Type.YieldSupply, backgroundUM = EarnBlockUM.BackgroundUM.Surface, @@ -670,7 +689,6 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr text = resourceReference(CoreResR.string.common_yield_mode), style = EarnBlockUM.TitleUM.Style.Small, tone = EarnBlockUM.TitleUM.Tone.Primary, - iconUM = EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Info), ), subtitleUM = EarnBlockUM.SubtitleUM.Text( text = resourceReference( @@ -680,47 +698,51 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr style = EarnBlockUM.SubtitleUM.Style.Large, tone = EarnBlockUM.SubtitleUM.Tone.Accent, ), - trailingUM = EarnBlockUM.TrailingUM.Button( - text = resourceReference(CoreResR.string.details_title), - style = EarnBlockUM.TrailingUM.Button.Style.Secondary, + trailingUM = EarnBlockUM.TrailingUM.StatusIcon( + tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info, ), onClick = {}, ), - // Processing.Enter — enabling, no trailing + // Processing.Enter — enabling, single-line title, loader in trailing EarnBlockUM.Content( type = Type.YieldSupply, backgroundUM = EarnBlockUM.BackgroundUM.Surface, iconUM = EarnBlockUM.IconUM.Glowing(iconRes = R.drawable.ic_yield_40), titleUM = EarnBlockUM.TitleUM( - text = resourceReference(CoreResR.string.common_yield_mode), + text = combinedReference( + resourceReference(CoreResR.string.common_yield_mode), + stringReference(" "), + resourceReference(CoreResR.string.common_enabling), + ), style = EarnBlockUM.TitleUM.Style.Small, tone = EarnBlockUM.TitleUM.Tone.Primary, ), - subtitleUM = EarnBlockUM.SubtitleUM.Text( - text = resourceReference(CoreResR.string.common_enabling), - style = EarnBlockUM.SubtitleUM.Style.Large, - tone = EarnBlockUM.SubtitleUM.Tone.Accent, - loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Positive), + subtitleUM = null, + trailingUM = EarnBlockUM.TrailingUM.Loader( + tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive, ), - trailingUM = null, ), - // Processing.Exit — disabling, no trailing, plain icon + // Processing.Exit — disabling, single-line title, warning icon, loader in trailing EarnBlockUM.Content( type = Type.YieldSupply, backgroundUM = EarnBlockUM.BackgroundUM.Surface, - iconUM = EarnBlockUM.IconUM.Plain(iconRes = R.drawable.ic_yield_disabling_40), + iconUM = EarnBlockUM.IconUM.Glowing( + iconRes = R.drawable.ic_yield_40, + tone = EarnBlockUM.IconUM.Tone.Warning, + ), titleUM = EarnBlockUM.TitleUM( - text = resourceReference(CoreResR.string.common_yield_mode), + text = combinedReference( + resourceReference(CoreResR.string.common_yield_mode), + stringReference(" "), + resourceReference(CoreResR.string.common_disabling), + ), style = EarnBlockUM.TitleUM.Style.Small, tone = EarnBlockUM.TitleUM.Tone.Primary, ), - subtitleUM = EarnBlockUM.SubtitleUM.Text( - text = resourceReference(CoreResR.string.common_disabling), - style = EarnBlockUM.SubtitleUM.Style.Large, - tone = EarnBlockUM.SubtitleUM.Tone.Disabled, - loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Muted), + subtitleUM = null, + trailingUM = EarnBlockUM.TrailingUM.Loader( + tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted, ), - trailingUM = null, ), ), ) diff --git a/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlockUM.kt b/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlockUM.kt index c0b0a4ad33..0675bf13ed 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlockUM.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/earn/EarnBlockUM.kt @@ -45,8 +45,11 @@ sealed interface EarnBlockUM { @Immutable sealed interface IconUM { - data class Glowing(@DrawableRes val iconRes: Int) : IconUM + data class Glowing(@DrawableRes val iconRes: Int, val tone: Tone = Tone.Accent) : IconUM data class Plain(@DrawableRes val iconRes: Int) : IconUM + + /** Accent — glow/tint follow the block [Type]; Warning — yellow icon tint and glow. */ + enum class Tone { Accent, Warning } } @Immutable @@ -54,13 +57,9 @@ sealed interface EarnBlockUM { val text: TextReference, val style: Style, val tone: Tone, - val iconUM: IconUM? = null, ) { enum class Style { Large, Small } enum class Tone { Primary, Secondary, Disabled, Accent } - - data class IconUM(val tone: IconTone) - enum class IconTone { Warning, Info } } @Immutable @@ -69,7 +68,6 @@ sealed interface EarnBlockUM { val text: TextReference, val style: Style, val tone: Tone, - val loader: Loader? = null, ) : SubtitleUM data class AccentedText( @@ -78,11 +76,8 @@ sealed interface EarnBlockUM { val style: Style, ) : SubtitleUM - data class Loader(val tone: LoaderTone) - enum class Style { Large, Small } enum class Tone { Primary, Disabled, Accent } - enum class LoaderTone { Positive, Muted } } @Immutable @@ -100,5 +95,18 @@ sealed interface EarnBlockUM { val cryptoValue: TextReference, val isBalanceHidden: Boolean, ) : TrailingUM + + /** Chevron indicating the whole row is clickable. */ + data object Chevron : TrailingUM + + /** Status icon (warning / info) placed in the trailing slot. */ + data class StatusIcon(val tone: Tone) : TrailingUM { + enum class Tone { Warning, Info } + } + + /** Circular progress indicator placed in the trailing slot (enabling / disabling states). */ + data class Loader(val tone: LoaderTone) : TrailingUM { + enum class LoaderTone { Positive, Muted } + } } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt index e86793d0d1..2b122509b3 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt @@ -97,9 +97,11 @@ fun TangemPagerIndicator( contentAlignment = Alignment.Center, ) { Row( - modifier = Modifier.offset { - IntOffset(animState.slideOffset.value.roundToInt(), 0) - }, + modifier = Modifier + .wrapContentWidth(unbounded = true) + .offset { + IntOffset(animState.slideOffset.value.roundToInt(), 0) + }, horizontalArrangement = Arrangement.spacedBy(SPACING), verticalAlignment = Alignment.CenterVertically, ) { @@ -367,8 +369,8 @@ val TangemPagerIndicatorColors: PagerIndicatorColors @Composable @ReadOnlyComposable get() = PagerIndicatorColors( - active = TangemTheme.colors2.graphic.neutral.primary, - inactive = TangemTheme.colors2.graphic.neutral.tertiary, + active = TangemTheme.colors3.bg.inverse, + inactive = TangemTheme.colors3.bg.opaque.secondary, overlay = null, ) @@ -413,6 +415,7 @@ private class TangemPagerIndicatorPreviewProvider : PreviewParameterProvider Unit) { Text( text = stringResourceSafe(R.string.organize_tokens_sort_by_balance), - style = TangemTheme.typography2.headingSemibold17, + style = TangemTheme.typography3.body.medium, color = if (organizeMenuUM.isSortedByBalance) { - TangemTheme.colors2.text.status.disabled + TangemTheme.colors3.text.tertiary } else { - TangemTheme.colors2.text.neutral.primary + TangemTheme.colors3.text.primary }, maxLines = 1, modifier = Modifier @@ -79,12 +79,12 @@ private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMe }, enabled = !organizeMenuUM.isSortedByBalance, ) - .padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4), + .padding(vertical = 10.dp, horizontal = 16.dp), ) HorizontalDivider( thickness = 0.5.dp, - color = TangemTheme.colors2.border.neutral.quaternary, + color = TangemTheme.colors3.border.tertiary, ) } @@ -102,36 +102,36 @@ private fun GroupTokensMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenu onDropdownDismiss() }, ) - .padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4), + .padding(vertical = 10.dp, horizontal = 16.dp), ) { Text( text = stringResourceSafe(R.string.organize_tokens_group), - style = TangemTheme.typography2.headingSemibold17, - color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography3.body.medium, + color = TangemTheme.colors3.text.primary, maxLines = 1, ) Box( - modifier = Modifier.size(TangemTheme.dimens2.x6), + modifier = Modifier.size(24.dp), contentAlignment = Alignment.Center, ) { if (organizeMenuUM.isGrouped) { Box( modifier = Modifier - .padding(TangemTheme.dimens2.x0_5) - .size(TangemTheme.dimens2.x5) + .padding(2.dp) + .size(20.dp) .background( - color = TangemTheme.colors2.graphic.neutral.primary, + color = TangemTheme.colors3.icon.primary, shape = CircleShape, ), ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_check_default_24), contentDescription = null, - tint = TangemTheme.colors2.graphic.neutral.primaryInverted, + tint = TangemTheme.colors3.icon.inverse, modifier = Modifier .align(Alignment.Center) - .padding(TangemTheme.dimens2.x0_5) - .size(TangemTheme.dimens2.x4), + .padding(2.dp) + .size(16.dp), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/OrganizeTokensContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/OrganizeTokensContent.kt index b64ccf1e30..cc65c0cbbe 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/OrganizeTokensContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/OrganizeTokensContent.kt @@ -34,8 +34,8 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.haze.hazeEffectTangem import com.tangem.core.ui.components.haze.hazeSourceTangem -import com.tangem.core.ui.ds.button.TangemButton import com.tangem.core.ui.ds.image.TangemIcon +import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.ds.row.TangemRowContainer import com.tangem.core.ui.ds.row.TangemRowLayoutId import com.tangem.core.ui.ds.row.header.TangemHeaderRow @@ -43,10 +43,9 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTail import com.tangem.core.ui.ds.row.token.TangemTokenRowUM import com.tangem.core.ui.ds.row.token.internal.TokenRowEndContent import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle -import com.tangem.core.ui.ds.topbar.TangemTopBar -import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent -import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM -import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.ds2.button.TangemButton +import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation +import com.tangem.core.ui.extensions.copy import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreviewRedesign @@ -82,21 +81,21 @@ internal fun OrganizeTokensContent( onDismissRequest = onDismiss, content = TangemBottomSheetConfigContent.Empty, ), - containerColor = TangemTheme.colors2.surface.level2, + containerColor = TangemTheme.colors3.bg.primary, title = { - TangemTopBar( + TangemTopNavigation( + contentPadding = TangemTopNavigation.DefaultContentPadding.copy(top = 16.dp), + windowInsets = WindowInsets(0.dp), + blurBackground = false, + contentAlign = TangemTopNavigation.ContentAlign.Center, title = resourceReference(R.string.organize_tokens_title), - type = TangemTopBarType.BottomSheet, - endContent = { - TangemTopBarActionContent( - actionUM = TangemTopBarActionUM( - iconRes = R.drawable.ic_exchange_mini_24, - isActionable = true, - onClick = { isShowDropdownMenu = true }, - ghostModeProgress = 0f, - ), + endButton = { + TangemButton( modifier = Modifier.testTag(OrganizeTokensScreenTestTags.MENU_BUTTON), - type = TangemTopBarType.BottomSheet, + variant = TangemButton.Variant.Material, + size = TangemButton.Size.X11, + iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_exchange_mini_24), + onClick = { isShowDropdownMenu = true }, ) OrganizeDropDownMenu( organizeMenuUM = organizeTokensUM.organizeMenuUM, @@ -137,7 +136,7 @@ private fun TokenList( var draggingItem by remember { mutableStateOf(null) } Box( - modifier = modifier.background(TangemTheme.colors2.surface.level2), + modifier = modifier.background(TangemTheme.colors3.bg.primary), ) { val footerInset = LocalTangemBottomSheetContentBottomInset.current @@ -238,7 +237,7 @@ private fun LazyItemScope.DraggableItem( enabled = isValidDropTarget, ) { _ -> val modifierWithBackground = itemModifier - .background(color = TangemTheme.colors.background.primary) + .background(color = TangemTheme.colors3.bg.secondary) .semantics { lazyListItemPosition = index } when (item) { @@ -281,16 +280,23 @@ private fun BoxScope.BottomButtons(organizeTokensUM: OrganizeTokensUM) { .padding(bottom = bottomBarHeight + TangemTheme.dimens2.x4), ) { TangemButton( - buttonUM = organizeTokensUM.cancelButton, modifier = Modifier .weight(1f) .testTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON), + onClick = organizeTokensUM.cancelButton.onClick, + text = organizeTokensUM.cancelButton.text, + variant = TangemButton.Variant.Secondary, + size = TangemButton.Size.X12, + isEnabled = organizeTokensUM.cancelButton.isEnabled, ) TangemButton( - buttonUM = organizeTokensUM.applyButton, modifier = Modifier .weight(1f) .testTag(OrganizeTokensScreenTestTags.APPLY_BUTTON), + onClick = organizeTokensUM.applyButton.onClick, + text = organizeTokensUM.applyButton.text, + size = TangemButton.Size.X12, + isEnabled = organizeTokensUM.applyButton.isEnabled, ) } } @@ -355,8 +361,8 @@ private fun OrganizeTokenRow( TokenRowEndContent( endContentUM = tokenRowUM.topEndContentUM, isBalanceHidden = isBalanceHidden, - textStyle = TangemTheme.typography2.captionSemibold12, - textColor = TangemTheme.colors2.text.neutral.secondary, + textStyle = TangemTheme.typography3.caption.medium, + textColor = TangemTheme.colors3.text.secondary, placeholderWidth = TangemTheme.dimens2.x11, modifier = Modifier .layoutId(layoutId = TangemRowLayoutId.START_BOTTOM) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt index 8ca6f08e99..de16ada7c3 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.child.organizetokens.ui.preview +import androidx.compose.ui.text.SpanStyle import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.ds.button.TangemButtonType import com.tangem.core.ui.ds.button.TangemButtonUM @@ -8,9 +9,12 @@ import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM import com.tangem.core.ui.ds.row.internal.TangemRowTailUM import com.tangem.core.ui.ds.row.token.TangemTokenRowUM import com.tangem.core.ui.event.consumedEvent +import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.styledStringReference import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeRowItemUM import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensUM import com.tangem.feature.wallet.child.organizetokens.entity.RoundingModeUM @@ -75,7 +79,16 @@ internal object OrganizeTokensPreview { tokenRowUM = draggableToken.copy( id = "${group.id}_token_$tokenNumber", titleUM = TangemTokenRowUM.TitleUM.Content( - text = stringReference(value = "Token $tokenNumber from $networkNumber network"), + text = combinedReference( + stringReference(value = "Token $tokenNumber"), + stringReference(value = " "), + styledStringReference( + value = "TKN$tokenNumber", + spanStyleReference = { + SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) + }, + ), + ), ), ), groupId = group.id, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionContent.kt index f0cd95fb56..56e14403fe 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionContent.kt @@ -16,7 +16,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag -import com.tangem.core.ui.test.BaseBottomSheetTestTags import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.DpOffset @@ -31,6 +30,7 @@ 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.TangemThemePreviewRedesign +import com.tangem.core.ui.test.BaseBottomSheetTestTags import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM import kotlinx.collections.immutable.ImmutableList @@ -60,9 +60,9 @@ internal fun TokenActionContent( tokenRowUM = tokenRowUM, isBalanceHidden = isBalanceHidden, modifier = Modifier - .padding(horizontal = TangemTheme.dimens2.x3) + .padding(horizontal = 12.dp) .clip(RoundedCornerShape(18.dp)) - .background(TangemTheme.colors2.surface.level3), + .background(TangemTheme.colors3.bg.secondary), ) TangemContextMenu( expanded = true, @@ -93,17 +93,17 @@ private fun TokenActionContextMenuContent(actions: ImmutableList Column { Row( - horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2_5), + horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically, modifier = Modifier .testTag(BaseBottomSheetTestTags.ACTION_BUTTON) .fillMaxWidth() - .clip(RoundedCornerShape(TangemTheme.dimens2.x2_5)) + .clip(RoundedCornerShape(10.dp)) .clickable( enabled = item.isEnabled, onClick = { @@ -112,39 +112,39 @@ private fun TokenActionContextMenuContent(actions: ImmutableList Unit, bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit, ) { - val density = LocalDensity.current - val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() } - var walletBalance by remember { mutableStateOf(TextReference.EMPTY) } var pullToRefreshConfig by remember { mutableStateOf( @@ -207,10 +204,15 @@ private fun WalletContent2( ) }, ) { paddingValues, bottomSheetState -> - val marketHintApproxHeight = 140.dp + val density = LocalDensity.current + var marketsHintHeight by remember { mutableStateOf(0.dp) } + val collapsedBodyOverhang = with(density) { behavior.state.partialHeightLimit.toDp() } val contentPadding = PaddingValues( - bottom = paddingValues.calculateBottomPadding() + marketHintApproxHeight, + bottom = paddingValues.calculateBottomPadding() + + marketsHintHeight + + collapsedBodyOverhang + + TangemTheme.dimens2.x2, ) val selectedWalletIndex by rememberUpdatedState(state.selectedWalletIndex) @@ -235,22 +237,17 @@ private fun WalletContent2( .fillMaxSize() .hazeSourceTangem(zIndex = -2f), ) { - val backgroundColor = if (LocalIsInDarkTheme.current) { - TangemTheme.colors2.surface.level1 - } else { - TangemTheme.colors2.surface.level2 - } Box( modifier = Modifier .matchParentSize() - .background(backgroundColor), + .background(TangemTheme.colors3.bg.primary), ) val isSheetExpanded by remember { derivedStateOf { bottomSheetState.targetValue == TangemSheetValue.Expanded } } if (!isSheetExpanded) { NorthernLightsBackground( - containerColor = backgroundColor, + containerColor = TangemTheme.colors3.bg.primary, modifier = Modifier .graphicsLayer { alpha = 1 - behavior.state.collapsedFraction * 2 } .matchParentSize(), @@ -262,10 +259,10 @@ private fun WalletContent2( pullToRefreshState = pullToRefreshState, pullToRefreshConfig = pullToRefreshConfig, behavior = behavior, - topOffset = subtitleBottom + TangemTheme.dimens2.x2, + topOffset = subtitleBottom + 8.dp, ) - val overlay = TangemTheme.colors2.overlay.overlayPrimary + val overlay = TangemTheme.colors3.material.tint.solid // Root-coordinates bounds of the "Add & Manage" button per pager page, reported by the // button itself, so the markets hint and tooltip can avoid covering it @@ -376,14 +373,14 @@ private fun WalletContent2( }, ) } - - val peekHeight = - bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight MarketsHint( modifier = Modifier .align(Alignment.BottomCenter) .fillMaxWidth(fraction = .6f) - .padding(bottom = peekHeight), + .padding(bottom = paddingValues.calculateBottomPadding()) + .onSizeChanged { size -> + marketsHintHeight = with(density) { size.height.toDp() } + }, isVisible = isShowMarketsHint, obstacleBounds = remember(currentWalletIndex) { { organizeButtonBounds[currentWalletIndex] } @@ -400,7 +397,7 @@ private fun WalletContent2( .fillMaxWidth(), isVisible = state.showMarketsOnboarding, availableHeight = maxHeight, - sheetTopInset = TangemTheme.dimens2.x3, + sheetTopInset = 12.dp, bottomSheetState = bottomSheetState, onCloseClick = state.onDismissMarketsTooltip, obstacleBounds = remember(walletsPagerState, organizeButtonBounds) { @@ -425,15 +422,15 @@ private inline fun BaseScaffoldWithMarkets( ) { val density = LocalDensity.current val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(density = this).toDp() } - val peekHeight = bottomSheetHeaderHeightProvider() + TangemTheme.dimens2.x3 + bottomBarHeight + val peekHeight = bottomSheetHeaderHeightProvider() + 12.dp + bottomBarHeight val coroutineScope = rememberCoroutineScope() val bottomSheetState = rememberTangemStandardBottomSheetState() val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState) - val expandedBackground = TangemTheme.colors2.surface.level2 - val collapsedBackground = TangemTheme.colors2.surface.level3 + val expandedBackground = TangemTheme.colors3.bg.primary + val collapsedBackground = TangemTheme.colors3.bg.secondary val background by animateColorAsState( targetValue = if (bottomSheetState.targetValue == TangemSheetValue.Expanded) { expandedBackground @@ -527,8 +524,8 @@ private fun BottomSheet( val maxHeight = LocalWindowSize.current.height val shape = RoundedCornerShape( - topStart = TangemTheme.dimens2.x8, - topEnd = TangemTheme.dimens2.x8, + topStart = 32.dp, + topEnd = 32.dp, ) CustomBottomSheet( state = bottomSheetState, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsHint.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsHint.kt index 399c345f9c..9fe2e75e6e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsHint.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsHint.kt @@ -61,14 +61,14 @@ internal fun MarketsHint(isVisible: Boolean, modifier: Modifier = Modifier, obst ) { Text( text = stringResourceSafe(R.string.markets_hint), - style = TangemTheme.typography2.bodyRegular15, - color = TangemTheme.colors2.text.neutral.tertiary, + style = TangemTheme.typography3.subheading.medium, + color = TangemTheme.colors3.text.secondary, textAlign = TextAlign.Center, ) Icon( modifier = Modifier.size(size = 24.dp), painter = painterResource(id = R.drawable.ic_chevron_24), - tint = TangemTheme.colors2.graphic.neutral.tertiary, + tint = TangemTheme.colors3.icon.secondary, contentDescription = null, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsTooltip.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsTooltip.kt index 1c9e506c96..44f6fd6f2a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsTooltip.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/MarketsTooltip.kt @@ -32,9 +32,13 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.* import com.tangem.core.ui.components.sheetscaffold.TangemSheetState +import com.tangem.core.ui.ds.image.TangemIconUM +import com.tangem.core.ui.ds2.button.TangemButton import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreviewRedesign +import com.tangem.core.ui.res.generated.icons.Icons +import com.tangem.core.ui.res.generated.icons.ic_cross_20 import com.tangem.core.ui.test.MarketTooltipTestTags import com.tangem.core.ui.utils.toPx import com.tangem.feature.wallet.impl.R @@ -118,14 +122,14 @@ internal fun MarketsTooltip( @Composable internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier = Modifier) { - val backgroundColor = TangemTheme.colors.background.action + val backgroundColor = TangemTheme.colors3.bg.tertiary val tipDpSize = DpSize(width = 20.dp, height = 8.dp) val tooltipShape = remember(tipDpSize) { TooltipShape(cornerRadius = 16.dp, tipSize = tipDpSize) } Row( modifier = modifier .shadow( - elevation = TangemTheme.dimens.elevation12, + elevation = 12.dp, shape = tooltipShape, clip = false, ambientColor = Color.Black.copy(alpha = 0.7f), @@ -149,27 +153,21 @@ internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier ) { Text( text = stringResourceSafe(id = R.string.markets_tooltip_v2_title), - style = TangemTheme.typography.subtitle2, - color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography3.subheading.medium, + color = TangemTheme.colors3.text.primary, ) Text( text = stringResourceSafe(id = R.string.markets_tooltip_message), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.secondary, + style = TangemTheme.typography3.caption.medium, + color = TangemTheme.colors3.text.secondary, ) } - Icon( - modifier = Modifier - .size(size = 16.dp) - .clickable( - interactionSource = null, - indication = null, - onClick = onCloseClick, - ) - .testTag(MarketTooltipTestTags.CLOSE_BUTTON), - painter = painterResource(id = R.drawable.ic_close_24), - tint = TangemTheme.colors.icon.informative, - contentDescription = null, + TangemButton( + variant = TangemButton.Variant.Ghost, + size = TangemButton.Size.X7, + iconStart = TangemIconUM.Icon(imageVector = Icons.ic_cross_20), + onClick = onCloseClick, + modifier = Modifier.testTag(MarketTooltipTestTags.CLOSE_BUTTON), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt index 500920fc7e..217c9112cd 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletItemBlocks.kt @@ -9,7 +9,7 @@ import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.boundsInRoot import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.testTag -import com.tangem.core.ui.ds.button.TangemButton +import com.tangem.core.ui.ds2.button.TangemButton import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.haptic.TangemHapticEffect import com.tangem.core.ui.res.LocalHapticManager @@ -26,7 +26,7 @@ internal const val ORGANIZE_TOKENS_BUTTON_ITEM_KEY = "OrganizeTokensButton" internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) { (state as? WalletUM.Content)?.let { content -> item(key = "NFTCollections", contentType = "NFTCollections") { - WalletNFTItem( + WalletNFTItem2( modifier = itemModifier, state = content.nftState, ) @@ -62,15 +62,18 @@ internal fun LazyListScope.organizeTokens2( } TangemButton( - buttonUM = organizeButton.copy( - onClick = { - hapticManager.perform(TangemHapticEffect.View.ContextClick) - organizeButton.onClick() - }, - ), modifier = itemModifier .onGloballyPositioned { currentOnButtonBoundsChange(it.boundsInRoot()) } .testTag(testTag), + size = TangemButton.Size.X9, + onClick = { + hapticManager.perform(TangemHapticEffect.View.ContextClick) + organizeButton.onClick() + }, + variant = TangemButton.Variant.Secondary, + iconStart = organizeButton.tangemIconUM, + text = organizeButton.text, + isEnabled = organizeButton.isEnabled, ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem2.kt index 8759ecdf11..983f16ad7d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem2.kt @@ -41,7 +41,7 @@ import kotlinx.collections.immutable.persistentListOf internal fun WalletNFTItem2(state: WalletNFTItemUM, modifier: Modifier = Modifier) { val nftModifier = modifier .clip(RoundedCornerShape(18.dp)) - .background(TangemTheme.colors2.surface.level3) + .background(TangemTheme.colors3.bg.secondary) when (state) { is WalletNFTItemUM.Hidden -> Unit is WalletNFTItemUM.Empty -> WalletNFTItemEmpty( @@ -70,13 +70,13 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie painter = painterResource(R.drawable.img_nft_empty_collection), contentDescription = null, modifier = Modifier - .size(TangemTheme.dimens2.x10) + .size(40.dp) .layoutId(TangemRowLayoutId.HEAD), ) Text( text = stringResourceSafe(R.string.nft_wallet_title), - style = TangemTheme.typography2.bodySemibold16, - color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography3.body.medium, + color = TangemTheme.colors3.text.primary, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier @@ -85,8 +85,8 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie ) Text( text = stringResourceSafe(R.string.nft_wallet_receive_nft), - style = TangemTheme.typography2.captionSemibold12, - color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography3.caption.medium, + color = TangemTheme.colors3.text.secondary, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier @@ -96,7 +96,7 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24), contentDescription = null, - tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant, + tint = TangemTheme.colors3.icon.secondary, modifier = Modifier.layoutId(TangemRowLayoutId.TAIL), ) } @@ -116,9 +116,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () -> } Text( text = stringResourceSafe(R.string.nft_wallet_title), - style = TangemTheme.typography2.bodySemibold16.applyBladeBrush( + style = TangemTheme.typography3.body.medium.applyBladeBrush( isEnabled = state.isFlickering, - textColor = TangemTheme.colors2.text.neutral.primary, + textColor = TangemTheme.colors3.text.primary, ), maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -132,9 +132,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () -> state.allAssetsCount, state.collectionsCount, ), - style = TangemTheme.typography2.captionSemibold12.applyBladeBrush( + style = TangemTheme.typography3.caption.medium.applyBladeBrush( isEnabled = state.isFlickering, - textColor = TangemTheme.colors2.text.neutral.secondary, + textColor = TangemTheme.colors3.text.secondary, ), maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -145,7 +145,7 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () -> Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24), contentDescription = null, - tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant, + tint = TangemTheme.colors3.icon.secondary, modifier = Modifier.layoutId(TangemRowLayoutId.TAIL), ) } @@ -173,8 +173,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) { } Text( text = stringResourceSafe(R.string.nft_wallet_title), - style = TangemTheme.typography2.bodySemibold16, - color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography3.body.medium, + color = TangemTheme.colors3.text.primary, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier @@ -183,8 +183,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) { ) Text( text = stringResourceSafe(R.string.nft_wallet_unable_to_load), - style = TangemTheme.typography2.captionSemibold12, - color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography3.caption.medium, + color = TangemTheme.colors3.text.secondary, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier @@ -207,7 +207,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) { .layoutId(TangemRowLayoutId.HEAD), ) TextShimmer( - style = TangemTheme.typography2.bodySemibold16, + style = TangemTheme.typography3.body.medium, radius = TangemTheme.dimens2.x25, modifier = Modifier @@ -216,7 +216,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) { .width(TangemTheme.dimens.size110), ) TextShimmer( - style = TangemTheme.typography2.captionSemibold12, + style = TangemTheme.typography3.caption.medium, radius = TangemTheme.dimens2.x25, modifier = Modifier .layoutId(TangemRowLayoutId.START_BOTTOM) @@ -251,7 +251,7 @@ private fun BoxScope.CollectionsPreviews(previews: ImmutableList { Icon( - modifier = previewModifier - .background(TangemTheme.colors2.surface.level2), + modifier = previewModifier.background(TangemTheme.colors3.bg.primary), imageVector = ImageVector.vectorResource(R.drawable.ic_nft_preview_more_16), - tint = TangemTheme.colors2.text.neutral.secondary, + tint = TangemTheme.colors3.text.secondary, contentDescription = null, ) } @@ -289,7 +288,7 @@ private fun BoxScope.previews2Modifiers(): List = listOf( .zIndex(1f) .padding(TangemTheme.dimens2.x0_5) .clip(RoundedCornerShape(topStart = 10.dp)) - .background(TangemTheme.colors2.surface.level3) + .background(TangemTheme.colors3.bg.secondary) .padding(start = TangemTheme.dimens2.x0_5, top = TangemTheme.dimens2.x0_5) .size(TangemTheme.dimens2.x6) .clip(RoundedCornerShape(TangemTheme.dimens2.x2)) @@ -307,7 +306,7 @@ private fun BoxScope.previews3Modifiers(): List = listOf( .zIndex(1f) .padding(top = 10.dp, end = 1.dp) .clip(RoundedCornerShape(8.dp)) - .background(TangemTheme.colors2.surface.level3) + .background(TangemTheme.colors3.bg.secondary) .padding(TangemTheme.dimens2.x0_5) .size(18.dp) .clip(RoundedCornerShape(6.dp)) @@ -347,7 +346,7 @@ private fun Preview_WalletNFTItem(@PreviewParameter(WalletNFTItemProvider2::clas WalletNFTItem2( state = state, modifier = Modifier - .background(TangemTheme.colors2.surface.level1), + .background(TangemTheme.colors3.bg.primary), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt index ceb9e0f51b..6fb064160c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt @@ -102,7 +102,7 @@ internal fun WalletBalance( walletBalanceUM = walletBalanceUM, isBalanceHidden = isBalanceHidden, ) - SpacerH(TangemTheme.dimens2.x3) + SpacerH(12.dp) Box( modifier = Modifier.onGloballyPositioned { coordinates -> val rawBottomPx = coordinates.boundsInRoot().bottom @@ -113,9 +113,9 @@ internal fun WalletBalance( SubtitleRow(walletBalanceUM = walletBalanceUM) } } - SpacerH(TangemTheme.dimens2.x2) + SpacerH(8.dp) ActionButtons(buttons = hapticButtons, modifier = Modifier.fillMaxWidth()) - SpacerH(TangemTheme.dimens2.x6) + SpacerH(24.dp) } } @@ -140,20 +140,20 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M is WalletAdditionalInfo.Content.SyncProgress -> { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1_5), + horizontalArrangement = Arrangement.spacedBy(6.dp), ) { Text( text = resourceReference( id = R.string.initial_wallet_sync_restore_progress, formatArgs = wrappedList(content.progressPercent), ).resolveReference(), - style = TangemTheme.typography2.bodyRegular14, - color = TangemTheme.colors2.text.neutral.tertiary, + style = TangemTheme.typography3.subheading.medium, + color = TangemTheme.colors3.text.secondary, modifier = Modifier.testTag(MainScreenTestTags.SYNC_PROGRESS_TEXT), ) CircularProgressIndicator( modifier = Modifier.size(19.dp), - color = TangemTheme.colors2.graphic.neutral.primary, + color = TangemTheme.colors3.icon.secondary, strokeWidth = 2.dp, ) } @@ -161,12 +161,12 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M else -> { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1), + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Text( text = walletBalanceUM.name, - style = TangemTheme.typography2.bodyRegular14, - color = TangemTheme.colors2.text.neutral.tertiary, + style = TangemTheme.typography3.subheading.medium, + color = TangemTheme.colors3.text.secondary, modifier = Modifier.testTag(MainScreenTestTags.CARD_TITLE), ) TangemDeviceIcon( @@ -194,36 +194,36 @@ private fun Balance(walletBalanceUM: WalletBalanceUM, isBalanceHidden: Boolean, when (balanceUM) { is WalletBalanceUM.Content -> Text( text = balanceUM.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(), - style = TangemTheme.typography2.titleRegular44.applyBladeBrush( + style = TangemTheme.typography3.display.medium.applyBladeBrush( isEnabled = balanceUM.isBalanceFlickering, - textColor = TangemTheme.colors2.text.neutral.primary, + textColor = TangemTheme.colors3.text.primary, ), - color = TangemTheme.colors2.text.neutral.primary, + color = TangemTheme.colors3.text.primary, maxLines = 1, overflow = TextOverflow.Ellipsis, autoSize = TextAutoSize.StepBased( - minFontSize = TangemTheme.typography2.bodySemibold15.fontSize, - maxFontSize = TangemTheme.typography2.titleRegular44.fontSize, + minFontSize = TangemTheme.typography3.body.medium.fontSize, + maxFontSize = TangemTheme.typography3.display.medium.fontSize, ), ) is WalletBalanceUM.Error -> Text( text = StringsSigns.DASH_SIGN, - style = TangemTheme.typography2.titleRegular44, - color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography3.display.medium, + color = TangemTheme.colors3.text.primary, maxLines = 1, overflow = TextOverflow.Ellipsis, autoSize = TextAutoSize.StepBased( - minFontSize = TangemTheme.typography2.bodySemibold15.fontSize, - maxFontSize = TangemTheme.typography2.titleRegular44.fontSize, + minFontSize = TangemTheme.typography3.body.medium.fontSize, + maxFontSize = TangemTheme.typography3.display.medium.fontSize, ), ) is WalletBalanceUM.Loading -> TextShimmer( text = "123456", - style = TangemTheme.typography2.titleRegular44, - radius = TangemTheme.dimens2.x25, + style = TangemTheme.typography3.display.medium, + radius = 100.dp, ) is WalletBalanceUM.Empty -> TextPlaceholder( - textStyle = TangemTheme.typography2.titleRegular44, + textStyle = TangemTheme.typography3.display.medium, width = 200.dp, ) } @@ -244,7 +244,7 @@ private fun WalletBalance_Preview( behavior = rememberTangemExitUntilCollapsedScrollBehavior(), buttons = params.actionsList, isBalanceHidden = false, - modifier = Modifier.background(TangemTheme.colors2.surface.level1), + modifier = Modifier.background(TangemTheme.colors3.bg.secondary), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt index 0bd93b7cf9..ca5f5ca0f1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt @@ -46,10 +46,10 @@ internal fun WalletListContent( promoBannersBlockComponent: PromoBannersBlockComponent? = null, walletId: String? = null, ) { - val containerColor = TangemTheme.colors2.surface.level1 + val containerColor = TangemTheme.colors3.bg.primary - val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3) - val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3) + val movableItemModifier = Modifier.padding(horizontal = 12.dp) + val itemModifier = movableItemModifier.padding(top = 12.dp) LazyColumn( modifier = modifier.testTag(MainScreenTestTags.SCREEN_CONTAINER), @@ -73,7 +73,7 @@ internal fun WalletListContent( item(key = "PromoBannersBlock") { component.ContentWithPadding( horizontalItemPadding = 12.dp, - modifier = Modifier.padding(top = TangemTheme.dimens2.x3), + modifier = Modifier.padding(top = 12.dp), walletId = walletId, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt index b36ae041ec..06f0145881 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt @@ -1,41 +1,41 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common import android.content.res.Configuration -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.lerp import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview -import com.tangem.core.ui.components.haze.hazeEffectTangem -import com.tangem.core.ui.ds.topbar.TangemTopBar -import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior +import com.tangem.core.ui.ds2.button.TangemButton +import com.tangem.core.ui.ds2.topnavigation.TangemNavigationText +import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.orMaskWithStars import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.haptic.TangemHapticEffect -import com.tangem.core.ui.res.* +import com.tangem.core.ui.res.LocalHapticManager +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreviewRedesign import com.tangem.core.ui.test.MainScreenTestTags import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig -import dev.chrisbanes.haze.HazeProgressive -import dev.chrisbanes.haze.HazeTint import kotlinx.collections.immutable.persistentListOf private const val VISIBILITY_THRESHOLD = 0.5f +private val BRAND_ICON_SLOT_SIZE = 44.dp /** * Wallet screen collapsing top bar @@ -53,76 +53,54 @@ internal fun WalletTopBar( behavior: TangemCollapsingAppBarBehavior, ) { val hapticManager = LocalHapticManager.current - Surface( - color = Color.Unspecified, - contentColor = Color.Unspecified, - modifier = Modifier.hazeEffectTangemTopBar(behavior), - ) { - val isWrappedBalanceShown by remember { - derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD } - } + val isWrappedBalanceShown by remember { + derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD } + } - val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) { - walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown } - } + val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) { + walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown } + } - TangemTopBar( - title = wrappedBalance, - startContent = { - TangemTopBarActionContent( - TangemTopBarActionUM( - iconRes = R.drawable.ic_tangem_24, - isActionable = false, - ), + TangemTopNavigation( + modifier = Modifier.testTag(MainScreenTestTags.TOP_BAR), + contentAlign = TangemTopNavigation.ContentAlign.Center, + startButton = { + // Non-clickable brand mark, sized to align with the trailing action buttons. + Box(modifier = Modifier.size(BRAND_ICON_SLOT_SIZE), contentAlignment = Alignment.Center) { + Icon( + painter = painterResource(id = R.drawable.ic_tangem_24), + contentDescription = null, + tint = TangemTheme.colors3.icon.primary, ) - }, - endContent = { - Row( - modifier = Modifier - .clip(CircleShape) - .background( - lerp( - start = Color.Transparent, - stop = TangemTheme.colors2.button.backgroundSecondary, - fraction = behavior.state.collapsedFraction, - ), - ), - ) { - topBarConfig.endActions.forEach { action -> - TangemTopBarActionContent( - action.copy( - onClick = action.onClick?.let { onClick -> - { - hapticManager.perform(TangemHapticEffect.View.ContextClick) - onClick() - } - }, - ), - modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON), - ) - } + } + }, + endButtonsGroup = if (topBarConfig.endActions.isNotEmpty()) { + { + topBarConfig.endActions.forEach { action -> + TangemButton( + variant = TangemButton.Variant.Ghost, + size = TangemButton.Size.X11, + iconStart = TangemIconUM.Icon(iconRes = action.iconRes), + isEnabled = action.isActionable && action.onClick != null, + onClick = { + hapticManager.perform(TangemHapticEffect.View.ContextClick) + action.onClick?.invoke() + }, + modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON), + ) } - }, - modifier = Modifier - .statusBarsPadding() - .testTag(MainScreenTestTags.TOP_BAR), - ) - } -} - -@Composable -private fun Modifier.hazeEffectTangemTopBar(behavior: TangemCollapsingAppBarBehavior): Modifier { - val rootBackground by LocalRootBackgroundColor.current - val intensity by animateFloatAsState(targetValue = behavior.state.collapsedFraction * 2f) - - return hazeEffectTangem { - fallbackTint = HazeTint(rootBackground.copy(alpha = intensity / 2)) - progressive = HazeProgressive.verticalGradient( - startIntensity = intensity, - endIntensity = 0f, - preferPerformance = true, - ) - } + } + } else { + null + }, + contentColumn = { + AnimatedVisibility(visible = wrappedBalance != null) { + wrappedBalance?.let { balance -> + TangemNavigationText(text = balance, role = TangemNavigationText.Role.Title) + } + } + }, + ) } // region Preview diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt index e8ce6bb945..3a6815f794 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt @@ -40,9 +40,6 @@ import com.tangem.core.ui.components.tokenlist.NON_CONTENT_TOKENS_LIST_KEY import com.tangem.core.ui.components.tokenlist.TokenListItem import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM import com.tangem.core.ui.decorations.roundedShapeItemDecoration -import com.tangem.core.ui.ds.button.SecondaryTangemButton -import com.tangem.core.ui.ds.button.TangemButtonShape -import com.tangem.core.ui.ds.button.TangemButtonSize import com.tangem.core.ui.ds.image.TangemIcon import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.ds.row.header.TangemHeaderRow @@ -51,6 +48,7 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTailUM import com.tangem.core.ui.ds.row.token.TangemTokenRow import com.tangem.core.ui.ds.row.token.TangemTokenRowUM import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle +import com.tangem.core.ui.ds2.button.TangemButton import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.test.MainScreenTestTags @@ -159,13 +157,13 @@ private fun LazyListScope.tokenItem( val itemModifier = modifier .testTag(MainScreenTestTags.TOKEN_LIST_ITEM) .semantics { lazyListItemPosition = index } - .padding(top = if (index == 0) TangemTheme.dimens2.x3 else 0.dp) + .padding(top = if (index == 0) 12.dp else 0.dp) .roundedShapeItemDecoration( radius = 18.dp, currentIndex = index, addDefaultPadding = false, lastIndex = lastIndex, - backgroundColor = TangemTheme.colors2.surface.level3, + backgroundColor = TangemTheme.colors3.bg.secondary, ) var position by remember { mutableStateOf(Offset.Zero) } @@ -261,11 +259,11 @@ private fun LazyListScope.portfolioItem( modifier = modifier .animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null) .roundedShapeItemDecoration( - radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5, + radius = if (listItem.isExpanded) 24.dp else 20.dp, currentIndex = tokenIndex + 1, addDefaultPadding = false, lastIndex = lastIndex, - backgroundColor = TangemTheme.colors2.surface.level3, + backgroundColor = TangemTheme.colors3.bg.secondary, ), visible = listItem.isExpanded, ) { @@ -327,15 +325,15 @@ private fun LazyListScope.accountItem( ) val portfolioModifier = modifier - .padding(top = if (index != 0) TangemTheme.dimens2.x2 else TangemTheme.dimens2.x3) + .padding(top = if (index != 0) 8.dp else 12.dp) .testTag(MainScreenTestTags.ACCOUNT_LIST_ITEM) .semantics { lazyListItemPosition = index } .roundedShapeItemDecoration( currentIndex = 0, - radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5, + radius = if (listItem.isExpanded) 24.dp else 20.dp, addDefaultPadding = false, lastIndex = effectiveLastIndex, - backgroundColor = TangemTheme.colors2.surface.level3, + backgroundColor = TangemTheme.colors3.bg.secondary, ) if (listItem.isCollapsable) { PortfolioRowItem( @@ -422,7 +420,7 @@ internal fun PortfolioRowItem( } val iconBoxSize = when (headIcon) { - is TangemIconUM.Empty -> TangemTheme.dimens2.x9 + is TangemIconUM.Empty -> 36.dp else -> size.toBoxSize() } TangemIcon( @@ -444,8 +442,8 @@ internal fun PortfolioRowItem( animationSpec = tween(durationMillis = 350), ) - val startStyle = TangemTheme.typography2.captionSemibold12 - val stopStyle = TangemTheme.typography2.bodySemibold16 + val startStyle = TangemTheme.typography3.caption.medium + val stopStyle = TangemTheme.typography3.body.medium val textStyle by remember(animationFraction.value) { derivedStateOf { lerp(startStyle, stopStyle, animationFraction.value) } @@ -509,7 +507,7 @@ private fun LazyListScope.nonContentItem(modifier: Modifier = Modifier) { NonContentItemContent( modifier = modifier .animateItem(fadeInSpec = null, fadeOutSpec = null) - .padding(top = TangemTheme.dimens.spacing96), + .padding(top = 96.dp), ) } } @@ -521,7 +519,7 @@ private fun LazyListScope.nonContentItem2(onEmptyClick: () -> Unit, modifier: Mo ) { NonContentItemContentV2( onClick = onEmptyClick, - textColor = TangemTheme.colors2.text.neutral.tertiary, + textColor = TangemTheme.colors3.text.secondary, modifier = modifier .animateItem(fadeInSpec = null, fadeOutSpec = null) .padding(top = 46.dp), @@ -540,17 +538,17 @@ private fun LazyListScope.nonContentAccountItem(listItem: TokensListItemUM2.Port modifier = modifier .animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null) .roundedShapeItemDecoration( - radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5, + radius = if (listItem.isExpanded) 24.dp else 20.dp, addDefaultPadding = false, currentIndex = 1, lastIndex = 1, - backgroundColor = TangemTheme.colors2.surface.level3, + backgroundColor = TangemTheme.colors3.bg.secondary, ), visible = listItem.isExpanded, ) { NonContentItemContentV2( modifier = Modifier.padding(vertical = 36.dp), - textColor = TangemTheme.colors2.text.neutral.secondary, + textColor = TangemTheme.colors3.text.secondary, onClick = listItem.onEmptyClick, ) } @@ -566,23 +564,23 @@ internal fun NonContentItemContentV2(textColor: Color, modifier: Modifier = Modi Icon( painter = painterResource(id = R.drawable.ic_empty_64), contentDescription = null, - modifier = Modifier.size(size = TangemTheme.dimens2.x16), - tint = TangemTheme.colors2.graphic.neutral.quaternary, + modifier = Modifier.size(64.dp), + tint = TangemTheme.colors3.icon.tertiary, ) - SpacerH(TangemTheme.dimens2.x5) + SpacerH(20.dp) Text( text = stringResourceSafe(id = R.string.main_empty_tokens_list_message), - modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing48), + modifier = Modifier.padding(horizontal = 48.dp), color = textColor, textAlign = TextAlign.Center, - style = TangemTheme.typography2.bodyRegular14, + style = TangemTheme.typography3.subheading.medium, ) - SpacerH(TangemTheme.dimens2.x4) - SecondaryTangemButton( + SpacerH(16.dp) + TangemButton( text = resourceReference(id = R.string.common_add_tokens), + variant = TangemButton.Variant.Secondary, + size = TangemButton.Size.X9, onClick = onClick, - size = TangemButtonSize.X8, - shape = TangemButtonShape.Rounded, modifier = Modifier.testTag(MainScreenTestTags.EMPTY_TOKENS_ADD_BUTTON), ) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/converter/YieldSupplyToEarnBlockConverter.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/converter/YieldSupplyToEarnBlockConverter.kt index ed13583cad..4120331026 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/converter/YieldSupplyToEarnBlockConverter.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/converter/YieldSupplyToEarnBlockConverter.kt @@ -78,7 +78,6 @@ internal class YieldSupplyToEarnBlockConverter : Converter EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Warning) - value.shouldShowInfoIcon -> EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Info) - else -> null + private fun buildTrailing(value: YieldSupplyUM.Content): EarnBlockUM.TrailingUM = when { + value.shouldShowWarningIcon -> EarnBlockUM.TrailingUM.StatusIcon( + tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning, + ) + value.shouldShowInfoIcon -> EarnBlockUM.TrailingUM.StatusIcon( + tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info, + ) + else -> EarnBlockUM.TrailingUM.Chevron } private fun buildProcessingEnter(): EarnBlockUM.Content { @@ -109,17 +109,18 @@ internal class YieldSupplyToEarnBlockConverter : Converter