Updated on 2026-08-14
This commit is contained in:
parent
e65bf8538b
commit
2c57ba3611
89 changed files with 3836 additions and 54 deletions
|
|
@ -9,6 +9,7 @@ import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
|||
import com.tangem.core.ui.ds2.badge.TangemBadge
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.fade.TangemFade
|
||||
import com.tangem.core.ui.ds2.glowring.TangemGlowRing
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoaderSize
|
||||
import com.tangem.core.ui.ds2.row.TangemRowContentLead
|
||||
import com.tangem.core.ui.ds2.row.TangemRowVerticalAlignment
|
||||
|
|
@ -333,6 +334,25 @@ internal data class TangemCheckmarkStory(
|
|||
val onEnabledToggle: () -> Unit,
|
||||
) : DsStoryBookPage
|
||||
|
||||
internal data class TangemGlowRingStory(
|
||||
val variant: TangemGlowRing.Variant,
|
||||
val quality: TangemGlowRing.Quality,
|
||||
val background: Background,
|
||||
val isAnimated: Boolean,
|
||||
val onVariantChange: (TangemGlowRing.Variant) -> Unit,
|
||||
val onQualityChange: (TangemGlowRing.Quality) -> Unit,
|
||||
val onBackgroundChange: (Background) -> Unit,
|
||||
val onAnimatedToggle: () -> Unit,
|
||||
) : DsStoryBookPage {
|
||||
|
||||
/** Backdrop the glow-ring preview is rendered on top of. */
|
||||
enum class Background(val label: String) {
|
||||
BgPrimary("bg.primary"),
|
||||
BgSecondary("bg.secondary"),
|
||||
BgInverse("bg.inverse"),
|
||||
}
|
||||
}
|
||||
|
||||
internal data class TangemBadgeV2Story(
|
||||
val variant: TangemBadge.Variant,
|
||||
val status: TangemBadge.Status,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.feature.tester.presentation.storybook.page.ds.button.tangemBut
|
|||
import com.tangem.feature.tester.presentation.storybook.page.ds.checkbox.tangemCheckboxV2StoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.checkmark.tangemCheckmarkStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.fade.tangemFadeStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.glowring.tangemGlowRingStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.loader.tangemLoaderStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.row.tangemRowStoryFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.search.tangemSearchStoryFactory
|
||||
|
|
@ -39,6 +40,7 @@ private fun buildDsStories() = listOf(
|
|||
DsStoryItem(title = "✨ TangemShimmer", factory = tangemShimmerStoryFactory),
|
||||
DsStoryItem(title = "🌫️ TangemFade", factory = tangemFadeStoryFactory),
|
||||
DsStoryItem(title = "🧭 TangemTopNavigation", factory = tangemTopNavigationStoryFactory),
|
||||
DsStoryItem(title = "💫 TangemGlowRing", factory = tangemGlowRingStoryFactory),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.feature.tester.presentation.storybook.page.ds.glowring
|
||||
|
||||
import com.tangem.core.ui.ds2.glowring.TangemGlowRing
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemGlowRingStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemGlowRingStory>.build(): TangemGlowRingStory {
|
||||
return TangemGlowRingStory(
|
||||
variant = TangemGlowRing.Variant.Magic,
|
||||
quality = TangemGlowRing.Quality.Auto,
|
||||
background = TangemGlowRingStory.Background.BgPrimary,
|
||||
isAnimated = true,
|
||||
onVariantChange = { variant ->
|
||||
updateStory { it.copy(variant = variant) }
|
||||
},
|
||||
onQualityChange = { quality ->
|
||||
updateStory { it.copy(quality = quality) }
|
||||
},
|
||||
onBackgroundChange = { background ->
|
||||
updateStory { it.copy(background = background) }
|
||||
},
|
||||
onAnimatedToggle = {
|
||||
updateStory { it.copy(isAnimated = !it.isAnimated) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemGlowRingStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemGlowRingStory>::build)
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
@file:Suppress("MagicNumber")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.ds.glowring
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
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.ds2.glowring.TangemGlowRing
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemGlowRingStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemGlowRingStory.Background
|
||||
|
||||
@Composable
|
||||
internal fun TangemGlowRingStory(state: TangemGlowRingStory, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
.padding(vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
// Preview stays pinned at the top.
|
||||
ComponentPreview(state = state)
|
||||
// Only the controls scroll.
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
VariantSelector(selected = state.variant, onSelect = state.onVariantChange)
|
||||
QualitySelector(selected = state.quality, onSelect = state.onQualityChange)
|
||||
BackgroundSelector(selected = state.background, onSelect = state.onBackgroundChange)
|
||||
Toggles(state = state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PreviewBackground(background: Background, modifier: Modifier = Modifier) {
|
||||
when (background) {
|
||||
Background.BgPrimary -> Box(modifier.background(TangemTheme.colors3.bg.primary))
|
||||
Background.BgSecondary -> Box(modifier.background(TangemTheme.colors3.bg.secondary))
|
||||
Background.BgInverse -> Box(modifier.background(TangemTheme.colors3.bg.inverse))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ComponentPreview(state: TangemGlowRingStory) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
.clip(RoundedCornerShape(16.dp)),
|
||||
) {
|
||||
PreviewBackground(
|
||||
background = state.background,
|
||||
modifier = Modifier.matchParentSize(),
|
||||
)
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 48.dp),
|
||||
) {
|
||||
TangemGlowRing(
|
||||
modifier = Modifier.size(width = 200.dp, height = 120.dp),
|
||||
variant = state.variant,
|
||||
animated = state.isAnimated,
|
||||
quality = state.quality,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun VariantSelector(selected: TangemGlowRing.Variant, onSelect: (TangemGlowRing.Variant) -> Unit) {
|
||||
Section(label = "Variant") {
|
||||
ChipGrid(
|
||||
items = TangemGlowRing.Variant.entries,
|
||||
label = { it.name },
|
||||
isSelected = { it == selected },
|
||||
onSelect = onSelect,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun QualitySelector(selected: TangemGlowRing.Quality, onSelect: (TangemGlowRing.Quality) -> Unit) {
|
||||
Section(label = "Quality (renderer)") {
|
||||
ChipGrid(
|
||||
items = TangemGlowRing.Quality.entries,
|
||||
label = { it.name },
|
||||
isSelected = { it == selected },
|
||||
onSelect = onSelect,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BackgroundSelector(selected: Background, onSelect: (Background) -> Unit) {
|
||||
Section(label = "Background") {
|
||||
ChipGrid(
|
||||
items = Background.entries,
|
||||
label = { it.label },
|
||||
isSelected = { it == selected },
|
||||
onSelect = onSelect,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Toggles(state: TangemGlowRingStory) {
|
||||
Section(label = "Flags") {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
ToggleRow(label = "animated", checked = state.isAnimated, onToggle = state.onAnimatedToggle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Section(label: String, content: @Composable () -> Unit) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
text = label,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun <T> ChipGrid(items: List<T>, label: (T) -> String, isSelected: (T) -> Boolean, onSelect: (T) -> Unit) {
|
||||
val shape = RoundedCornerShape(50)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
.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),
|
||||
) {
|
||||
items.forEach { item ->
|
||||
Chip(
|
||||
label = label(item),
|
||||
selected = isSelected(item),
|
||||
onClick = { onSelect(item) },
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Chip(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 ToggleRow(label: String, checked: Boolean, onToggle: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(TangemTheme.colors2.surface.level2)
|
||||
.clickable(onClick = onToggle)
|
||||
.padding(horizontal = 12.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Text(
|
||||
text = if (checked) "ON" else "OFF",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = if (checked) TangemTheme.colors.text.accent else TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ import com.tangem.feature.tester.presentation.storybook.page.ds.button.TangemBut
|
|||
import com.tangem.feature.tester.presentation.storybook.page.ds.checkbox.TangemCheckboxV2Story
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.checkmark.TangemCheckmarkStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.fade.TangemFadeStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.glowring.TangemGlowRingStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.loader.TangemLoaderStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.row.TangemRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.search.TangemSearchStory
|
||||
|
|
@ -96,6 +97,7 @@ internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier)
|
|||
is TangemBadgeV2Story -> TangemBadgeV2Story(state = storyState)
|
||||
is TangemCheckboxV2Story -> TangemCheckboxV2Story(state = storyState)
|
||||
is TangemCheckmarkStory -> TangemCheckmarkStory(state = storyState)
|
||||
is TangemGlowRingStory -> TangemGlowRingStory(state = storyState)
|
||||
is TangemRowStory -> TangemRowStory(state = storyState)
|
||||
is TangemSearchStory -> TangemSearchStory(state = storyState)
|
||||
is TangemShimmerStory -> TangemShimmerStory(state = storyState)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue