Updated on 2026-08-14
This commit is contained in:
parent
f6b0bf8dd5
commit
0b52308ff1
18 changed files with 1394 additions and 21 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.tester.presentation.storybook.entity
|
|||
import com.tangem.core.ui.ds.badge.TangemBadgeColor
|
||||
import com.tangem.core.ui.ds.field.search.TangemFieldShape
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
|
||||
internal sealed interface StoryBookPage
|
||||
|
||||
|
|
@ -64,4 +65,22 @@ internal data class TangemSearchFieldStory(
|
|||
internal data class TypographyStory(
|
||||
val isFontScaleDefault: Boolean,
|
||||
val onFontScaleToggle: () -> Unit,
|
||||
) : StoryBookPage
|
||||
) : StoryBookPage
|
||||
|
||||
internal data class TangemTopBarStory(
|
||||
val selectedType: TangemTopBarType,
|
||||
val onTypeChange: (TangemTopBarType) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data class TangemTabStory(
|
||||
val checkedIndex: Int,
|
||||
val onCheckedIndexChange: (Int) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data object TangemPagerIndicatorStory : StoryBookPage
|
||||
|
||||
internal data object PlaceholderStory : StoryBookPage
|
||||
|
||||
internal data object ProgressIndicatorStory : StoryBookPage
|
||||
|
||||
internal data object DeviceIconStory : StoryBookPage
|
||||
|
|
@ -139,12 +139,18 @@ private fun BadgeShapeGroup(size: TangemBadgeSize, shape: TangemBadgeShape, colo
|
|||
@Composable
|
||||
private fun ColumnHeaderRow() {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Spacer(Modifier.width(STATE_LABEL_WIDTH.dp))
|
||||
Text(
|
||||
text = "Text + Icon",
|
||||
text = "Icon Start",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = "Icon End",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
|
|
@ -172,7 +178,7 @@ private fun BadgeTypeRow(
|
|||
type: TangemBadgeType,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
|
|
@ -196,6 +202,21 @@ private fun BadgeTypeRow(
|
|||
onClick = {},
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemBadge(
|
||||
text = stringReference("New"),
|
||||
tangemIconUM = TangemIconUM.Icon(iconRes = R.drawable.ic_information_24),
|
||||
size = size,
|
||||
shape = shape,
|
||||
color = color,
|
||||
type = type,
|
||||
iconPosition = TangemBadgeIconPosition.End,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("primary") {
|
||||
ButtonSection(title = "Primary") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Primary") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
PrimaryTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -46,14 +46,16 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("secondary") {
|
||||
ButtonSection(title = "Secondary") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Secondary") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
SecondaryTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -67,8 +69,10 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
|
|
@ -77,7 +81,7 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
ButtonSection(
|
||||
title = "PrimaryInverse",
|
||||
background = TangemTheme.colors2.surface.level2,
|
||||
) { isEnabled, text, shape ->
|
||||
) { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
PrimaryInverseTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -91,14 +95,16 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("outline") {
|
||||
ButtonSection(title = "Outline") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Outline") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
OutlineTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -112,14 +118,16 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("accent") {
|
||||
ButtonSection(title = "Accent") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Accent") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
StatusTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -133,14 +141,16 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("positive") {
|
||||
ButtonSection(title = "Positive") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Positive") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
StatusTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -154,15 +164,17 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
type = TangemButtonType.Positive,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("ghost") {
|
||||
ButtonSection(title = "Ghost") { isEnabled, text, shape ->
|
||||
ButtonSection(title = "Ghost") { isEnabled, isLoading, text, shape, iconPosition ->
|
||||
GhostTangemButton(
|
||||
onClick = {},
|
||||
text = if (text) stringReference("Continue") else null,
|
||||
|
|
@ -176,21 +188,74 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
}
|
||||
},
|
||||
),
|
||||
iconPosition = iconPosition,
|
||||
size = TangemButtonSize.X10,
|
||||
isEnabled = isEnabled,
|
||||
isLoading = isLoading,
|
||||
shape = shape,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("sizes") {
|
||||
SizeShowcase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SizeShowcase() {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Sizes",
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
TangemButtonSize.entries.forEach { size ->
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = size.name,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.width(STATE_LABEL_WIDTH.dp),
|
||||
)
|
||||
PrimaryTangemButton(
|
||||
onClick = {},
|
||||
text = stringReference("Button"),
|
||||
tangemIconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primaryInverted },
|
||||
),
|
||||
size = size,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ButtonSection(
|
||||
title: String,
|
||||
background: Color = TangemTheme.colors2.surface.level1,
|
||||
shapes: List<TangemButtonShape> = TangemButtonShape.entries,
|
||||
button: @Composable (isEnabled: Boolean, text: Boolean, shape: TangemButtonShape) -> Unit,
|
||||
button: @Composable (
|
||||
isEnabled: Boolean,
|
||||
isLoading: Boolean,
|
||||
text: Boolean,
|
||||
shape: TangemButtonShape,
|
||||
iconPosition: TangemButtonIconPosition,
|
||||
) -> Unit,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
|
|
@ -205,7 +270,9 @@ private fun ButtonSection(
|
|||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
shapes.forEach { shape ->
|
||||
ShapeGroup(shape = shape, button = button)
|
||||
TangemButtonIconPosition.entries.forEach { iconPosition ->
|
||||
ShapeGroup(shape = shape, iconPosition = iconPosition, button = button)
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
|
|
@ -217,17 +284,46 @@ private fun ButtonSection(
|
|||
@Composable
|
||||
private fun ShapeGroup(
|
||||
shape: TangemButtonShape,
|
||||
button: @Composable (isEnabled: Boolean, text: Boolean, shape: TangemButtonShape) -> Unit,
|
||||
iconPosition: TangemButtonIconPosition,
|
||||
button: @Composable (
|
||||
isEnabled: Boolean,
|
||||
isLoading: Boolean,
|
||||
text: Boolean,
|
||||
shape: TangemButtonShape,
|
||||
iconPosition: TangemButtonIconPosition,
|
||||
) -> Unit,
|
||||
) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Text(
|
||||
text = shape.name,
|
||||
text = "${shape.name} / Icon ${iconPosition.name}",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
ColumnHeaderRow()
|
||||
StateRow(isEnabled = true, shape = shape, button = button)
|
||||
StateRow(isEnabled = false, shape = shape, button = button)
|
||||
StateRow(
|
||||
label = "Enabled",
|
||||
isEnabled = true,
|
||||
isLoading = false,
|
||||
shape = shape,
|
||||
iconPosition = iconPosition,
|
||||
button = button,
|
||||
)
|
||||
StateRow(
|
||||
label = "Disabled",
|
||||
isEnabled = false,
|
||||
isLoading = false,
|
||||
shape = shape,
|
||||
iconPosition = iconPosition,
|
||||
button = button,
|
||||
)
|
||||
StateRow(
|
||||
label = "Loading",
|
||||
isEnabled = true,
|
||||
isLoading = true,
|
||||
shape = shape,
|
||||
iconPosition = iconPosition,
|
||||
button = button,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,27 +349,37 @@ private fun ColumnHeaderRow() {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun StateRow(
|
||||
label: String,
|
||||
isEnabled: Boolean,
|
||||
isLoading: Boolean,
|
||||
shape: TangemButtonShape,
|
||||
button: @Composable (isEnabled: Boolean, text: Boolean, shape: TangemButtonShape) -> Unit,
|
||||
iconPosition: TangemButtonIconPosition,
|
||||
button: @Composable (
|
||||
isEnabled: Boolean,
|
||||
isLoading: Boolean,
|
||||
text: Boolean,
|
||||
shape: TangemButtonShape,
|
||||
iconPosition: TangemButtonIconPosition,
|
||||
) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = if (isEnabled) "Enabled" else "Disabled",
|
||||
text = label,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.width(STATE_LABEL_WIDTH.dp),
|
||||
)
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
button(isEnabled, true, shape)
|
||||
button(isEnabled, isLoading, true, shape, iconPosition)
|
||||
}
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
button(isEnabled, false, shape)
|
||||
button(isEnabled, isLoading, false, shape, iconPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.deviceicon
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.DeviceIconStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
|
||||
internal val deviceIconStoryFactory: StoryPageFactory =
|
||||
StoryPageFactory { DeviceIconStory }
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.deviceicon
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
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.unit.dp
|
||||
import com.tangem.core.ui.ds.image.DeviceIconUM
|
||||
import com.tangem.core.ui.ds.image.TangemDeviceIcon
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
private val CardBlue = Color(0xFF1C5FBF)
|
||||
private val CardGold = Color(0xFFD4A017)
|
||||
private val CardPurple = Color(0xFF7B2FBE)
|
||||
private val RingGreen = Color(0xFF2ECC71)
|
||||
|
||||
@Composable
|
||||
internal fun DeviceIconStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("section_cards") {
|
||||
SectionTitle(text = "Cards")
|
||||
}
|
||||
|
||||
item("card_1") {
|
||||
DeviceIconRow(
|
||||
label = "Single card",
|
||||
state = DeviceIconUM.Card(mainColor = CardBlue, secondColor = null),
|
||||
)
|
||||
}
|
||||
|
||||
item("card_2") {
|
||||
DeviceIconRow(
|
||||
label = "Two cards",
|
||||
state = DeviceIconUM.Card(mainColor = CardBlue, secondColor = CardGold),
|
||||
)
|
||||
}
|
||||
|
||||
item("card_3") {
|
||||
DeviceIconRow(
|
||||
label = "Three cards",
|
||||
state = DeviceIconUM.Card(
|
||||
mainColor = CardBlue,
|
||||
secondColor = CardGold,
|
||||
thirdColor = CardPurple,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
item("section_rings") {
|
||||
SectionTitle(text = "Rings")
|
||||
}
|
||||
|
||||
item("ring_solo") {
|
||||
DeviceIconRow(
|
||||
label = "Ring only",
|
||||
state = DeviceIconUM.Ring(mainColor = RingGreen),
|
||||
)
|
||||
}
|
||||
|
||||
item("ring_card") {
|
||||
DeviceIconRow(
|
||||
label = "Ring + card",
|
||||
state = DeviceIconUM.Ring(mainColor = RingGreen, cardColor = CardBlue),
|
||||
)
|
||||
}
|
||||
|
||||
item("ring_two_cards") {
|
||||
DeviceIconRow(
|
||||
label = "Ring + 2 cards",
|
||||
state = DeviceIconUM.Ring(
|
||||
mainColor = RingGreen,
|
||||
cardColor = CardBlue,
|
||||
secondCardColor = CardGold,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
item("section_stubs") {
|
||||
SectionTitle(text = "Stubs")
|
||||
}
|
||||
|
||||
repeat(3) { count ->
|
||||
item("stub_$count") {
|
||||
DeviceIconRow(
|
||||
label = "Stub ($count card${if (count > 0) "s" else ""})",
|
||||
state = DeviceIconUM.Stub(cardsCount = count),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_mobile") {
|
||||
SectionTitle(text = "Mobile")
|
||||
}
|
||||
|
||||
item("mobile") {
|
||||
DeviceIconRow(
|
||||
label = "Mobile wallet",
|
||||
state = DeviceIconUM.Mobile,
|
||||
)
|
||||
}
|
||||
|
||||
item("section_sizes") {
|
||||
SectionTitle(text = "Sizes")
|
||||
}
|
||||
|
||||
item("sizes") {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalAlignment = Alignment.Bottom,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
listOf(24, 32, 40, 48).forEach { size ->
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
TangemDeviceIcon(
|
||||
state = DeviceIconUM.Card(
|
||||
mainColor = CardBlue,
|
||||
secondColor = CardGold,
|
||||
thirdColor = CardPurple,
|
||||
),
|
||||
modifier = Modifier.size(size.dp),
|
||||
)
|
||||
Text(
|
||||
text = "${size}dp",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionTitle(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DeviceIconRow(label: String, state: DeviceIconUM) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
TangemDeviceIcon(
|
||||
state = state,
|
||||
modifier = Modifier.size(40.dp),
|
||||
)
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -88,6 +88,29 @@ private fun buildSampleRows(): List<TangemHeaderRowUM> = listOf(
|
|||
title = stringReference("Account"),
|
||||
subtitle = stringReference("\$ 42,900.17"),
|
||||
),
|
||||
TangemHeaderRowUM(
|
||||
id = "tail_text",
|
||||
startIconUM = TangemIconUM.Currency(currencyIconState = CurrencyIconState.Locked),
|
||||
tailUM = TangemRowTailUM.Text(text = stringReference("12 tokens")),
|
||||
title = stringReference("Account"),
|
||||
subtitle = stringReference("\$ 42,900.17"),
|
||||
),
|
||||
TangemHeaderRowUM(
|
||||
id = "tail_draggable",
|
||||
startIconUM = TangemIconUM.Currency(currencyIconState = CurrencyIconState.Locked),
|
||||
tailUM = TangemRowTailUM.Draggable(iconRes = R.drawable.ic_drag_24),
|
||||
title = stringReference("Account"),
|
||||
subtitle = stringReference("\$ 42,900.17"),
|
||||
),
|
||||
TangemHeaderRowUM(
|
||||
id = "clickable",
|
||||
startIconUM = TangemIconUM.Currency(currencyIconState = CurrencyIconState.Locked),
|
||||
tailUM = TangemRowTailUM.Icon(R.drawable.ic_arrow_collapse_24),
|
||||
title = stringReference("Clickable row"),
|
||||
subtitle = stringReference("\$ 42,900.17"),
|
||||
isEnabled = true,
|
||||
onItemClick = {},
|
||||
),
|
||||
TangemHeaderRowUM(
|
||||
id = "title_only",
|
||||
title = stringReference("Account"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.pagerindicator
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemPagerIndicatorStory
|
||||
|
||||
internal val tangemPagerIndicatorStoryFactory: StoryPageFactory =
|
||||
StoryPageFactory { TangemPagerIndicatorStory }
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.pagerindicator
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.TangemPagerIndicator
|
||||
import com.tangem.core.ui.ds.TangemPagerIndicatorColors
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun TangemPagerIndicatorStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("section_page_counts") {
|
||||
SectionTitle(text = "Page counts")
|
||||
}
|
||||
|
||||
listOf(1, 2, 3, 4, 5).forEach { pageCount ->
|
||||
item("count_$pageCount") {
|
||||
IndicatorRow(label = "$pageCount page(s)", pageCount = pageCount, currentPage = 0)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_many_pages") {
|
||||
SectionTitle(text = "Many pages (>5)")
|
||||
}
|
||||
|
||||
item("many_start") {
|
||||
IndicatorRow(label = "7 pages, at start", pageCount = 7, currentPage = 0)
|
||||
}
|
||||
|
||||
item("many_middle") {
|
||||
IndicatorRow(label = "7 pages, at middle", pageCount = 7, currentPage = 3)
|
||||
}
|
||||
|
||||
item("many_end") {
|
||||
IndicatorRow(label = "7 pages, at end", pageCount = 7, currentPage = 6)
|
||||
}
|
||||
|
||||
item("ten_start") {
|
||||
IndicatorRow(label = "10 pages, at start", pageCount = 10, currentPage = 0)
|
||||
}
|
||||
|
||||
item("ten_middle") {
|
||||
IndicatorRow(label = "10 pages, at middle", pageCount = 10, currentPage = 5)
|
||||
}
|
||||
|
||||
item("ten_end") {
|
||||
IndicatorRow(label = "10 pages, at end", pageCount = 10, currentPage = 9)
|
||||
}
|
||||
|
||||
item("section_active_positions") {
|
||||
SectionTitle(text = "Active dot positions (5 pages)")
|
||||
}
|
||||
|
||||
repeat(4) { page ->
|
||||
item("active_$page") {
|
||||
IndicatorRow(label = "Active: page ${page + 1}", pageCount = 5, currentPage = page)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_overlay") {
|
||||
SectionTitle(text = "With overlay background")
|
||||
}
|
||||
|
||||
item("overlay") {
|
||||
IndicatorRowWithOverlay(pageCount = 5, currentPage = 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionTitle(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun IndicatorRow(label: String, pageCount: Int, currentPage: Int) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
TangemPagerIndicator(
|
||||
pagerState = rememberPagerState(currentPage) { pageCount },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun IndicatorRowWithOverlay(pageCount: Int, currentPage: Int) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "With overlay",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
TangemPagerIndicator(
|
||||
pagerState = rememberPagerState(currentPage) { pageCount },
|
||||
colors = TangemPagerIndicatorColors.copy(
|
||||
overlay = TangemTheme.colors2.tabs.backgroundSecondary,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.placeholder
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.PlaceholderStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
|
||||
internal val placeholderStoryFactory: StoryPageFactory =
|
||||
StoryPageFactory { PlaceholderStory }
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.placeholder
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.ChipShimmer
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SmallButtonShimmer
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun PlaceholderStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("section_rectangle") {
|
||||
SectionTitle(text = "RectangleShimmer")
|
||||
}
|
||||
|
||||
item("rect_default") {
|
||||
ShimmerRow(label = "Default") {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("rect_narrow") {
|
||||
ShimmerRow(label = "Narrow (40%)") {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(fraction = 0.4f)
|
||||
.height(16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("rect_tall") {
|
||||
ShimmerRow(label = "Tall (48dp)") {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("rect_custom_radius") {
|
||||
ShimmerRow(label = "Custom radius (16dp)") {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(24.dp),
|
||||
radius = 16.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_circle") {
|
||||
SectionTitle(text = "CircleShimmer")
|
||||
}
|
||||
|
||||
item("circle_sizes") {
|
||||
ShimmerRow(label = "Sizes: 24, 32, 40, 48") {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
CircleShimmer(modifier = Modifier.size(24.dp))
|
||||
CircleShimmer(modifier = Modifier.size(32.dp))
|
||||
CircleShimmer(modifier = Modifier.size(40.dp))
|
||||
CircleShimmer(modifier = Modifier.size(48.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item("section_text") {
|
||||
SectionTitle(text = "TextShimmer")
|
||||
}
|
||||
|
||||
item("text_title") {
|
||||
ShimmerRow(label = "titleRegular44") {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.titleRegular44,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.5f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("text_heading") {
|
||||
ShimmerRow(label = "headingSemibold22") {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.headingSemibold22,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.6f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("text_body") {
|
||||
ShimmerRow(label = "bodyRegular16") {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.bodyRegular16,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.7f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("text_caption") {
|
||||
ShimmerRow(label = "captionRegular12") {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.captionRegular12,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.4f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("text_size_height") {
|
||||
ShimmerRow(label = "bodyRegular16 (textSizeHeight)") {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.bodyRegular16,
|
||||
textSizeHeight = true,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.5f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_button_chip") {
|
||||
SectionTitle(text = "SmallButtonShimmer & ChipShimmer")
|
||||
}
|
||||
|
||||
item("small_button") {
|
||||
ShimmerRow(label = "SmallButtonShimmer") {
|
||||
SmallButtonShimmer()
|
||||
}
|
||||
}
|
||||
|
||||
item("small_button_icon") {
|
||||
ShimmerRow(label = "SmallButtonShimmer (with icon)") {
|
||||
SmallButtonShimmer(withIcon = true)
|
||||
}
|
||||
}
|
||||
|
||||
item("chip") {
|
||||
ShimmerRow(label = "ChipShimmer") {
|
||||
ChipShimmer()
|
||||
}
|
||||
}
|
||||
|
||||
item("section_composition") {
|
||||
SectionTitle(text = "Skeleton composition")
|
||||
}
|
||||
|
||||
item("card_skeleton") {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Typical card loading state",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
CircleShimmer(modifier = Modifier.size(40.dp))
|
||||
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
modifier = Modifier.width(120.dp),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.captionRegular13,
|
||||
modifier = Modifier.width(80.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item("list_skeleton") {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "List loading state",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
repeat(3) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
RectangleShimmer(modifier = Modifier.size(40.dp))
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.bodyMedium16,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.6f),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.captionRegular13,
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.4f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionTitle(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShimmerRow(label: String, content: @Composable () -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.progress
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.ProgressIndicatorStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
|
||||
internal val progressIndicatorStoryFactory: StoryPageFactory =
|
||||
StoryPageFactory { ProgressIndicatorStory }
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.progress
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.progress.TangemLinearProgressIndicatorWithDot
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun ProgressIndicatorStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("section_progress") {
|
||||
SectionTitle(text = "Progress values")
|
||||
}
|
||||
|
||||
listOf(0f, 0.25f, 0.5f, 0.75f, 1f).forEach { progress ->
|
||||
item("progress_$progress") {
|
||||
ProgressRow(label = "${(progress * 100).toInt()}%", progress = progress)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_heights") {
|
||||
SectionTitle(text = "Track heights")
|
||||
}
|
||||
|
||||
listOf(4, 6, 8).forEach { height ->
|
||||
item("height_$height") {
|
||||
ProgressRow(label = "${height}dp track", progress = 0.5f, height = height)
|
||||
}
|
||||
}
|
||||
|
||||
item("section_colors") {
|
||||
SectionTitle(text = "Color variants")
|
||||
}
|
||||
|
||||
item("accent") {
|
||||
ProgressRowWithColors(
|
||||
label = "Accent",
|
||||
progress = 0.6f,
|
||||
dotColor = TangemTheme.colors2.fill.status.accent,
|
||||
bgColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant,
|
||||
)
|
||||
}
|
||||
|
||||
item("warning") {
|
||||
ProgressRowWithColors(
|
||||
label = "Warning",
|
||||
progress = 0.4f,
|
||||
dotColor = TangemTheme.colors2.fill.status.warning,
|
||||
bgColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant,
|
||||
)
|
||||
}
|
||||
|
||||
item("attention") {
|
||||
ProgressRowWithColors(
|
||||
label = "Attention",
|
||||
progress = 0.8f,
|
||||
dotColor = TangemTheme.colors2.fill.status.attention,
|
||||
bgColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionTitle(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressRow(label: String, progress: Float, height: Int = 6) {
|
||||
ProgressRowWithColors(
|
||||
label = label,
|
||||
progress = progress,
|
||||
height = height,
|
||||
dotColor = TangemTheme.colors2.fill.status.accent,
|
||||
bgColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressRowWithColors(
|
||||
label: String,
|
||||
progress: Float,
|
||||
dotColor: androidx.compose.ui.graphics.Color,
|
||||
bgColor: androidx.compose.ui.graphics.Color,
|
||||
height: Int = 6,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
TangemLinearProgressIndicatorWithDot(
|
||||
progress = { progress },
|
||||
dotColor = dotColor,
|
||||
backgroundColor = bgColor,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(height.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tab
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTabStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemTabStory>.build(): TangemTabStory {
|
||||
return TangemTabStory(
|
||||
checkedIndex = 0,
|
||||
onCheckedIndexChange = { index ->
|
||||
updateStory { it.copy(checkedIndex = index) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemTabStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemTabStory>::build)
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tab
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.tabs.TangemTab
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTabStory
|
||||
|
||||
@Composable
|
||||
internal fun TangemTabStory(state: TangemTabStory, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("interactive") {
|
||||
TabSection(title = "Interactive") {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
listOf("Markets", "Portfolio", "Activity").forEachIndexed { index, label ->
|
||||
TangemTab(
|
||||
text = stringReference(label),
|
||||
isChecked = state.checkedIndex == index,
|
||||
onCheckedChange = { if (it) state.onCheckedIndexChange(index) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item("checked") {
|
||||
TabSection(title = "Checked") {
|
||||
TangemTab(
|
||||
text = stringReference("Markets"),
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("unchecked") {
|
||||
TabSection(title = "Unchecked") {
|
||||
TangemTab(
|
||||
text = stringReference("Markets"),
|
||||
isChecked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("disabled_checked") {
|
||||
TabSection(title = "Disabled (Checked)") {
|
||||
TangemTab(
|
||||
text = stringReference("Markets"),
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("disabled_unchecked") {
|
||||
TabSection(title = "Disabled (Unchecked)") {
|
||||
TangemTab(
|
||||
text = stringReference("Markets"),
|
||||
isChecked = false,
|
||||
onCheckedChange = {},
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("multiple_tabs") {
|
||||
TabSection(title = "Multiple tabs row") {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
TangemTab(
|
||||
text = stringReference("All"),
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
TangemTab(
|
||||
text = stringReference("Gainers"),
|
||||
isChecked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
TangemTab(
|
||||
text = stringReference("Losers"),
|
||||
isChecked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TabSection(title: String, content: @Composable () -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
content()
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.topbar
|
||||
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTopBarStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemTopBarStory>.build(): TangemTopBarStory {
|
||||
return TangemTopBarStory(
|
||||
selectedType = TangemTopBarType.Default,
|
||||
onTypeChange = { type ->
|
||||
updateStory { it.copy(selectedType = type) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemTopBarStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemTopBarStory>::build)
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.topbar
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
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.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTopBarStory
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun TangemTopBarStory(state: TangemTopBarStory, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(bottom = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
stickyHeader("type_toggle") {
|
||||
TypeToggle(
|
||||
selected = state.selectedType,
|
||||
onSelect = state.onTypeChange,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
|
||||
item("title_only") {
|
||||
TopBarVariant(label = "Title only") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Wallet"),
|
||||
type = state.selectedType,
|
||||
startAction = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("title_subtitle") {
|
||||
TopBarVariant(label = "Title + Subtitle") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Wallet"),
|
||||
subtitle = stringReference("3 cards"),
|
||||
type = state.selectedType,
|
||||
startAction = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("back_action") {
|
||||
TopBarVariant(label = "Back action + Title") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Send"),
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
onClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("back_and_end") {
|
||||
TopBarVariant(label = "Back + Title + End action") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Token Details"),
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
onClick = {},
|
||||
),
|
||||
endActions = persistentListOf(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_more_default_24,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("back_and_two_end") {
|
||||
TopBarVariant(label = "Back + Title + 2 End actions") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Settings"),
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
onClick = {},
|
||||
),
|
||||
endActions = persistentListOf(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_information_24,
|
||||
onClick = {},
|
||||
),
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("ghost_actions") {
|
||||
TopBarVariant(label = "Ghost mode actions (progress=1)") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Portfolio"),
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
onClick = {},
|
||||
ghostModeProgress = 1f,
|
||||
),
|
||||
endActions = persistentListOf(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_more_default_24,
|
||||
onClick = {},
|
||||
ghostModeProgress = 1f,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("non_actionable") {
|
||||
TopBarVariant(label = "Non-actionable icons") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Details"),
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
isActionable = false,
|
||||
),
|
||||
endActions = persistentListOf(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_more_default_24,
|
||||
isActionable = false,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("title_icon") {
|
||||
TopBarVariant(label = "Title with icon") {
|
||||
TangemTopBar(
|
||||
title = stringReference("Wallet"),
|
||||
titleIconRes = R.drawable.ic_tangem_24,
|
||||
type = state.selectedType,
|
||||
startAction = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_back_24,
|
||||
onClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("no_title") {
|
||||
TopBarVariant(label = "No title (end action only)") {
|
||||
TangemTopBar(
|
||||
type = state.selectedType,
|
||||
startAction = null,
|
||||
endActions = persistentListOf(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeToggle(
|
||||
selected: TangemTopBarType,
|
||||
onSelect: (TangemTopBarType) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val shape = RoundedCornerShape(50)
|
||||
Row(
|
||||
modifier = modifier
|
||||
.clip(shape)
|
||||
.background(TangemTheme.colors2.surface.level2)
|
||||
.border(width = 1.dp, color = TangemTheme.colors2.border.neutral.secondary, shape = shape)
|
||||
.padding(4.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
TangemTopBarType.entries.forEach { type ->
|
||||
TypeChip(
|
||||
label = type.name,
|
||||
selected = type == selected,
|
||||
onClick = { onSelect(type) },
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeChip(label: String, selected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val chipShape = RoundedCornerShape(50)
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier
|
||||
.clip(chipShape)
|
||||
.background(if (selected) TangemTheme.colors2.surface.level3 else TangemTheme.colors2.surface.level2)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(vertical = 8.dp, horizontal = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = if (selected) TangemTheme.colors.text.primary1 else TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TopBarVariant(label: String, content: @Composable () -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
content()
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
|
@ -20,12 +20,18 @@ import com.tangem.feature.tester.presentation.storybook.page.badge.tangemBadgeSt
|
|||
import com.tangem.feature.tester.presentation.storybook.page.buttons.buttonsStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.checkbox.tangemCheckboxStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.contextmenu.tangemContextMenuStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.deviceicon.deviceIconStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.headerrow.tangemHeaderRowStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.message.tangemMessageStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.opportunities.opportunitiesBGStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.pagerindicator.tangemPagerIndicatorStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.placeholder.placeholderStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.progress.progressIndicatorStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.searchfield.tangemSearchFieldStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tab.tangemTabStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tabs.tangemSegmentedPickerStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tokenrow.tangemTokenRowStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.topbar.tangemTopBarStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.typography.typographyStoryFactory
|
||||
|
||||
private data class StoryItem(val title: String, val factory: StoryPageFactory)
|
||||
|
|
@ -43,6 +49,12 @@ private fun buildStories() = listOf(
|
|||
StoryItem(title = "📋 Context Menu", factory = tangemContextMenuStoryFactory),
|
||||
StoryItem(title = "🔍 Search Field", factory = tangemSearchFieldStoryFactory),
|
||||
StoryItem(title = "🔤 Typography", factory = typographyStoryFactory),
|
||||
StoryItem(title = "🧭 Top Bar", factory = tangemTopBarStoryFactory),
|
||||
StoryItem(title = "🔀 Tab", factory = tangemTabStoryFactory),
|
||||
StoryItem(title = "⚫ Pager Indicator", factory = tangemPagerIndicatorStoryFactory),
|
||||
StoryItem(title = "💀 Placeholder", factory = placeholderStoryFactory),
|
||||
StoryItem(title = "⏳ Progress Indicator", factory = progressIndicatorStoryFactory),
|
||||
StoryItem(title = "💳 Device Icon", factory = deviceIconStoryFactory),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import androidx.compose.animation.AnimatedContent
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.ButtonsStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.DeviceIconStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.NorthernLightsStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.OpportunitiesBGStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.PlaceholderStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.ProgressIndicatorStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemBadgeStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryBookUM
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryList
|
||||
|
|
@ -14,23 +17,33 @@ import com.tangem.feature.tester.presentation.storybook.entity.TangemCheckboxSto
|
|||
import com.tangem.feature.tester.presentation.storybook.entity.TangemHeaderRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemContextMenuStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemMessageStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemPagerIndicatorStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemSearchFieldStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemSegmentedPickerStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTabStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTokenRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTopBarStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TypographyStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.background.NorthernLightsStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.badge.TangemBadgeStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.buttons.ButtonsStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.deviceicon.DeviceIconStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.opportunities.OpportunitiesBGStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.checkbox.TangemCheckboxStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.message.TangemMessageStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.pagerindicator.TangemPagerIndicatorStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.placeholder.PlaceholderStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.progress.ProgressIndicatorStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tab.TangemTabStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tabs.TangemSegmentedPickerStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tokenrow.TangemTokenRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.topbar.TangemTopBarStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.headerrow.TangemHeaderRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.contextmenu.TangemContextMenuStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.searchfield.TangemSearchFieldStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.typography.TypographyStory
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
@Composable
|
||||
internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier) {
|
||||
BackHandler(onBack = state.onBackClick)
|
||||
|
|
@ -54,6 +67,12 @@ internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier)
|
|||
is TangemContextMenuStory -> TangemContextMenuStory(state = storyState)
|
||||
is TangemSearchFieldStory -> TangemSearchFieldStory(state = storyState)
|
||||
is TypographyStory -> TypographyStory(state = storyState)
|
||||
is TangemTopBarStory -> TangemTopBarStory(state = storyState)
|
||||
is TangemTabStory -> TangemTabStory(state = storyState)
|
||||
TangemPagerIndicatorStory -> TangemPagerIndicatorStory()
|
||||
PlaceholderStory -> PlaceholderStory()
|
||||
ProgressIndicatorStory -> ProgressIndicatorStory()
|
||||
DeviceIconStory -> DeviceIconStory()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue