Updated on 2026-08-14

This commit is contained in:
Tangem 2025-02-28 13:42:54 +05:00
commit b96d11cea7
34 changed files with 183 additions and 402 deletions

View file

@ -5,7 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

View file

@ -1,7 +1,7 @@
package com.tangem.core.ui.components
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

View file

@ -5,7 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

View file

@ -2,8 +2,8 @@ package com.tangem.core.ui.components
import androidx.annotation.FloatRange
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
@ -27,13 +27,13 @@ fun ResizableText(
maxLines: Int = Int.MAX_VALUE,
style: TextStyle = LocalTextStyle.current,
) {
val fontSizeValue = remember { mutableStateOf(fontSizeRange.max.value) }
val fontSizeValue = remember { mutableFloatStateOf(fontSizeRange.max.value) }
val readyToDraw = remember { mutableStateOf(false) }
val textState = remember { mutableStateOf(text) }
if (textState.value != text) {
readyToDraw.value = false
fontSizeValue.value = fontSizeRange.max.value
fontSizeValue.floatValue = fontSizeRange.max.value
textState.value = text
}
@ -41,18 +41,18 @@ fun ResizableText(
text = text,
modifier = modifier.drawWithContent { if (readyToDraw.value) drawContent() },
color = color,
fontSize = fontSizeValue.value.sp,
fontSize = fontSizeValue.floatValue.sp,
overflow = overflow,
softWrap = false,
maxLines = maxLines,
onTextLayout = {
if (it.hasVisualOverflow) {
val nextFontSizeValue = fontSizeValue.value - fontSizeRange.step.value
val nextFontSizeValue = fontSizeValue.floatValue - fontSizeRange.step.value
if (nextFontSizeValue <= fontSizeRange.min.value) {
fontSizeValue.value = fontSizeRange.min.value
fontSizeValue.floatValue = fontSizeRange.min.value
readyToDraw.value = true
} else {
fontSizeValue.value = nextFontSizeValue * COEFFICIENT
fontSizeValue.floatValue = nextFontSizeValue * COEFFICIENT
}
} else {
readyToDraw.value = true

View file

@ -5,8 +5,8 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

View file

@ -14,7 +14,8 @@ import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -119,7 +120,7 @@ private fun TangemTextField(
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: TangemTextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
colors: TextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
size: TangemTextFieldSize = TangemTextFieldSize.Default,
onClear: () -> Unit = { onValueChange(TextFieldValue()) },
) {
@ -230,7 +231,7 @@ private fun TangemTextFieldWithIcon(
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: TangemTextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
colors: TextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
size: TangemTextFieldSize = TangemTextFieldSize.Default,
onIconClick: () -> Unit = {},
) {
@ -326,154 +327,139 @@ private fun TangemTextFieldSize.toShape(): Shape = when (this) {
}
object TangemTextFieldsDefault {
val defaultTextFieldColors: TangemTextFieldColors
@Composable @Stable get() = TangemTextFieldColors(
textColor = TangemTheme.colors.text.primary1,
val defaultTextFieldColors: TextFieldColors
@Composable @Stable get() = TextFieldColors(
focusedTextColor = TangemTheme.colors.text.primary1,
errorTextColor = TangemTheme.colors.text.primary1,
unfocusedTextColor = TangemTheme.colors.text.primary1,
disabledTextColor = TangemTheme.colors.text.disabled,
backgroundColor = Color.Transparent,
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
errorContainerColor = Color.Transparent,
cursorColor = TangemTheme.colors.icon.primary1,
errorCursorColor = TangemTheme.colors.icon.warning,
focusedIndicatorColor = TangemTheme.colors.icon.primary1,
unfocusedIndicatorColor = TangemTheme.colors.stroke.secondary,
disabledIndicatorColor = TangemTheme.colors.stroke.secondary,
errorIndicatorColor = TangemTheme.colors.icon.warning,
leadingIconColor = TangemTheme.colors.icon.informative,
focusedLeadingIconColor = TangemTheme.colors.icon.informative,
unfocusedLeadingIconColor = TangemTheme.colors.icon.informative,
disabledLeadingIconColor = Color.Transparent,
errorLeadingIconColor = TangemTheme.colors.icon.warning,
trailingIconColor = TangemTheme.colors.icon.informative,
focusedTrailingIconColor = TangemTheme.colors.icon.informative,
unfocusedTrailingIconColor = TangemTheme.colors.icon.informative,
disabledTrailingIconColor = Color.Transparent,
errorTrailingIconColor = TangemTheme.colors.icon.warning,
focusedLabelColor = TangemTheme.colors.text.primary1,
unfocusedLabelColor = TangemTheme.colors.text.secondary,
disabledLabelColor = TangemTheme.colors.text.disabled,
errorLabelColor = TangemTheme.colors.icon.warning,
placeholderColor = TangemTheme.colors.text.secondary,
focusedPlaceholderColor = TangemTheme.colors.text.secondary,
errorPlaceholderColor = TangemTheme.colors.text.secondary,
unfocusedPlaceholderColor = TangemTheme.colors.text.secondary,
disabledPlaceholderColor = TangemTheme.colors.text.disabled,
captionColor = TangemTheme.colors.text.tertiary,
disabledCaptionColor = TangemTheme.colors.text.disabled,
errorCaptionColor = TangemTheme.colors.icon.warning,
focusedSupportingTextColor = TangemTheme.colors.text.tertiary,
unfocusedSupportingTextColor = TangemTheme.colors.text.tertiary,
disabledSupportingTextColor = TangemTheme.colors.text.disabled,
errorSupportingTextColor = TangemTheme.colors.icon.warning,
textSelectionColors = LocalTextSelectionColors.current,
focusedPrefixColor = Color.Transparent,
unfocusedPrefixColor = Color.Transparent,
disabledPrefixColor = Color.Transparent,
errorPrefixColor = Color.Transparent,
focusedSuffixColor = Color.Transparent,
unfocusedSuffixColor = Color.Transparent,
disabledSuffixColor = Color.Transparent,
errorSuffixColor = Color.Transparent,
)
}
@Immutable
data class TangemTextFieldColors(
private val textColor: Color,
private val disabledTextColor: Color,
private val cursorColor: Color,
private val errorCursorColor: Color,
private val focusedIndicatorColor: Color,
private val unfocusedIndicatorColor: Color,
private val errorIndicatorColor: Color,
private val disabledIndicatorColor: Color,
private val leadingIconColor: Color,
private val disabledLeadingIconColor: Color,
private val errorLeadingIconColor: Color,
private val trailingIconColor: Color,
private val disabledTrailingIconColor: Color,
private val errorTrailingIconColor: Color,
private val backgroundColor: Color,
private val focusedLabelColor: Color,
private val unfocusedLabelColor: Color,
private val disabledLabelColor: Color,
private val errorLabelColor: Color,
private val placeholderColor: Color,
private val disabledPlaceholderColor: Color,
private val captionColor: Color,
private val disabledCaptionColor: Color,
private val errorCaptionColor: Color,
) : TextFieldColors {
@Composable
fun TextFieldColors.leadingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledLeadingIconColor
isError -> errorLeadingIconColor
else -> focusedLeadingIconColor
},
)
}
@Composable
override fun leadingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledLeadingIconColor
isError -> errorLeadingIconColor
else -> leadingIconColor
},
@Composable
fun TextFieldColors.trailingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledTrailingIconColor
isError -> errorTrailingIconColor
else -> focusedTrailingIconColor
},
)
}
@Composable
fun TextFieldColors.indicatorColor(
enabled: Boolean,
isError: Boolean,
interactionSource: InteractionSource,
): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledIndicatorColor
isError -> errorIndicatorColor
focused -> focusedIndicatorColor
else -> unfocusedIndicatorColor
}
return if (enabled) {
animateColorAsState(
targetValue = targetValue,
animationSpec = tween(durationMillis = 120),
label = "IndicatorColor",
)
} else {
rememberUpdatedState(targetValue)
}
}
@Composable
override fun trailingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledTrailingIconColor
isError -> errorTrailingIconColor
else -> trailingIconColor
},
)
@Composable
fun TextFieldColors.placeholderColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) focusedPlaceholderColor else disabledPlaceholderColor)
}
@Composable
fun TextFieldColors.labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledLabelColor
error -> errorLabelColor
focused -> focusedLabelColor
else -> unfocusedLabelColor
}
return rememberUpdatedState(targetValue)
}
@Composable
override fun indicatorColor(
enabled: Boolean,
isError: Boolean,
interactionSource: InteractionSource,
): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
@Composable
fun TextFieldColors.textColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) focusedTextColor else disabledTextColor)
}
val targetValue = when {
!enabled -> disabledIndicatorColor
isError -> errorIndicatorColor
focused -> focusedIndicatorColor
else -> unfocusedIndicatorColor
}
return if (enabled) {
animateColorAsState(
targetValue = targetValue,
animationSpec = tween(durationMillis = 120),
label = "IndicatorColor",
)
} else {
rememberUpdatedState(targetValue)
}
}
@Composable
fun TextFieldColors.cursorColor(isError: Boolean): State<Color> {
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
}
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(backgroundColor)
}
@Composable
override fun placeholderColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) placeholderColor else disabledPlaceholderColor)
}
@Composable
override fun labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledLabelColor
error -> errorLabelColor
focused -> focusedLabelColor
else -> unfocusedLabelColor
}
return rememberUpdatedState(targetValue)
}
@Composable
override fun textColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) textColor else disabledTextColor)
}
@Composable
override fun cursorColor(isError: Boolean): State<Color> {
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
}
@Suppress("TopLevelComposableFunctions")
@Composable
fun captionColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
newValue = when {
!enabled -> disabledCaptionColor
isError -> errorCaptionColor
else -> captionColor
},
)
}
@Suppress("TopLevelComposableFunctions")
@Composable
fun TextFieldColors.captionColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
newValue = when {
!enabled -> disabledSupportingTextColor
isError -> errorSupportingTextColor
else -> focusedSupportingTextColor
},
)
}
// endregion Defaults

View file

@ -7,7 +7,10 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -105,7 +108,7 @@ private fun CollapsedSearchView(
.padding(TangemTheme.dimens.spacing16)
.size(TangemTheme.dimens.size24)
.clickable { onBackClick() },
tint = MaterialTheme.colors.onPrimary,
tint = TangemTheme.colors.icon.primary1,
)
Column(
verticalArrangement = Arrangement.Center,
@ -216,7 +219,8 @@ private fun ExpandedSearchView(
onDone = { focusManager.clearFocus() },
),
colors = TangemTextFieldsDefault.defaultTextFieldColors.copy(
placeholderColor = TangemTheme.colors.text.disabled,
focusedPlaceholderColor = TangemTheme.colors.text.disabled,
unfocusedPlaceholderColor = TangemTheme.colors.text.disabled,
cursorColor = TangemTheme.colors.text.tertiary,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,

View file

@ -3,7 +3,7 @@ package com.tangem.core.ui.components.audits
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier

View file

@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind

View file

@ -3,8 +3,8 @@ package com.tangem.core.ui.components.rows
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,19C6,19.53 6.211,20.039 6.586,20.414C6.961,20.789 7.47,21 8,21H16C16.53,21 17.039,20.789 17.414,20.414C17.789,20.039 18,19.53 18,19V7H6V19ZM8,9H16V19H8V9ZM15.5,4L14.5,3H9.5L8.5,4H5V6H19V4H15.5Z"
android:fillColor="#1E1E1E"/>
</vector>