diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds2/button/TangemButtonExt.kt b/core/ui/src/main/java/com/tangem/core/ui/ds2/button/TangemButtonExt.kt index a023d2cf26..028b66b851 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds2/button/TangemButtonExt.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds2/button/TangemButtonExt.kt @@ -3,9 +3,10 @@ package com.tangem.core.ui.ds2.button import androidx.compose.runtime.Composable import androidx.compose.runtime.NonRestartableComposable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.res.generated.icons.Icons -import com.tangem.core.ui.res.generated.icons.ic_arrow_left_20 +import com.tangem.core.ui.res.generated.icons.ic_chevron_left_20 import com.tangem.core.ui.res.generated.icons.ic_cross_20 @Composable @@ -14,7 +15,8 @@ fun TangemButton.Back(modifier: Modifier = Modifier, onClick: () -> Unit) { TangemButton( modifier = modifier, variant = TangemButton.Variant.Material, - iconStart = TangemIconUM.Icon(Icons.ic_arrow_left_20), + size = TangemButton.Size.X11, + iconStart = TangemIconUM.Icon(Icons.ic_chevron_left_20), onClick = onClick, ) } @@ -25,7 +27,26 @@ fun TangemButton.Close(modifier: Modifier = Modifier, onClick: () -> Unit) { TangemButton( modifier = modifier, variant = TangemButton.Variant.Material, + size = TangemButton.Size.X11, iconStart = TangemIconUM.Icon(Icons.ic_cross_20), onClick = onClick, ) +} + +@Composable +@NonRestartableComposable +fun TangemButton.GroupEntry(iconUM: TangemIconUM, modifier: Modifier = Modifier, onClick: () -> Unit) { + TangemButton( + modifier = modifier, + variant = TangemButton.Variant.Ghost, + size = TangemButton.Size.X9, + iconStart = iconUM, + onClick = onClick, + ) +} + +@Composable +@NonRestartableComposable +fun TangemButton.GroupEntry(imageVector: ImageVector, modifier: Modifier = Modifier, onClick: () -> Unit) { + GroupEntry(iconUM = TangemIconUM.Icon(imageVector), modifier = modifier, onClick = onClick) } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds2/search/TangemSearch.kt b/core/ui/src/main/java/com/tangem/core/ui/ds2/search/TangemSearch.kt index bd6ed68653..9009854d55 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds2/search/TangemSearch.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds2/search/TangemSearch.kt @@ -140,7 +140,11 @@ private fun SearchField(state: TangemSearch.State, focusRequester: FocusRequeste Icon( modifier = Modifier.padding(end = 8.dp), imageVector = Icons.ic_search_20, - tint = TangemTheme.colors3.icon.primary, + tint = if (state.isActive) { + TangemTheme.colors3.icon.secondary + } else { + TangemTheme.colors3.icon.primary + }, contentDescription = null, ) QueryTextField(state = state, focusRequester = focusRequester) diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds2/surface/TangemSurface.kt b/core/ui/src/main/java/com/tangem/core/ui/ds2/surface/TangemSurface.kt index 2b4f731dac..c60d3eb95b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds2/surface/TangemSurface.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds2/surface/TangemSurface.kt @@ -98,7 +98,7 @@ fun TangemSurface( } if (onClick != null) { - CompositionLocalProvider(LocalRippleConfiguration provides tangemSurfaceRipple()) { + CompositionLocalProvider(LocalRippleConfiguration provides tangemSurfaceRipple(color)) { surface() } } else { @@ -115,14 +115,17 @@ fun TangemSurface( * `isAlphaContentClip`) to avoid the dark blur bleeding through the surface. */ @Composable -private fun Modifier.materialShadow(shape: Shape): Modifier = softLayerShadow( - radius = 40.dp, - color = Color.Black.copy(alpha = 0.12f), - shape = shape, - spread = 0.dp, - offset = DpOffset(x = 0.dp, y = 8.dp), - isAlphaContentClip = true, -) +private fun Modifier.materialShadow(shape: Shape): Modifier { + val isBlurEnabled = LocalHazeState.current.blurEnabled + return softLayerShadow( + radius = 40.dp, + color = Color.Black.copy(alpha = 0.12f), + shape = shape, + spread = 0.dp, + offset = DpOffset(x = 0.dp, y = 8.dp), + isAlphaContentClip = isBlurEnabled, + ) +} /** Diagonal gradient stroke that wraps the material variant. */ @Composable @@ -191,8 +194,12 @@ private fun materialBorderBrush(): Brush { @Composable @ReadOnlyComposable -private fun tangemSurfaceRipple(): RippleConfiguration = RippleConfiguration( - color = TangemTheme.colors3.interaction.press.default, +private fun tangemSurfaceRipple(backgroundColor: Color): RippleConfiguration = RippleConfiguration( + color = if (backgroundColor == TangemTheme.colors3.bg.inverse) { + TangemTheme.colors3.interaction.press.inverse + } else { + TangemTheme.colors3.interaction.press.default + }, rippleAlpha = RippleAlpha( draggedAlpha = 0f, focusedAlpha = 0f, diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemNavigationText.kt b/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemNavigationText.kt index 2f9a0fc5d2..3c8c4394a2 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemNavigationText.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemNavigationText.kt @@ -48,7 +48,7 @@ fun TangemNavigationText( modifier = modifier, color = navigationTextColor(role), style = navigationTextStyle(role), - textAlign = TextAlign.Center, + textAlign = TextAlign.Start, maxLines = maxLines, overflow = overflow, ) @@ -73,7 +73,7 @@ fun TangemNavigationText( modifier = modifier, color = navigationTextColor(role), style = navigationTextStyle(role), - textAlign = TextAlign.Center, + textAlign = TextAlign.Start, maxLines = maxLines, overflow = overflow, ) diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemTopNavigation.kt b/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemTopNavigation.kt index 97b85281f2..8be7187dcc 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemTopNavigation.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds2/topnavigation/TangemTopNavigation.kt @@ -53,7 +53,7 @@ private enum class SlotId { Start, Content, Group, End } * @param blurBackground Whether the fade behind the row should blur the content below. * @param startButton Leading slot. Typically a back button (see [TangemButton.Back]). * @param endButtonsGroup Optional pill-grouped secondary actions placed just before [endButton]. - * @param endButton Trailing slot. Typically a close button (see [TangemButton.Close]). + * @param endButton Trailing slot. Typically, a close button (see [TangemButton.Close]). * @param contentColumn Center slot. Place title/subtitle children here. */ @Suppress("LongMethod") @@ -88,7 +88,6 @@ fun TangemTopNavigation( blur = blurBackground, ) - val groupSpacing = 8.dp Layout( modifier = Modifier .fillMaxWidth() @@ -108,7 +107,7 @@ fun TangemTopNavigation( Column( modifier = Modifier - .padding(horizontal = 12.dp) + .padding(start = if (startButton != null) 12.dp else 0.dp, end = 12.dp) .layoutId(SlotId.Content), horizontalAlignment = when (contentAlign) { TangemTopNavigation.ContentAlign.Start -> Alignment.Start @@ -148,7 +147,7 @@ fun TangemTopNavigation( } }, ) { measurables, constraints -> - val groupSpacingPx = groupSpacing.roundToPx() + val groupSpacingPx = 8.dp.roundToPx() val totalWidth = constraints.maxWidth val startM = measurables.first { it.layoutId == SlotId.Start } @@ -161,13 +160,15 @@ fun TangemTopNavigation( val endP = endM.measure(slotConstraints) val groupP = groupM.measure(slotConstraints) + val endGap = if (endP.width > 0) groupSpacingPx else 0 + val groupOccupiedWidth = if (groupP.width > 0) endGap + groupP.width else 0 + val trailingWidth = endP.width + groupOccupiedWidth + val contentMaxWidth = when (contentAlign) { - // Symmetric band so the content can be visually centered within `totalWidth` - // without colliding with the start/end slots. TangemTopNavigation.ContentAlign.Center -> - (totalWidth - 2 * maxOf(startP.width, endP.width)).coerceAtLeast(0) + (totalWidth - 2 * maxOf(startP.width, trailingWidth)).coerceAtLeast(0) TangemTopNavigation.ContentAlign.Start -> - (totalWidth - startP.width - endP.width).coerceAtLeast(0) + (totalWidth - startP.width - trailingWidth).coerceAtLeast(0) } val contentP = contentM.measure(slotConstraints.copy(maxWidth = contentMaxWidth)) @@ -183,15 +184,14 @@ fun TangemTopNavigation( ((totalWidth - contentP.width) / 2) .coerceIn( startP.width, - (totalWidth - endP.width - contentP.width).coerceAtLeast(startP.width), + (totalWidth - trailingWidth - contentP.width).coerceAtLeast(startP.width), ) } contentP.placeRelative(x = contentX, y = centerY(contentP.height)) endP.placeRelative(x = totalWidth - endP.width, y = centerY(endP.height)) - // Group floats to the left of endButton with `groupSpacing` gap, overlaying the - // tail of the content band if necessary. - val groupX = (totalWidth - endP.width - groupSpacingPx - groupP.width) + + val groupX = (totalWidth - endP.width - endGap - groupP.width) .coerceAtLeast(0) groupP.placeRelative(x = groupX, y = centerY(groupP.height)) } diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/ds/topnavigation/TangemTopNavigationStory.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/ds/topnavigation/TangemTopNavigationStory.kt index be6e3d55f2..97dc84c5d5 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/ds/topnavigation/TangemTopNavigationStory.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/ds/topnavigation/TangemTopNavigationStory.kt @@ -49,12 +49,13 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.tangem.core.ui.components.haze.hazeSourceTangem -import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.ds2.button.Back import com.tangem.core.ui.ds2.button.Close +import com.tangem.core.ui.ds2.button.GroupEntry import com.tangem.core.ui.ds2.button.TangemButton import com.tangem.core.ui.ds2.topnavigation.TangemNavigationText import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation @@ -79,7 +80,7 @@ private const val PREVIEW_HEIGHT_DP = 220 // Match the production TangemTopNavigation's spring stiffness so the story animates identically. private val SlotAlphaSpec = spring(stiffness = Spring.StiffnessMediumLow) -private val SlotSizeSpec = spring(stiffness = Spring.StiffnessMediumLow) +private val SlotSizeSpec = spring(stiffness = Spring.StiffnessMediumLow) private val TitleEnterTransition = fadeIn(animationSpec = SlotAlphaSpec) private val TitleExitTransition = fadeOut(animationSpec = SlotAlphaSpec) private val SubtitleEnterTransition = @@ -257,42 +258,36 @@ private fun endGroupContent(endGroup: EndGroup): (@Composable RowScope.() -> Uni EndGroup.None -> null EndGroup.One -> { { - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_arrow_swap_horizontal_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_arrow_swap_horizontal_20, onClick = {}, ) } } EndGroup.Two -> { { - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_arrow_swap_horizontal_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_arrow_swap_horizontal_20, onClick = {}, ) - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_scan_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_scan_20, onClick = {}, ) } } EndGroup.Three -> { { - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_arrow_swap_horizontal_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_arrow_swap_horizontal_20, onClick = {}, ) - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_sign_usd_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_sign_usd_20, onClick = {}, ) - TangemButton( - variant = TangemButton.Variant.Ghost, - iconStart = TangemIconUM.Icon(Icons.ic_scan_20), + TangemButton.GroupEntry( + imageVector = Icons.ic_scan_20, onClick = {}, ) }