Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-21 12:10:31 +03:00
commit d73ab1aee6
9 changed files with 1113 additions and 0 deletions

View file

@ -0,0 +1,60 @@
package com.tangem.core.ui.components.fields
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.input.VisualTransformation
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* Simple text field with placeholder
*/
@Composable
fun SimpleTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
placeholder: TextReference? = null,
singleLine: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
color: Color = TangemTheme.colors.text.primary1,
readOnly: Boolean = false,
) {
val focusRequester = remember { FocusRequester() }
BasicTextField(
value = value,
onValueChange = onValueChange,
textStyle = TangemTheme.typography.body2.copy(color = color),
cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
singleLine = singleLine,
readOnly = readOnly,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
decorationBox = { textValue ->
Box {
if (value.isBlank() && placeholder != null) {
Text(
text = placeholder.resolveReference(),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.disabled,
modifier = Modifier,
)
}
textValue()
}
},
modifier = modifier
.focusRequester(focusRequester),
)
}

View file

@ -0,0 +1,152 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* [InputRowDefault](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-807&mode=design&t=86eKp9izWxUvmoCq-4)
*
* @param title title reference
* @param text primary text reference
* @param modifier modifier
* @param titleColor title color
* @param textColor text color
* @param iconRes action icon
* @param iconTint action icon tint
* @param onIconClick click on action icon
* @param showDivider show divider
* @see [InputRowEnter] for editable version
*/
@Composable
fun InputRowDefault(
title: TextReference,
text: TextReference,
modifier: Modifier = Modifier,
titleColor: Color = TangemTheme.colors.text.secondary,
textColor: Color = TangemTheme.colors.text.primary1,
iconRes: Int? = null,
iconTint: Color = TangemTheme.colors.icon.informative,
onIconClick: (() -> Unit)? = null,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Column(
modifier = Modifier
.weight(1f),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
Text(
text = text.resolveReference(),
style = TangemTheme.typography.body2,
color = textColor,
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
)
}
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = iconTint,
modifier = Modifier
.padding(
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
) { onIconClick?.invoke() },
)
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowDefaultPreview_Light(
@PreviewParameter(InputRowDefaultPreviewDataProvider::class) data: InputRowDefaultPreviewData,
) {
TangemTheme {
InputRowDefault(
title = TextReference.Str(data.title),
text = TextReference.Str(data.text),
iconRes = data.iconRes,
showDivider = data.showDivider,
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
@Preview
@Composable
private fun InputRowDefaultPreview_Dark(
@PreviewParameter(InputRowDefaultPreviewDataProvider::class) data: InputRowDefaultPreviewData,
) {
TangemTheme(isDark = true) {
InputRowDefault(
title = TextReference.Str(data.title),
text = TextReference.Str(data.text),
iconRes = data.iconRes,
showDivider = data.showDivider,
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
private data class InputRowDefaultPreviewData(
val title: String,
val text: String,
val iconRes: Int?,
val showDivider: Boolean,
)
private class InputRowDefaultPreviewDataProvider : PreviewParameterProvider<InputRowDefaultPreviewData> {
override val values: Sequence<InputRowDefaultPreviewData>
get() = sequenceOf(
InputRowDefaultPreviewData(
title = "title",
text = "text",
iconRes = null,
showDivider = true,
),
InputRowDefaultPreviewData(
title = "title",
text = "text",
iconRes = R.drawable.ic_chevron_right_24,
showDivider = false,
),
)
}
//endregion

View file

@ -0,0 +1,167 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.components.fields.SimpleTextField
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* [InputRowEnter](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-799&mode=design&t=IQ5lBJEkFGU4WSvi-4)
*
* @param title title reference
* @param text primary text reference
* @param onValueChange text change callback
* @param modifier modifier
* @param titleColor title color
* @param textColor text color
* @param isSingleLine text
* @param visualTransformation applied transformation to text
* @param keyboardOptions keyboard options for field
* @param iconRes action icon
* @param iconTint action icon tint
* @param onIconClick click on action icon
* @param showDivider show divider
* @see [InputRowDefault] for read only version
*/
@Composable
fun InputRowEnter(
title: TextReference,
text: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
titleColor: Color = TangemTheme.colors.text.secondary,
textColor: Color = TangemTheme.colors.text.primary1,
isSingleLine: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
iconRes: Int? = null,
iconTint: Color = TangemTheme.colors.icon.informative,
onIconClick: (() -> Unit)? = null,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
SimpleTextField(
value = text,
onValueChange = onValueChange,
color = textColor,
singleLine = isSingleLine,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8),
)
}
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = iconTint,
modifier = Modifier
.padding(
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
) { onIconClick?.invoke() },
)
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowEnterPreview_Light(
@PreviewParameter(InputRowEnterPreviewDataProvider::class) data: InputRowEnterPreviewData,
) {
TangemTheme {
InputRowEnter(
title = TextReference.Str(data.title),
text = data.text,
iconRes = data.iconRes,
showDivider = data.showDivider,
onValueChange = {},
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
@Preview
@Composable
private fun InputRowEnterPreview_Dark(
@PreviewParameter(InputRowEnterPreviewDataProvider::class) data: InputRowEnterPreviewData,
) {
TangemTheme(isDark = true) {
InputRowEnter(
title = TextReference.Str(data.title),
text = data.text,
iconRes = data.iconRes,
showDivider = data.showDivider,
onValueChange = {},
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
private data class InputRowEnterPreviewData(
val title: String,
val text: String,
val iconRes: Int?,
val showDivider: Boolean,
)
private class InputRowEnterPreviewDataProvider :
PreviewParameterProvider<InputRowEnterPreviewData> {
override val values: Sequence<InputRowEnterPreviewData>
get() = sequenceOf(
InputRowEnterPreviewData(
title = "title",
text = "text",
iconRes = null,
showDivider = true,
),
InputRowEnterPreviewData(
title = "title",
text = "text",
iconRes = R.drawable.ic_chevron_right_24,
showDivider = false,
),
)
}
//endregion

View file

@ -0,0 +1,153 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.components.fields.SimpleTextField
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* Input Row Enter with Info variation.
* [Input Row Enter](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-799&mode=design&t=IQ5lBJEkFGU4WSvi-4)
* [Input Row Enter Info](https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node-id=7854-33577&mode=design&t=6o23sqF8fDQdn4C5-4)
*
* @param title title reference
* @param text primary text reference
* @param onValueChange text change callback
* @param modifier modifier
* @param titleColor title color
* @param textColor text color
* @param isSingleLine text
* @param visualTransformation applied transformation to text
* @param keyboardOptions keyboard options for field
* @param showDivider show divider
*/
@Composable
fun InputRowEnterInfo(
title: TextReference,
text: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
info: TextReference? = null,
titleColor: Color = TangemTheme.colors.text.secondary,
textColor: Color = TangemTheme.colors.text.primary1,
infoColor: Color = TangemTheme.colors.text.tertiary,
isSingleLine: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
Row {
SimpleTextField(
value = text,
onValueChange = onValueChange,
singleLine = isSingleLine,
color = textColor,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8)
.weight(1f),
)
info?.let {
Text(
text = it.resolveReference(),
style = TangemTheme.typography.body2,
color = infoColor,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing8)
.align(Alignment.Bottom),
)
}
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowEnterInfoPreview_Light(
@PreviewParameter(InputRowEnterInfoPreviewDataProvider::class) data: InputRowEnterInfoPreviewData,
) {
TangemTheme {
InputRowEnterInfo(
title = data.title,
text = data.text,
info = data.info,
showDivider = data.showDivider,
onValueChange = {},
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
@Preview
@Composable
private fun InputRowEnterInfoPreview_Dark(
@PreviewParameter(InputRowEnterInfoPreviewDataProvider::class) data: InputRowEnterInfoPreviewData,
) {
TangemTheme(isDark = true) {
InputRowEnterInfo(
title = data.title,
text = data.text,
info = data.info,
showDivider = data.showDivider,
onValueChange = {},
modifier = Modifier.background(TangemTheme.colors.background.action),
)
}
}
private data class InputRowEnterInfoPreviewData(
val title: TextReference,
val text: String,
val showDivider: Boolean,
val info: TextReference?,
)
private class InputRowEnterInfoPreviewDataProvider :
PreviewParameterProvider<InputRowEnterInfoPreviewData> {
override val values: Sequence<InputRowEnterInfoPreviewData>
get() = sequenceOf(
InputRowEnterInfoPreviewData(
title = TextReference.Str("title"),
text = "text",
showDivider = true,
info = TextReference.Str("info"),
),
InputRowEnterInfoPreviewData(
title = TextReference.Str("title"),
text = "text",
showDivider = false,
info = null,
),
)
}
//endregion

View file

@ -0,0 +1,196 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.components.currency.tokenicon.TokenIcon
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* [Input Row Image](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-813&mode=design&t=IQ5lBJEkFGU4WSvi-4)
*
* @param title title reference
* @param subtitle subtitle reference
* @param caption caption reference
* @param tokenIconState token icon state [TokenIconState]
* @param modifier modifier
* @param titleColor title color
* @param subtitleColor subtitle color
* @param captionColor caption color
* @param iconRes action icon
* @param iconTint action icon tint
* @param onIconClick click on action icon
* @param showNetworkIcon show token network icon
* @param showDivider show divider
*/
@Composable
fun InputRowImage(
title: TextReference,
subtitle: TextReference,
caption: TextReference,
tokenIconState: TokenIconState,
modifier: Modifier = Modifier,
titleColor: Color = TangemTheme.colors.text.secondary,
subtitleColor: Color = TangemTheme.colors.text.primary1,
captionColor: Color = TangemTheme.colors.text.tertiary,
iconRes: Int? = null,
iconTint: Color = TangemTheme.colors.icon.informative,
onIconClick: (() -> Unit)? = null,
showNetworkIcon: Boolean = false,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
Row(
modifier = Modifier
.padding(
top = TangemTheme.dimens.spacing6,
),
) {
TokenIcon(
state = tokenIconState,
shouldDisplayNetwork = showNetworkIcon,
modifier = Modifier
.size(TangemTheme.dimens.size36),
)
Column(
modifier = Modifier
.weight(1f)
.padding(start = TangemTheme.dimens.spacing12),
) {
Text(
text = subtitle.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = subtitleColor,
)
Text(
text = caption.resolveReference(),
style = TangemTheme.typography.caption2,
color = captionColor,
modifier = Modifier.padding(top = TangemTheme.dimens.spacing2),
)
}
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = iconTint,
modifier = Modifier
.align(CenterVertically)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
) { onIconClick?.invoke() },
)
}
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowInputEnterInfoPreview_Light(
@PreviewParameter(InputRowImagePreviewDataProvider::class) data: InputRowImagePreviewData,
) {
TangemTheme {
InputRowImage(
title = data.title,
modifier = Modifier.background(TangemTheme.colors.background.action),
subtitle = data.subtitle,
caption = data.caption,
tokenIconState = data.iconState,
iconRes = data.actionIconRes,
onIconClick = {},
showNetworkIcon = false,
showDivider = data.showDivider,
)
}
}
@Preview
@Composable
private fun InputRowImagePreview_Dark(
@PreviewParameter(InputRowImagePreviewDataProvider::class) data: InputRowImagePreviewData,
) {
TangemTheme(isDark = true) {
InputRowImage(
title = data.title,
modifier = Modifier.background(TangemTheme.colors.background.action),
subtitle = data.subtitle,
caption = data.caption,
tokenIconState = data.iconState,
iconRes = data.actionIconRes,
onIconClick = {},
showNetworkIcon = false,
showDivider = data.showDivider,
)
}
}
private data class InputRowImagePreviewData(
val title: TextReference,
val subtitle: TextReference,
val caption: TextReference,
val iconState: TokenIconState,
val showDivider: Boolean,
val actionIconRes: Int?,
val showNetworkIcon: Boolean = false,
)
private class InputRowImagePreviewDataProvider :
PreviewParameterProvider<InputRowImagePreviewData> {
override val values: Sequence<InputRowImagePreviewData>
get() = sequenceOf(
InputRowImagePreviewData(
title = TextReference.Str("title"),
subtitle = TextReference.Str("subtitle"),
caption = TextReference.Str("caption"),
iconState = TokenIconState.Locked,
actionIconRes = null,
showDivider = false,
showNetworkIcon = false,
),
InputRowImagePreviewData(
title = TextReference.Str("title"),
subtitle = TextReference.Str("subtitle"),
caption = TextReference.Str("caption"),
iconState = TokenIconState.Locked,
actionIconRes = R.drawable.ic_chevron_right_24,
showDivider = true,
showNetworkIcon = true,
),
)
}
//endregion

View file

@ -0,0 +1,168 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.fields.SimpleTextField
import com.tangem.core.ui.components.icons.identicon.IdentIcon
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.components.inputrow.inner.PasteButton
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* [Input Row Recipient](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-826&mode=design&t=IQ5lBJEkFGU4WSvi-4)
*
* @param title title reference
* @param value recipient address
* @param placeholder placeholder
* @param onValueChange callback for value change
* @param onPasteClick callback for paste
* @param modifier composable modifier
* @param singleLine is single line text
* @param error error text
* @param isError is error flag
* @param showDivider show divider
*
* @see InputRowRecipientDefault for readonly version
*/
@Composable
fun InputRowRecipient(
title: TextReference,
value: String,
placeholder: TextReference,
onValueChange: (String) -> Unit,
onPasteClick: (String) -> Unit,
modifier: Modifier = Modifier,
singleLine: Boolean = false,
error: TextReference? = null,
isError: Boolean = false,
showDivider: Boolean = false,
) {
val (titleText, color) = if (isError && error != null) {
error to TangemTheme.colors.text.warning
} else {
title to TangemTheme.colors.text.secondary
}
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Text(
text = titleText.resolveReference(),
style = TangemTheme.typography.caption2,
color = color,
)
Row(
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8),
) {
IdentIcon(
address = value,
modifier = Modifier
.align(CenterVertically)
.clip(RoundedCornerShape(TangemTheme.dimens.radius18))
.size(TangemTheme.dimens.size36)
.background(TangemTheme.colors.background.tertiary),
)
SimpleTextField(
value = value,
placeholder = placeholder,
onValueChange = onValueChange,
singleLine = singleLine,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing12)
.weight(1f)
.align(CenterVertically),
)
PasteButton(
isPasteButtonVisible = value.isBlank(),
onClick = onPasteClick,
modifier = Modifier
.align(CenterVertically)
.padding(start = TangemTheme.dimens.spacing8),
)
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowRecipientPreview_Light(
@PreviewParameter(InputRowRecipientPreviewDataProvider::class) value: InputRowRecipientPreviewData,
) {
TangemTheme {
InputRowRecipient(
value = value.value,
title = TextReference.Res(R.string.send_recipient),
placeholder = TextReference.Res(R.string.send_optional_field),
error = TextReference.Str("Error"),
isError = value.isError,
showDivider = true,
onValueChange = {},
onPasteClick = {},
modifier = Modifier.background(TangemTheme.colors.background.primary),
)
}
}
@Preview
@Composable
private fun InputRowRecipientPreview_Dark(
@PreviewParameter(InputRowRecipientPreviewDataProvider::class) value: InputRowRecipientPreviewData,
) {
TangemTheme(isDark = true) {
InputRowRecipient(
value = value.value,
title = TextReference.Res(R.string.send_recipient),
placeholder = TextReference.Res(R.string.send_optional_field),
error = TextReference.Str("Error"),
isError = value.isError,
showDivider = true,
onValueChange = {},
onPasteClick = {},
modifier = Modifier.background(TangemTheme.colors.background.primary),
)
}
}
private data class InputRowRecipientPreviewData(
val value: String,
val isError: Boolean,
)
private class InputRowRecipientPreviewDataProvider : PreviewParameterProvider<InputRowRecipientPreviewData> {
override val values: Sequence<InputRowRecipientPreviewData>
get() = sequenceOf(
InputRowRecipientPreviewData(
value = "",
isError = false,
),
InputRowRecipientPreviewData(
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
isError = false,
),
InputRowRecipientPreviewData(
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
isError = true,
),
)
}
//endregion

View file

@ -0,0 +1,106 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.icons.identicon.IdentIcon
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* Read only version of [InputRowRecipient].
* [Input Row Recipient](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-826&mode
* =design&t=IQ5lBJEkFGU4WSvi-4)
*
* @param title title reference
* @param value recipient address
* @param modifier composable modifier
* @param titleColor title color
* @param showDivider show divider
* @see InputRowRecipient for editable version
*/
@Composable
fun InputRowRecipientDefault(
title: TextReference,
value: String,
modifier: Modifier = Modifier,
titleColor: Color = TangemTheme.colors.text.secondary,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
Row(
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8),
) {
IdentIcon(
address = value,
modifier = Modifier
.align(Alignment.CenterVertically)
.clip(RoundedCornerShape(TangemTheme.dimens.radius18))
.size(TangemTheme.dimens.size36)
.background(TangemTheme.colors.background.tertiary),
)
Text(
text = value,
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing12)
.weight(1f)
.align(Alignment.CenterVertically),
)
}
}
}
}
//region preview
@Preview
@Composable
private fun InputRowRecipientPreview_Light() {
TangemTheme {
InputRowRecipientDefault(
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
title = TextReference.Res(R.string.send_recipient),
showDivider = true,
modifier = Modifier.background(TangemTheme.colors.background.primary),
)
}
}
@Preview
@Composable
private fun InputRowRecipientPreview_Dark() {
TangemTheme(isDark = true) {
InputRowRecipientDefault(
value = "0x391316d97a07027a0702c8A002c8A0C25d8470",
title = TextReference.Res(R.string.send_recipient),
showDivider = false,
modifier = Modifier.background(TangemTheme.colors.background.primary),
)
}
}
//endregion

View file

@ -0,0 +1,31 @@
package com.tangem.core.ui.components.inputrow.inner
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Divider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.tangem.core.ui.res.TangemTheme
@Composable
fun DividerContainer(
modifier: Modifier = Modifier,
showDivider: Boolean = false,
paddingValues: PaddingValues = PaddingValues(start = TangemTheme.dimens.spacing12),
content: @Composable () -> Unit,
) {
Box(modifier = modifier) {
content()
if (showDivider) {
Divider(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(paddingValues),
color = TangemTheme.colors.stroke.primary,
thickness = TangemTheme.dimens.size0_5,
)
}
}
}

View file

@ -0,0 +1,80 @@
package com.tangem.core.ui.components.inputrow.inner
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
/**
* Paste button with cross icon. Retrieves text from clipboard.
* [Paste button](https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node-id=7853-33535&mode=design&t=6o23sqF8fDQdn4C5-4)
*
* @param isPasteButtonVisible is paste button visible
* @param onClick action callback
* @param modifier composable modifier
*/
@Composable
fun PasteButton(isPasteButtonVisible: Boolean, onClick: (String) -> Unit, modifier: Modifier = Modifier) {
val clipboardManager = LocalClipboardManager.current
val hapticFeedback = LocalHapticFeedback.current
if (isPasteButtonVisible) {
Box(modifier = modifier) {
Text(
text = "Paste",
style = TangemTheme.typography.button,
color = TangemTheme.colors.text.primary2,
modifier = Modifier
.background(
color = TangemTheme.colors.button.primary,
shape = TangemTheme.shapes.roundedCornersXMedium,
)
.padding(
horizontal = TangemTheme.dimens.spacing10,
vertical = TangemTheme.dimens.spacing2,
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(radius = TangemTheme.dimens.radius8),
onClick = {
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
onClick(
clipboardManager
.getText()
?.toString()
.orEmpty(),
)
},
),
)
}
} else {
Icon(
painter = painterResource(id = R.drawable.ic_close_24),
tint = TangemTheme.colors.icon.informative,
contentDescription = stringResource(R.string.common_close),
modifier = modifier
.size(TangemTheme.dimens.size20)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(radius = TangemTheme.dimens.radius10),
onClick = { onClick("") },
),
)
}
}