Updated on 2026-08-14
This commit is contained in:
commit
19df6fefae
194 changed files with 5193 additions and 1945 deletions
|
|
@ -83,12 +83,16 @@ fun TangemMessage(
|
|||
trailingContent = if (isIconLeading) null else icon,
|
||||
contentColor = contentColor,
|
||||
onCloseClick = messageUM.onCloseClick,
|
||||
buttons = {
|
||||
messageUM.buttonsUM.fastForEach { buttonUM ->
|
||||
TangemButton(
|
||||
buttonUM = buttonUM.tangemButtonUM,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
buttons = if (messageUM.buttonsUM.isEmpty()) {
|
||||
null
|
||||
} else {
|
||||
{
|
||||
messageUM.buttonsUM.fastForEach { buttonUM ->
|
||||
TangemButton(
|
||||
buttonUM = buttonUM.tangemButtonUM,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,19 +27,20 @@ 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.test.TokenElementsTestTags
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
|
||||
/**
|
||||
* UI model for header row component
|
||||
*
|
||||
* @param headerRowUM UI model for the header row
|
||||
* @param modifier Modifier for the composable
|
||||
* @param headerRowUM UI model for the header row
|
||||
* @param modifier Modifier for the composable
|
||||
* @param dragHandleModifier Modifier applied to the drag handle in the row's tail (e.g. a reorderable
|
||||
* drag-handle modifier). Defaults to [Modifier] for non-reorderable rows.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemHeaderRow(
|
||||
headerRowUM: TangemHeaderRowUM,
|
||||
modifier: Modifier = Modifier,
|
||||
reorderableState: ReorderableLazyListState? = null,
|
||||
dragHandleModifier: Modifier = Modifier,
|
||||
isBalanceHidden: Boolean = false,
|
||||
) {
|
||||
TangemHeaderRow(
|
||||
|
|
@ -48,7 +49,7 @@ fun TangemHeaderRow(
|
|||
title = headerRowUM.title,
|
||||
subtitle = headerRowUM.subtitle,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
reorderableState = reorderableState,
|
||||
dragHandleModifier = dragHandleModifier,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -129,7 +130,7 @@ fun TangemHeaderRow(
|
|||
subtitle: TextReference? = null,
|
||||
headTangemIconUM: TangemIconUM? = null,
|
||||
tailUM: TangemRowTailUM = TangemRowTailUM.Empty,
|
||||
reorderableState: ReorderableLazyListState? = null,
|
||||
dragHandleModifier: Modifier = Modifier,
|
||||
isEnabled: Boolean = false,
|
||||
onItemClick: (() -> Unit)? = null,
|
||||
) {
|
||||
|
|
@ -181,7 +182,7 @@ fun TangemHeaderRow(
|
|||
SpacerWMax()
|
||||
TangemRowTail(
|
||||
tangemRowTailUM = tailUM,
|
||||
reorderableState = reorderableState,
|
||||
dragHandleModifier = dragHandleModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,12 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.OrganizeTokensScreenTestTags
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.detectReorder
|
||||
|
||||
@Composable
|
||||
fun TangemRowTail(
|
||||
tangemRowTailUM: TangemRowTailUM,
|
||||
modifier: Modifier = Modifier,
|
||||
reorderableState: ReorderableLazyListState? = null,
|
||||
dragHandleModifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = tangemRowTailUM,
|
||||
|
|
@ -39,7 +37,7 @@ fun TangemRowTail(
|
|||
TangemRowTailUM.Empty -> Unit
|
||||
is TangemRowTailUM.Draggable -> DraggableImage(
|
||||
iconRes = animatedState.iconRes,
|
||||
reorderableState = reorderableState,
|
||||
dragHandleModifier = dragHandleModifier,
|
||||
modifier = innerModifier,
|
||||
)
|
||||
is TangemRowTailUM.Text -> ContentText(text = animatedState.text, modifier = innerModifier)
|
||||
|
|
@ -54,21 +52,11 @@ fun TangemRowTail(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun DraggableImage(
|
||||
@DrawableRes iconRes: Int,
|
||||
reorderableState: ReorderableLazyListState?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
private fun DraggableImage(@DrawableRes iconRes: Int, dragHandleModifier: Modifier, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(size = TangemTheme.dimens2.x6)
|
||||
.then(
|
||||
other = if (reorderableState != null) {
|
||||
Modifier.detectReorder(reorderableState)
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
.then(dragHandleModifier)
|
||||
.testTag(OrganizeTokensScreenTestTags.DRAGGABLE_IMAGE),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -21,24 +21,24 @@ import com.tangem.core.ui.extensions.clickableSingle
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
|
||||
/**
|
||||
* Composable function that represents a Tangem token row in a list.
|
||||
*
|
||||
* [Token Row](https://www.figma.com/design/RU7AIgwHtGdMfy83T5UOoR/Core-Library?node-id=8207-17583&t=k8dyaykorsNocGVq-4)
|
||||
*
|
||||
* @param tokenRowUM The user model containing the data for the token row.
|
||||
* @param isBalanceHidden A boolean indicating whether the balance should be hidden.
|
||||
* @param reorderableState The state of the reorderable lazy list, if applicable.
|
||||
* @param modifier The modifier to be applied to the row.
|
||||
* @param tokenRowUM The user model containing the data for the token row.
|
||||
* @param isBalanceHidden A boolean indicating whether the balance should be hidden.
|
||||
* @param dragHandleModifier Modifier applied to the drag handle in the row's tail (e.g. a reorderable
|
||||
* drag-handle modifier). Defaults to [Modifier] for non-reorderable rows.
|
||||
* @param modifier The modifier to be applied to the row.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemTokenRow(
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
isBalanceHidden: Boolean,
|
||||
reorderableState: ReorderableLazyListState?,
|
||||
modifier: Modifier = Modifier,
|
||||
dragHandleModifier: Modifier = Modifier,
|
||||
) {
|
||||
TangemRowContainer(
|
||||
content = {
|
||||
|
|
@ -91,7 +91,7 @@ fun TangemTokenRow(
|
|||
|
||||
TangemRowTail(
|
||||
tangemRowTailUM = tokenRowUM.tailUM,
|
||||
reorderableState = reorderableState,
|
||||
dragHandleModifier = dragHandleModifier,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
|
|
@ -116,18 +116,19 @@ fun TangemTokenRow(
|
|||
* [Token Row](https://www.figma.com/design/RU7AIgwHtGdMfy83T5UOoR/Core-Library?node-id=8207-17583&t=k8dyaykorsNocGVq-4)
|
||||
*
|
||||
* @param tokenRowUM The user model containing the data for the token row.
|
||||
* @param headComponent The composable function representing the head component.
|
||||
* @param titleComponent The composable function representing the title component.
|
||||
* @param isBalanceHidden A boolean indicating whether the balance should be hidden.
|
||||
* @param reorderableState The state of the reorderable lazy list, if applicable.
|
||||
* @param modifier The modifier to be applied to the row.
|
||||
* @param headComponent The composable function representing the head component.
|
||||
* @param titleComponent The composable function representing the title component.
|
||||
* @param isBalanceHidden A boolean indicating whether the balance should be hidden.
|
||||
* @param dragHandleModifier Modifier applied to the drag handle in the row's tail (e.g. a reorderable
|
||||
* drag-handle modifier). Defaults to [Modifier] for non-reorderable rows.
|
||||
* @param modifier The modifier to be applied to the row.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemTokenRow(
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
isBalanceHidden: Boolean,
|
||||
reorderableState: ReorderableLazyListState?,
|
||||
modifier: Modifier = Modifier,
|
||||
dragHandleModifier: Modifier = Modifier,
|
||||
headComponent: @Composable (Modifier) -> Unit,
|
||||
titleComponent: @Composable (Modifier) -> Unit,
|
||||
) {
|
||||
|
|
@ -190,7 +191,7 @@ fun TangemTokenRow(
|
|||
|
||||
TangemRowTail(
|
||||
tangemRowTailUM = tokenRowUM.tailUM,
|
||||
reorderableState = reorderableState,
|
||||
dragHandleModifier = dragHandleModifier,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
|
|
@ -210,7 +211,6 @@ private fun TangemTokenRow_Preview(
|
|||
TangemTokenRow(
|
||||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = false,
|
||||
reorderableState = null,
|
||||
modifier = Modifier.background(TangemTheme.colors2.surface.level1),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import kotlinx.coroutines.flow.drop
|
|||
import kotlin.math.abs
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
private const val LIST_FLING_DAMPING = 0.1f
|
||||
|
||||
/**
|
||||
* A scroll behavior for a collapsing top app bar that collapses when scrolling up and expands when scrolling down.
|
||||
* When the user stops scrolling, the app bar will settle to either fully collapsed or fully expanded state
|
||||
|
|
@ -176,7 +178,8 @@ private fun exitUntilCollapsedScrollBehavior(
|
|||
}
|
||||
}
|
||||
|
||||
return Velocity(0f, available.y - remainingVelocity)
|
||||
val passedVelocity = remainingVelocity * LIST_FLING_DAMPING
|
||||
return Velocity(0f, available.y - passedVelocity)
|
||||
}
|
||||
|
||||
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.NonRestartableComposable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
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
|
||||
import com.tangem.core.ui.test.TopNavigationTestTags
|
||||
|
||||
|
|
@ -16,7 +17,8 @@ fun TangemButton.Back(modifier: Modifier = Modifier, onClick: () -> Unit) {
|
|||
TangemButton(
|
||||
modifier = modifier.testTag(TopNavigationTestTags.BACK_BUTTON),
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
|
@ -27,7 +29,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)
|
||||
}
|
||||
|
|
@ -1,27 +1,13 @@
|
|||
package com.tangem.core.ui.ds2.button
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.ExitTransition
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.expandHorizontally
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkHorizontally
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.TextAutoSize
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
|
|
@ -38,11 +24,7 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoader
|
||||
import com.tangem.core.ui.extensions.ColorReference2
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.conditionalCompose
|
||||
import com.tangem.core.ui.extensions.rememberLastNonNull
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
/**
|
||||
|
|
@ -168,6 +150,10 @@ private fun ContentRow(
|
|||
maxLines = 1,
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = TangemTheme.typography3.caption.medium.fontSize,
|
||||
maxFontSize = TangemTheme.typography3.body.medium.fontSize,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
|
|
@ -14,7 +15,7 @@ import androidx.compose.ui.graphics.Brush
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -24,25 +25,17 @@ import kotlin.math.cos
|
|||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* Design-system rectangle shimmer placeholder.
|
||||
* Design-system v2 shimmer placeholder — a rounded rectangle with a sweeping highlight.
|
||||
*
|
||||
* A rounded rectangle painted with `bg.opaque.secondary`. A tilted band sweeps across it where
|
||||
* the base color's alpha is gradually dimmed toward the center of the band and restored at the
|
||||
* edges, producing a soft "blade" highlight passing through the placeholder. The alpha profile
|
||||
* matches [com.tangem.core.ui.components.text.BladeAnimation].
|
||||
*
|
||||
* Cycle: 1.5s hold → 0.8s linear sweep → restart.
|
||||
*
|
||||
* Version 1.0
|
||||
* [Figma](https://www.figma.com/design/AsnJ5CPHib4Qxw12gszjMS/%F0%9F%92%A0-DS-Components?node-id=3398-625&p=f&m=dev)
|
||||
*
|
||||
* Sizing is the caller's responsibility — set width and height via [modifier].
|
||||
* For a placeholder sized after a typography line, use the [TangemShimmer] text overload instead.
|
||||
*
|
||||
* @param modifier Modifier applied to the shimmer's root.
|
||||
* @param modifier Modifier applied to the shimmer's root. Set the width and height here.
|
||||
* @param radius Corner radius of the rectangle.
|
||||
*/
|
||||
@Composable
|
||||
fun RectangleShimmer(modifier: Modifier = Modifier, radius: Dp = 6.dp) {
|
||||
fun TangemShimmer(modifier: Modifier = Modifier, radius: Dp = TangemShimmer.DefaultRadius) {
|
||||
val baseColor = TangemTheme.colors3.bg.opaque.secondary
|
||||
val progress = LocalTangemShimmerProgress.current ?: rememberShimmerProgressInstance()
|
||||
val colorStops = remember(baseColor) { buildColorStops(baseColor) }
|
||||
|
|
@ -77,63 +70,76 @@ fun RectangleShimmer(modifier: Modifier = Modifier, radius: Dp = 6.dp) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Text-sized shimmer placeholder. Sizes itself to the bounding box of the [text] measured in the
|
||||
* typography preset selected by [style], plus the preset's vertical padding (top + bottom).
|
||||
* Text-line shimmer placeholder, sized and styled after the typography line described by [style].
|
||||
*
|
||||
* @param text Text used to determine the shimmer's size. Not drawn.
|
||||
* @param style Typography preset — drives both the measurement style and the vertical padding.
|
||||
* @param radius Corner radius of the rectangle.
|
||||
* [Figma](https://www.figma.com/design/AsnJ5CPHib4Qxw12gszjMS/%F0%9F%92%A0-DS-Components?node-id=3398-625&p=f&m=dev)
|
||||
*
|
||||
* @param style A [TangemTheme.typography3] style (e.g. `TangemTheme.typography3.body.medium`) the
|
||||
* placeholder is sized after. Unrecognized styles fall back to `body.medium`.
|
||||
* @param modifier Modifier applied to the shimmer's root.
|
||||
* @param textAlign Horizontal position of the block within the parent width.
|
||||
*/
|
||||
@Composable
|
||||
fun TextShimmer(text: String, style: TextShimmerStyle, radius: Dp, modifier: Modifier = Modifier) {
|
||||
val textStyle = style.toTextStyle()
|
||||
val measurer = rememberTextMeasurer()
|
||||
val density = LocalDensity.current
|
||||
val (widthDp, heightDp) = remember(text, textStyle, measurer, density) {
|
||||
val measured = measurer.measure(text = text, style = textStyle)
|
||||
with(density) { measured.size.width.toDp() to measured.size.height.toDp() }
|
||||
fun TangemShimmer(style: TextStyle, modifier: Modifier = Modifier, textAlign: TextAlign = TextAlign.Start) {
|
||||
val preset = TangemShimmer.TextPreset.forStyle(style)
|
||||
val lineHeightDp = with(LocalDensity.current) { style.lineHeight.toDp() }
|
||||
val alignment = when (textAlign) {
|
||||
TextAlign.Center -> Alignment.Center
|
||||
TextAlign.End -> Alignment.CenterEnd
|
||||
else -> Alignment.CenterStart
|
||||
}
|
||||
|
||||
RectangleShimmer(
|
||||
modifier = modifier.size(
|
||||
width = widthDp,
|
||||
height = heightDp + style.verticalPadding * 2,
|
||||
),
|
||||
radius = radius,
|
||||
)
|
||||
Box(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
contentAlignment = alignment,
|
||||
) {
|
||||
TangemShimmer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(preset.widthFraction)
|
||||
.height(lineHeightDp)
|
||||
.padding(vertical = preset.verticalPadding),
|
||||
radius = preset.radius,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Public API namespace for [TangemShimmer]. */
|
||||
object TangemShimmer {
|
||||
|
||||
/** Default corner radius of the rectangle shimmer. */
|
||||
val DefaultRadius: Dp = 6.dp
|
||||
|
||||
/** Per-typography sizing for the [TangemShimmer] text overload. */
|
||||
internal enum class TextPreset(val widthFraction: Float, val verticalPadding: Dp, val radius: Dp) {
|
||||
Display(widthFraction = 0.5f, verticalPadding = 4.dp, radius = 12.dp),
|
||||
HeadingMedium(widthFraction = 0.7f, verticalPadding = 2.dp, radius = 8.dp),
|
||||
HeadingSmall(widthFraction = 0.6f, verticalPadding = 2.dp, radius = 16.dp),
|
||||
Body(widthFraction = 0.5f, verticalPadding = 2.dp, radius = 16.dp),
|
||||
Subheading(widthFraction = 0.4f, verticalPadding = 2.dp, radius = 16.dp),
|
||||
Caption(widthFraction = 0.3f, verticalPadding = 2.dp, radius = 16.dp),
|
||||
;
|
||||
|
||||
companion object {
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun forStyle(style: TextStyle): TextPreset {
|
||||
val typography = TangemTheme.typography3
|
||||
return when (style) {
|
||||
typography.display.medium -> Display
|
||||
typography.heading.medium -> HeadingMedium
|
||||
typography.heading.small -> HeadingSmall
|
||||
typography.subheading.medium -> Subheading
|
||||
typography.caption.medium -> Caption
|
||||
else -> Body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Typography preset for [TextShimmer]. Each preset maps to a [TangemTheme.typography3] style
|
||||
* and contributes additional [verticalPadding] applied to both top and bottom — the shimmer
|
||||
* block ends up `2 * verticalPadding` taller than the raw measured text.
|
||||
*/
|
||||
enum class TextShimmerStyle(val verticalPadding: Dp) {
|
||||
DISPLAY(verticalPadding = 4.dp),
|
||||
HEADING_MEDIUM(verticalPadding = 2.dp),
|
||||
HEADING_SMALL(verticalPadding = 2.dp),
|
||||
BODY(verticalPadding = 2.dp),
|
||||
SUBHEADING(verticalPadding = 2.dp),
|
||||
CAPTION(verticalPadding = 2.dp),
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun TextShimmerStyle.toTextStyle(): TextStyle = when (this) {
|
||||
TextShimmerStyle.DISPLAY -> TangemTheme.typography3.display.medium
|
||||
TextShimmerStyle.HEADING_MEDIUM -> TangemTheme.typography3.heading.medium
|
||||
TextShimmerStyle.HEADING_SMALL -> TangemTheme.typography3.heading.small
|
||||
TextShimmerStyle.BODY -> TangemTheme.typography3.body.medium
|
||||
TextShimmerStyle.SUBHEADING -> TangemTheme.typography3.subheading.medium
|
||||
TextShimmerStyle.CAPTION -> TangemTheme.typography3.caption.medium
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps [content] so every [RectangleShimmer] / [TextShimmer] inside reuses a single shimmer
|
||||
* animation driver. Without this provider each shimmer creates its own
|
||||
* [rememberInfiniteTransition] — that scales poorly in lists and lets sweeps drift out of phase.
|
||||
* Safe to nest; safe to omit (each shimmer falls back to its own driver).
|
||||
* Wraps [content] so every [TangemShimmer] inside shares a single, in-phase animation driver —
|
||||
* use it around lists of shimmers. Safe to nest; safe to omit.
|
||||
*/
|
||||
@Composable
|
||||
fun ProvideTangemShimmer(content: @Composable () -> Unit) {
|
||||
|
|
@ -198,24 +204,16 @@ private fun TangemShimmerPreview() {
|
|||
.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
RectangleShimmer(
|
||||
TangemShimmer(
|
||||
modifier = Modifier.size(width = 200.dp, height = 24.dp),
|
||||
radius = 6.dp,
|
||||
)
|
||||
RectangleShimmer(
|
||||
TangemShimmer(
|
||||
modifier = Modifier.size(width = 120.dp, height = 16.dp),
|
||||
radius = 4.dp,
|
||||
)
|
||||
TextShimmer(
|
||||
text = "Account balance",
|
||||
style = TextShimmerStyle.BODY,
|
||||
radius = 4.dp,
|
||||
)
|
||||
TextShimmer(
|
||||
text = "$12,345.67",
|
||||
style = TextShimmerStyle.HEADING_MEDIUM,
|
||||
radius = 6.dp,
|
||||
)
|
||||
TangemShimmer(style = TangemTheme.typography3.body.medium)
|
||||
TangemShimmer(style = TangemTheme.typography3.heading.medium)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ fun TangemSurface(
|
|||
}
|
||||
|
||||
if (onClick != null) {
|
||||
CompositionLocalProvider(LocalRippleConfiguration provides tangemSurfaceRipple()) {
|
||||
CompositionLocalProvider(LocalRippleConfiguration provides tangemSurfaceRipple(color)) {
|
||||
surface()
|
||||
}
|
||||
} else {
|
||||
|
|
@ -117,14 +117,17 @@ fun TangemSurface(
|
|||
* `isAlphaContentClip`) to avoid the dark blur bleeding through the surface.
|
||||
*/
|
||||
@Composable
|
||||
private fun Modifier.materialShadow(shape: Shape, radius: Dp): Modifier = softLayerShadow(
|
||||
radius = radius,
|
||||
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, radius: Dp): Modifier {
|
||||
val isBlurEnabled = LocalHazeState.current.blurEnabled
|
||||
return softLayerShadow(
|
||||
radius = radius,
|
||||
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
|
||||
|
|
@ -193,8 +196,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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import androidx.compose.foundation.text.selection.TextSelectionColors
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.*
|
||||
import com.tangem.core.ui.components.haze.ProvideHaze
|
||||
import com.tangem.core.ui.ds2.shimmers.ProvideTangemShimmer
|
||||
import com.tangem.core.ui.res.generated.TangemTypography3
|
||||
import com.tangem.core.ui.res.generated.darkColors3
|
||||
import com.tangem.core.ui.res.generated.lightColors3
|
||||
|
|
@ -48,8 +49,10 @@ fun TangemThemeRedesign(content: @Composable () -> Unit) {
|
|||
CompositionLocalProvider(
|
||||
LocalTextSelectionColors provides TangemTextSelectionColors2,
|
||||
) {
|
||||
ProvideHaze {
|
||||
content()
|
||||
ProvideTangemShimmer {
|
||||
ProvideHaze {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ package com.tangem.core.ui.test
|
|||
object BuyTokenScreenTestTags {
|
||||
const val LAZY_LIST = "BUY_TOKEN_SCREEN_LAZY_LIST"
|
||||
const val LAZY_LIST_ITEM = "BUY_TOKEN_SCREEN_LAZY_LIST_ITEM"
|
||||
const val WALLET_TAB = "BUY_TOKEN_SCREEN_WALLET_TAB"
|
||||
}
|
||||
|
|
@ -5,4 +5,5 @@ object DetailsScreenTestTags {
|
|||
const val SCREEN_ITEM = "DETAILS_SCREEN_ITEM"
|
||||
const val VERSION_NAME = "DETAILS_SCREEN_VERSION_NAME"
|
||||
const val USER_WALLET_ITEM = "DETAILS_SCREEN_USER_WALLET_ITEM"
|
||||
const val ADD_WALLET_BUTTON = "DETAILS_SCREEN_ADD_WALLET_BUTTON"
|
||||
}
|
||||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
|
|
|
|||
21
core/ui/src/main/res/drawable/ic_gonka_22.xml
Normal file
21
core/ui/src/main/res/drawable/ic_gonka_22.xml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="44"
|
||||
android:viewportHeight="44">
|
||||
<path
|
||||
android:pathData="M22.0779,0.0009C22.2017,6.0786 22.4682,12.1564 22.8218,18.234C23.2874,26.2385 26.7009,34.2436 29.0827,42.2481C29.1354,42.4251 29.185,42.6029 29.2367,42.7799C26.9701,43.5691 24.5355,44 22,44C19.4649,44 17.0305,43.5698 14.7642,42.7808C14.816,42.6034 14.8663,42.4255 14.9191,42.2481C17.3009,34.2436 20.7144,26.2385 21.18,18.234C21.5336,12.1564 21.7992,6.0786 21.923,0.0009C21.9487,0.0008 21.9743,0 22,0C22.026,0 22.0519,0.0008 22.0779,0.0009Z"
|
||||
android:fillColor="#000000" />
|
||||
<path
|
||||
android:pathData="M20.7262,21.2364C19.4639,28.1647 15.6505,35.0935 12.8718,42.0216C12.0526,41.6475 11.2603,41.2248 10.4987,40.7568C14.3095,34.2502 19.1923,27.7431 20.7262,21.2364Z"
|
||||
android:fillColor="#000000" />
|
||||
<path
|
||||
android:pathData="M23.2747,21.2364C24.8085,27.7426 29.6898,34.2498 33.5004,40.7559C32.739,41.2237 31.9472,41.6467 31.1282,42.0208C28.3495,35.093 24.5369,28.1642 23.2747,21.2364Z"
|
||||
android:fillColor="#000000" />
|
||||
<path
|
||||
android:pathData="M20.6062,0.0448C20.5973,6.1451 20.5901,12.2455 20.5641,18.3459C20.5354,25.059 13.5075,31.7743 7.4363,38.4875C2.8764,34.4566 0,28.5647 0,22C0,10.3179 9.1054,0.7638 20.6062,0.0448Z"
|
||||
android:fillColor="#000000" />
|
||||
<path
|
||||
android:pathData="M23.3938,0.0448C34.8946,0.7638 44,10.3179 44,22C44,28.5649 41.123,34.4565 36.5628,38.4875C30.4919,31.7747 23.4655,25.0585 23.4368,18.3459C23.4108,12.2455 23.4027,6.1451 23.3938,0.0448Z"
|
||||
android:fillColor="#000000" />
|
||||
</vector>
|
||||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="32" android:viewportWidth="32" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#EBEBEB" android:pathData="M16,23.697L22.663,27.802C23.715,28.45 25.011,27.488 24.733,26.268L22.964,18.528L28.852,13.321C29.78,12.5 29.284,10.944 28.061,10.838L20.31,10.167L17.278,2.864C16.799,1.712 15.201,1.712 14.722,2.864L11.69,10.167L3.939,10.838C2.716,10.944 2.22,12.5 3.148,13.321L9.036,18.528L7.267,26.268C6.988,27.488 8.285,28.45 9.336,27.802L16,23.697Z"/>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="128dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="8dp"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
<!--
|
||||
~ Copyright (C) 2026 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
|
|
|
|||
13
core/ui/src/main/res/drawable/img_gonka_22.xml
Normal file
13
core/ui/src/main/res/drawable/img_gonka_22.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="44"
|
||||
android:viewportHeight="44">
|
||||
<path
|
||||
android:pathData="M22,0C34.15,0 44,9.85 44,22C44,34.15 34.15,44 22,44C9.85,44 0,34.15 0,22C0,9.85 9.85,0 22,0Z"
|
||||
android:fillColor="#242424" />
|
||||
<path
|
||||
android:pathData="M22,0C34.15,0 44,9.85 44,22C44,34.15 34.15,44 22,44C9.85,44 0,34.15 0,22C0,9.85 9.85,0 22,0ZM22.0779,0.0009C22.2017,6.0786 22.4682,12.1564 22.8218,18.234C23.2874,26.2385 26.7009,34.2436 29.0827,42.2481C29.1354,42.4251 29.185,42.6029 29.2367,42.7799C26.9701,43.5691 24.5355,44 22,44C19.4649,44 17.0305,43.5698 14.7642,42.7808C14.816,42.6034 14.8663,42.4255 14.9191,42.2481C17.3009,34.2436 20.7144,26.2385 21.18,18.234C21.5336,12.1564 21.7992,6.0786 21.923,0.0009C21.9487,0.0008 21.9743,0 22,0C22.026,0 22.0519,0.0008 22.0779,0.0009ZM20.7262,21.2364C19.4639,28.1647 15.6505,35.0935 12.8718,42.0216C12.0526,41.6475 11.2603,41.2248 10.4987,40.7568C14.3095,34.2502 19.1923,27.7431 20.7262,21.2364ZM23.2747,21.2364C24.8085,27.7426 29.6898,34.2498 33.5004,40.7559C32.739,41.2237 31.9472,41.6467 31.1282,42.0208C28.3495,35.093 24.5369,28.1642 23.2747,21.2364ZM20.6062,0.0448C20.5973,6.1451 20.5901,12.2455 20.5641,18.3459C20.5354,25.059 13.5075,31.7743 7.4363,38.4875C2.8764,34.4566 0,28.5647 0,22C0,10.3179 9.1054,0.7638 20.6062,0.0448ZM23.3938,0.0448C34.8946,0.7638 44,10.3179 44,22C44,28.5649 41.123,34.4565 36.5628,38.4875C30.4919,31.7747 23.4655,25.0585 23.4368,18.3459C23.4108,12.2455 23.4027,6.1451 23.3938,0.0448Z"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="evenOdd" />
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue