Updated on 2026-08-14
This commit is contained in:
parent
31e0591ef0
commit
6cfb8213f0
23 changed files with 1163 additions and 6 deletions
|
|
@ -171,11 +171,56 @@ Show every meaningful axis of variation in one place:
|
|||
| **Shapes** (Default, Rounded) | One labeled group (`ShapeGroup`) per shape, iterate `TangemButtonShape.entries` |
|
||||
| **Content** (text+icon vs icon-only) | Two columns per row |
|
||||
| **Sizes** | Separate `LazyColumn` item per size group if needed |
|
||||
| **Styles / Effects** (e.g. `TangemMessageEffect`) | Chip toggle — see below |
|
||||
|
||||
> **Prefer vertical stacking over horizontal.** A row should contain at most
|
||||
> 2–3 components; more than that overflows on narrow screens. Use
|
||||
> `Modifier.weight(1f)` on columns instead of fixed widths.
|
||||
|
||||
### Toggle for style/effect axes
|
||||
|
||||
When a discrete axis (e.g. a visual effect enum) would produce too many full-width
|
||||
components on one screen, use a **sticky chip-picker** instead of stacking all values.
|
||||
Make the page **stateful** and store the selected value in the `StoryBookPage` data class.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐ ← stickyHeader
|
||||
│ Magic │ Card │ Warning │ None│ ← chip row (EffectToggle)
|
||||
└─────────────────────────────────┘
|
||||
No icon, no buttons
|
||||
[ message with selected effect ]
|
||||
With icon
|
||||
[ message with selected effect ]
|
||||
…
|
||||
```
|
||||
|
||||
**Pattern:**
|
||||
|
||||
1. Add the selected value + callback to the `StoryBookPage` data class:
|
||||
```kotlin
|
||||
internal data class FooStory(
|
||||
val selectedVariant: Variant,
|
||||
val onVariantChange: (Variant) -> Unit,
|
||||
) : StoryBookPage
|
||||
```
|
||||
2. Use a stateful `Build.kt` (see [Step 2](#2-create-pagefoobuildk)).
|
||||
3. In the story composable, add a `stickyHeader` with a chip row:
|
||||
```kotlin
|
||||
stickyHeader("toggle") {
|
||||
VariantToggle(
|
||||
selected = state.selectedVariant,
|
||||
onSelect = state.onVariantChange,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
```
|
||||
4. Each `item` below uses `state.selectedVariant` for the component under test.
|
||||
|
||||
See `TangemMessageStory` for a complete example.
|
||||
|
||||
### Section structure (component grids)
|
||||
|
||||
Follow the pattern used in `ButtonsStory`:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,35 @@
|
|||
package com.tangem.feature.tester.presentation.storybook.entity
|
||||
|
||||
import com.tangem.core.ui.ds.badge.TangemBadgeColor
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
|
||||
internal sealed interface StoryBookPage
|
||||
|
||||
internal data object StoryList : StoryBookPage
|
||||
|
||||
internal data object ButtonsStory : StoryBookPage
|
||||
|
||||
internal data class TangemBadgeStory(
|
||||
val selectedColor: TangemBadgeColor,
|
||||
val onColorChange: (TangemBadgeColor) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data object OpportunitiesBGStory : StoryBookPage
|
||||
|
||||
internal data class TangemCheckboxStory(
|
||||
val isRoundedChecked: Boolean,
|
||||
val onRoundedCheckedChange: (Boolean) -> Unit,
|
||||
val isCircleChecked: Boolean,
|
||||
val onCircleCheckedChange: (Boolean) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data object TangemSegmentedPickerStory : StoryBookPage
|
||||
|
||||
internal data class TangemMessageStory(
|
||||
val selectedEffect: TangemMessageEffect,
|
||||
val onEffectChange: (TangemMessageEffect) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data class NorthernLightsStory(
|
||||
val variant: Variant,
|
||||
val onVariantChange: (Variant) -> Unit,
|
||||
|
|
@ -14,4 +38,9 @@ internal data class NorthernLightsStory(
|
|||
Shader,
|
||||
Simple,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal data class TangemTokenRowStory(
|
||||
val isBalanceHidden: Boolean,
|
||||
val onBalanceHiddenToggle: () -> Unit,
|
||||
) : StoryBookPage
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.background
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.NorthernLightsStory
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@file:Suppress("MagicNumber")
|
||||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.background
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.badge
|
||||
|
||||
import com.tangem.core.ui.ds.badge.TangemBadgeColor
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemBadgeStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemBadgeStory>.build(): TangemBadgeStory {
|
||||
return TangemBadgeStory(
|
||||
selectedColor = TangemBadgeColor.Blue,
|
||||
onColorChange = { color ->
|
||||
updateStory { it.copy(selectedColor = color) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemBadgeStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemBadgeStory>::build)
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.badge
|
||||
|
||||
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.badge.*
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemBadgeStory
|
||||
|
||||
private const val STATE_LABEL_WIDTH = 80
|
||||
|
||||
@Composable
|
||||
internal fun TangemBadgeStory(state: TangemBadgeStory, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(bottom = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
stickyHeader("color_toggle") {
|
||||
ColorToggle(
|
||||
selected = state.selectedColor,
|
||||
onSelect = state.onColorChange,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
TangemBadgeSize.entries.forEach { size ->
|
||||
item(size.name) {
|
||||
BadgeSizeSection(size = size, color = state.selectedColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColorToggle(
|
||||
selected: TangemBadgeColor,
|
||||
onSelect: (TangemBadgeColor) -> 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),
|
||||
) {
|
||||
TangemBadgeColor.entries.forEach { color ->
|
||||
ColorChip(
|
||||
label = color.name,
|
||||
selected = color == selected,
|
||||
onClick = { onSelect(color) },
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColorChip(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 BadgeSizeSection(size: TangemBadgeSize, color: TangemBadgeColor) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = size.name,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
TangemBadgeShape.entries.forEach { shape ->
|
||||
BadgeShapeGroup(size = size, shape = shape, color = color)
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BadgeShapeGroup(size: TangemBadgeSize, shape: TangemBadgeShape, color: TangemBadgeColor) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Text(
|
||||
text = shape.name,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
ColumnHeaderRow()
|
||||
TangemBadgeType.entries.forEach { type ->
|
||||
BadgeTypeRow(size = size, shape = shape, color = color, type = type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnHeaderRow() {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Spacer(Modifier.width(STATE_LABEL_WIDTH.dp))
|
||||
Text(
|
||||
text = "Text + Icon",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = "Text",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = "Icon",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BadgeTypeRow(
|
||||
size: TangemBadgeSize,
|
||||
shape: TangemBadgeShape,
|
||||
color: TangemBadgeColor,
|
||||
type: TangemBadgeType,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = type.name,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.width(STATE_LABEL_WIDTH.dp),
|
||||
)
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemBadge(
|
||||
text = stringReference("New"),
|
||||
iconRes = R.drawable.ic_information_24,
|
||||
size = size,
|
||||
shape = shape,
|
||||
color = color,
|
||||
type = type,
|
||||
iconPosition = TangemBadgeIconPosition.Start,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemBadge(
|
||||
text = stringReference("New"),
|
||||
size = size,
|
||||
shape = shape,
|
||||
color = color,
|
||||
type = type,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemBadge(
|
||||
iconRes = R.drawable.ic_information_24,
|
||||
size = size,
|
||||
shape = shape,
|
||||
color = color,
|
||||
type = type,
|
||||
iconPosition = TangemBadgeIconPosition.Start,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.buttons
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.ButtonsStory
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.buttons
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -24,6 +25,7 @@ internal fun ButtonsStory(modifier: Modifier = Modifier) {
|
|||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.checkbox
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemCheckboxStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemCheckboxStory>.build(): TangemCheckboxStory {
|
||||
return TangemCheckboxStory(
|
||||
isRoundedChecked = false,
|
||||
onRoundedCheckedChange = { checked ->
|
||||
updateStory { it.copy(isRoundedChecked = checked) }
|
||||
},
|
||||
isCircleChecked = false,
|
||||
onCircleCheckedChange = { checked ->
|
||||
updateStory { it.copy(isCircleChecked = checked) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemCheckboxStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemCheckboxStory>::build)
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.checkbox
|
||||
|
||||
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.unit.dp
|
||||
import com.tangem.core.ui.ds.checkbox.TangemCheckbox
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemCheckboxStory
|
||||
|
||||
private const val STATE_LABEL_WIDTH = 80
|
||||
|
||||
@Composable
|
||||
internal fun TangemCheckboxStory(state: TangemCheckboxStory, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("grid") {
|
||||
CheckboxGrid(state = state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CheckboxGrid(state: TangemCheckboxStory) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
ColumnHeaderRow()
|
||||
CheckboxRow(
|
||||
label = "Rounded",
|
||||
isChecked = state.isRoundedChecked,
|
||||
onCheckedChange = state.onRoundedCheckedChange,
|
||||
isRounded = true,
|
||||
)
|
||||
CheckboxRow(
|
||||
label = "Circle",
|
||||
isChecked = state.isCircleChecked,
|
||||
onCheckedChange = state.onCircleCheckedChange,
|
||||
isRounded = false,
|
||||
)
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnHeaderRow() {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Spacer(Modifier.width(STATE_LABEL_WIDTH.dp))
|
||||
Text(
|
||||
text = "Enabled",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = "Disabled",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = "Disabled (on)",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CheckboxRow(label: String, isChecked: Boolean, onCheckedChange: (Boolean) -> Unit, isRounded: Boolean) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.width(STATE_LABEL_WIDTH.dp),
|
||||
)
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemCheckbox(
|
||||
isChecked = isChecked,
|
||||
isRounded = isRounded,
|
||||
isEnabled = true,
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemCheckbox(
|
||||
isChecked = false,
|
||||
isRounded = isRounded,
|
||||
isEnabled = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TangemCheckbox(
|
||||
isChecked = true,
|
||||
isRounded = isRounded,
|
||||
isEnabled = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.message
|
||||
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemMessageStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemMessageStory>.build(): TangemMessageStory {
|
||||
return TangemMessageStory(
|
||||
selectedEffect = TangemMessageEffect.None,
|
||||
onEffectChange = { newEffect ->
|
||||
updateStory { it.copy(selectedEffect = newEffect) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemMessageStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemMessageStory>::build)
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.message
|
||||
|
||||
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.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.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.message.*
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemMessageStory
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun TangemMessageStory(state: TangemMessageStory, modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(bottom = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.statusBarsPadding()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
stickyHeader("effect_toggle") {
|
||||
EffectToggle(
|
||||
selected = state.selectedEffect,
|
||||
onSelect = state.onEffectChange,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
|
||||
item("plain") {
|
||||
VariantSection(label = "No icon, no buttons") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "plain",
|
||||
title = stringReference("Update available"),
|
||||
subtitle = stringReference("A new firmware version is ready to install on your card."),
|
||||
messageEffect = state.selectedEffect,
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("icon") {
|
||||
VariantSection(label = "With icon") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "icon",
|
||||
title = stringReference("Wallet backup missing"),
|
||||
subtitle = stringReference("To protect your assets, complete the backup process."),
|
||||
messageEffect = state.selectedEffect,
|
||||
iconUM = TangemIconUM.Icon(R.drawable.ic_attention_default_24),
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("centered") {
|
||||
VariantSection(label = "Centered") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "centered",
|
||||
title = stringReference("Scan your card"),
|
||||
subtitle = stringReference("Hold the card to the back of your phone."),
|
||||
messageEffect = state.selectedEffect,
|
||||
iconUM = TangemIconUM.Icon(R.drawable.ic_attention_default_24),
|
||||
isCentered = true,
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("1btn") {
|
||||
VariantSection(label = "With 1 button") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "1btn",
|
||||
title = stringReference("Generate addresses"),
|
||||
subtitle = stringReference("Generate addresses for 2 new networks using your card."),
|
||||
messageEffect = state.selectedEffect,
|
||||
iconUM = TangemIconUM.Icon(R.drawable.ic_attention_default_24),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = stringReference("Generate"),
|
||||
type = TangemButtonType.Primary,
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("2btn") {
|
||||
VariantSection(label = "With 2 buttons") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "2btn",
|
||||
title = stringReference("Rate the app"),
|
||||
subtitle = stringReference("How do you like Tangem so far?"),
|
||||
messageEffect = state.selectedEffect,
|
||||
iconUM = TangemIconUM.Icon(R.drawable.ic_attention_default_24),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = stringReference("Love it!"),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = {},
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = stringReference("Can be better"),
|
||||
type = TangemButtonType.Primary,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("close") {
|
||||
VariantSection(label = "With close button") {
|
||||
TangemMessage(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "close",
|
||||
title = stringReference("Note top up"),
|
||||
subtitle = stringReference("To activate the card, top it up with at least 1 XLM."),
|
||||
messageEffect = state.selectedEffect,
|
||||
iconUM = TangemIconUM.Icon(R.drawable.ic_attention_default_24),
|
||||
onCloseClick = {},
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EffectToggle(
|
||||
selected: TangemMessageEffect,
|
||||
onSelect: (TangemMessageEffect) -> 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),
|
||||
) {
|
||||
TangemMessageEffect.entries.forEach { effect ->
|
||||
EffectChip(
|
||||
label = effect.name,
|
||||
selected = effect == selected,
|
||||
onClick = { onSelect(effect) },
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EffectChip(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 VariantSection(label: String, content: @Composable ColumnScope.() -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.opportunities
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.OpportunitiesBGStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
|
||||
internal val opportunitiesBGStoryFactory: StoryPageFactory = StoryPageFactory { OpportunitiesBGStory }
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.opportunities
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
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.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.opportunities.OpportunitiesBG
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
private data class IconVariant(
|
||||
val label: String,
|
||||
val icon: TangemIconUM,
|
||||
)
|
||||
|
||||
private val variants = listOf(
|
||||
IconVariant(
|
||||
label = "Bitcoin",
|
||||
icon = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_btc_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconVariant(
|
||||
label = "Solana",
|
||||
icon = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_solana_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconVariant(
|
||||
label = "Avalanche",
|
||||
icon = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_avalanche_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconVariant(
|
||||
label = "BNB Smart Chain",
|
||||
icon = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_bsc_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconVariant(
|
||||
label = "Cardano",
|
||||
icon = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_cardano_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@Composable
|
||||
internal fun OpportunitiesBGStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
variants.forEach { variant ->
|
||||
item(variant.label) {
|
||||
OpportunitiesBG(
|
||||
icon = variant.icon,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(16.dp)),
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 24.dp),
|
||||
) {
|
||||
TangemIcon(
|
||||
tangemIconUM = variant.icon,
|
||||
modifier = Modifier.size(40.dp),
|
||||
)
|
||||
Text(
|
||||
text = variant.label,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tabs
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemSegmentedPickerStory
|
||||
|
||||
internal val tangemSegmentedPickerStoryFactory: StoryPageFactory = StoryPageFactory { TangemSegmentedPickerStory }
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tabs
|
||||
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.tabs.TangemSegmentUM
|
||||
import com.tangem.core.ui.ds.tabs.TangemSegmentedPicker
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
private val items2 = persistentListOf(
|
||||
TangemSegmentUM(id = "all", title = stringReference("All")),
|
||||
TangemSegmentUM(id = "tokens", title = stringReference("Tokens")),
|
||||
)
|
||||
|
||||
private val items3 = persistentListOf(
|
||||
TangemSegmentUM(id = "1d", title = stringReference("1D")),
|
||||
TangemSegmentUM(id = "1w", title = stringReference("1W")),
|
||||
TangemSegmentUM(id = "1m", title = stringReference("1M")),
|
||||
)
|
||||
|
||||
private val items4 = persistentListOf(
|
||||
TangemSegmentUM(id = "1d", title = stringReference("1D")),
|
||||
TangemSegmentUM(id = "1w", title = stringReference("1W")),
|
||||
TangemSegmentUM(id = "1m", title = stringReference("1M")),
|
||||
TangemSegmentUM(id = "1y", title = stringReference("1Y")),
|
||||
)
|
||||
|
||||
private val items5 = persistentListOf(
|
||||
TangemSegmentUM(id = "send", title = stringReference("Send")),
|
||||
TangemSegmentUM(id = "receive", title = stringReference("Receive")),
|
||||
TangemSegmentUM(id = "swap", title = stringReference("Swap")),
|
||||
TangemSegmentUM(id = "buy", title = stringReference("Buy")),
|
||||
TangemSegmentUM(id = "sell", title = stringReference("Sell")),
|
||||
)
|
||||
|
||||
private data class PickerConfig(
|
||||
val label: String,
|
||||
val hasSeparator: Boolean,
|
||||
val isFixed: Boolean,
|
||||
)
|
||||
|
||||
private val configs = listOf(
|
||||
PickerConfig("Default", hasSeparator = false, isFixed = false),
|
||||
PickerConfig("Separator", hasSeparator = true, isFixed = false),
|
||||
PickerConfig("Fixed", hasSeparator = false, isFixed = true),
|
||||
PickerConfig("Fixed + Separator", hasSeparator = true, isFixed = true),
|
||||
)
|
||||
|
||||
@Composable
|
||||
internal fun TangemSegmentedPickerStory(modifier: Modifier = Modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
item("default_surface") {
|
||||
PickerSection(
|
||||
title = "Default surface",
|
||||
isAltSurface = false,
|
||||
background = TangemTheme.colors2.surface.level1,
|
||||
)
|
||||
}
|
||||
item("alt_surface") {
|
||||
PickerSection(
|
||||
title = "Alt surface",
|
||||
isAltSurface = true,
|
||||
background = TangemTheme.colors2.surface.level2,
|
||||
)
|
||||
}
|
||||
item("segment_count") {
|
||||
SegmentCountSection()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PickerSection(title: String, isAltSurface: Boolean, background: Color) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(background)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
configs.forEach { config ->
|
||||
PickerRow(config = config, isAltSurface = isAltSurface)
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PickerRow(config: PickerConfig, isAltSurface: Boolean) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
Text(
|
||||
text = config.label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
TangemSegmentedPicker(
|
||||
items = items4,
|
||||
hasSeparator = config.hasSeparator,
|
||||
isFixed = config.isFixed,
|
||||
isAltSurface = isAltSurface,
|
||||
onClick = {},
|
||||
modifier = if (config.isFixed) Modifier.fillMaxWidth() else Modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SegmentCountSection() {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Segment count",
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
SegmentCountRow(label = "2 segments", items = items2)
|
||||
SegmentCountRow(label = "3 segments", items = items3)
|
||||
SegmentCountRow(label = "4 segments", items = items4)
|
||||
SegmentCountRow(label = "5 segments", items = items5)
|
||||
}
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SegmentCountRow(label: String, items: ImmutableList<TangemSegmentUM>) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
TangemSegmentedPicker(
|
||||
items = items,
|
||||
isFixed = true,
|
||||
onClick = {},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tokenrow
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTokenRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemTokenRowStory>.build(): TangemTokenRowStory {
|
||||
return TangemTokenRowStory(
|
||||
isBalanceHidden = false,
|
||||
onBalanceHiddenToggle = { updateStory { it.copy(isBalanceHidden = !it.isBalanceHidden) } },
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemTokenRowStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemTokenRowStory>::build)
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
@file:Suppress("MagicNumber", "LongMethod")
|
||||
package com.tangem.feature.tester.presentation.storybook.page.tokenrow
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRow
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRow_PreviewProvider
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTokenRowStory
|
||||
|
||||
@Composable
|
||||
internal fun TangemTokenRowStory(state: TangemTokenRowStory, modifier: Modifier = Modifier) {
|
||||
val rows = remember { TangemTokenRow_PreviewProvider().values.toList() }
|
||||
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(bottom = 16.dp),
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
) {
|
||||
stickyHeader("balance_toggle") {
|
||||
BalanceToggle(
|
||||
isHidden = state.isBalanceHidden,
|
||||
onToggle = state.onBalanceHiddenToggle,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors2.surface.level1)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
|
||||
items(rows, key = { it.id }) { um ->
|
||||
TangemTokenRow(
|
||||
tokenRowUM = um,
|
||||
isBalanceHidden = state.isBalanceHidden,
|
||||
reorderableTokenListState = null,
|
||||
modifier = Modifier.background(TangemTheme.colors2.surface.level1),
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = TangemTheme.colors2.border.neutral.secondary,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BalanceToggle(isHidden: Boolean, onToggle: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Text(
|
||||
text = "isBalanceHidden",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
Switch(checked = isHidden, onCheckedChange = { onToggle() })
|
||||
}
|
||||
}
|
||||
|
|
@ -16,13 +16,25 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.feature.tester.presentation.storybook.entity.StoryBookUM
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.background.northernLightsStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.badge.tangemBadgeStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.buttons.buttonsStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.opportunities.opportunitiesBGStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.message.tangemMessageStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.checkbox.tangemCheckboxStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tabs.tangemSegmentedPickerStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tokenrow.tangemTokenRowStoryFactory
|
||||
|
||||
private data class StoryItem(val title: String, val factory: StoryPageFactory)
|
||||
|
||||
private fun buildStories() = listOf(
|
||||
StoryItem(title = "🔘 Buttons", factory = buttonsStoryFactory),
|
||||
StoryItem(title = "🏷️ Badge", factory = tangemBadgeStoryFactory),
|
||||
StoryItem(title = "✨ Opportunities BG", factory = opportunitiesBGStoryFactory),
|
||||
StoryItem(title = "🌌 Northern Lights Background", factory = northernLightsStoryFactory),
|
||||
StoryItem(title = "💬 Message", factory = tangemMessageStoryFactory),
|
||||
StoryItem(title = "🗂️ Segmented Picker", factory = tangemSegmentedPickerStoryFactory),
|
||||
StoryItem(title = "☑️ Checkbox", factory = tangemCheckboxStoryFactory),
|
||||
StoryItem(title = "🪙 Token Row", factory = tangemTokenRowStoryFactory),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -6,10 +6,22 @@ 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.NorthernLightsStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.OpportunitiesBGStory
|
||||
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
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemCheckboxStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemMessageStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemSegmentedPickerStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemTokenRowStory
|
||||
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.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.tabs.TangemSegmentedPickerStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.tokenrow.TangemTokenRowStory
|
||||
|
||||
@Composable
|
||||
internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier) {
|
||||
|
|
@ -17,12 +29,19 @@ internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier)
|
|||
|
||||
AnimatedContent(
|
||||
targetState = state.currentPage,
|
||||
contentKey = { it::class },
|
||||
modifier = modifier,
|
||||
) { storyState ->
|
||||
when (storyState) {
|
||||
StoryList -> StoryBookListScreen(state = state)
|
||||
is NorthernLightsStory -> NorthernLightsStory(state = storyState)
|
||||
ButtonsStory -> ButtonsStory()
|
||||
is TangemBadgeStory -> TangemBadgeStory(state = storyState)
|
||||
OpportunitiesBGStory -> OpportunitiesBGStory()
|
||||
is TangemMessageStory -> TangemMessageStory(state = storyState)
|
||||
is TangemCheckboxStory -> TangemCheckboxStory(state = storyState)
|
||||
TangemSegmentedPickerStory -> TangemSegmentedPickerStory()
|
||||
is TangemTokenRowStory -> TangemTokenRowStory(state = storyState)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue