Updated on 2026-08-14
This commit is contained in:
parent
a8744eb429
commit
aaacc3d736
32 changed files with 1306 additions and 86 deletions
|
|
@ -2,11 +2,19 @@ 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.ds2.loader.TangemLoaderSize
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
|
||||
internal sealed interface StoryBookPage
|
||||
|
||||
/**
|
||||
* Marker for pages that live inside the DS components sub-list.
|
||||
* The view model uses it to route back navigation to the DS list
|
||||
* instead of the root [StoryList].
|
||||
*/
|
||||
internal sealed interface DsStoryBookPage : StoryBookPage
|
||||
|
||||
internal data object StoryList : StoryBookPage
|
||||
|
||||
internal data object ButtonsStory : StoryBookPage
|
||||
|
|
@ -83,4 +91,13 @@ internal data object PlaceholderStory : StoryBookPage
|
|||
|
||||
internal data object ProgressIndicatorStory : StoryBookPage
|
||||
|
||||
internal data object DeviceIconStory : StoryBookPage
|
||||
internal data object DeviceIconStory : StoryBookPage
|
||||
|
||||
internal data class DsComponentsListStory(
|
||||
val onStoryClick: (StoryPageFactory) -> Unit,
|
||||
) : StoryBookPage
|
||||
|
||||
internal data class TangemLoaderStory(
|
||||
val selectedSize: TangemLoaderSize,
|
||||
val onSizeChange: (TangemLoaderSize) -> Unit,
|
||||
) : DsStoryBookPage
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.feature.tester.presentation.storybook.page.ds
|
||||
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.DsComponentsListStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
|
||||
internal val dsComponentsListStoryFactory: StoryPageFactory = StoryPageFactory { updatePage ->
|
||||
DsComponentsListStory(
|
||||
onStoryClick = { factory ->
|
||||
updatePage { factory.create(updatePage) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.feature.tester.presentation.storybook.page.ds
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.DsComponentsListStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.StoryPageFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.loader.tangemLoaderStoryFactory
|
||||
|
||||
private data class DsStoryItem(val title: String, val factory: StoryPageFactory)
|
||||
|
||||
private fun buildDsStories() = listOf(
|
||||
DsStoryItem(title = "⏳ TangemLoader", factory = tangemLoaderStoryFactory),
|
||||
)
|
||||
|
||||
@Composable
|
||||
internal fun DsComponentsListStory(state: DsComponentsListStory, modifier: Modifier = Modifier) {
|
||||
val stories = remember { buildDsStories() }
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.primary),
|
||||
) {
|
||||
items(items = stories, key = { it.title }) { item ->
|
||||
PrimaryButton(
|
||||
text = item.title,
|
||||
onClick = { state.onStoryClick(item.factory) },
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.feature.tester.presentation.storybook.page.ds.loader
|
||||
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoaderSize
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemLoaderStory
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.StateUpdater
|
||||
import com.tangem.feature.tester.presentation.storybook.viewmodel.storyPageFactory
|
||||
|
||||
internal fun StateUpdater<TangemLoaderStory>.build(): TangemLoaderStory {
|
||||
return TangemLoaderStory(
|
||||
selectedSize = TangemLoaderSize.X24,
|
||||
onSizeChange = { size ->
|
||||
updateStory { it.copy(selectedSize = size) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal val tangemLoaderStoryFactory
|
||||
get() = storyPageFactory(StateUpdater<TangemLoaderStory>::build)
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
@file:Suppress("MagicNumber")
|
||||
|
||||
package com.tangem.feature.tester.presentation.storybook.page.ds.loader
|
||||
|
||||
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.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
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.ds2.loader.TangemLoader
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoaderSize
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemLoaderStory
|
||||
|
||||
@Composable
|
||||
internal fun TangemLoaderStory(state: TangemLoaderStory, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.statusBarsPadding()
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
ComponentPreview(size = state.selectedSize)
|
||||
SizeSelector(
|
||||
selected = state.selectedSize,
|
||||
onSelect = state.onSizeChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ComponentPreview(size: TangemLoaderSize) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(160.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(TangemTheme.colors2.surface.level2),
|
||||
) {
|
||||
TangemLoader(size = size)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SizeSelector(selected: TangemLoaderSize, onSelect: (TangemLoaderSize) -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Size",
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
val shape = RoundedCornerShape(50)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.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),
|
||||
) {
|
||||
TangemLoaderSize.entries.forEach { size ->
|
||||
SizeChip(
|
||||
label = size.name,
|
||||
selected = size == selected,
|
||||
onClick = { onSelect(size) },
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SizeChip(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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import com.tangem.feature.tester.presentation.storybook.page.buttons.buttonsStor
|
|||
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.ds.dsComponentsListStoryFactory
|
||||
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
|
||||
|
|
@ -37,6 +38,7 @@ import com.tangem.feature.tester.presentation.storybook.page.typography.typograp
|
|||
private data class StoryItem(val title: String, val factory: StoryPageFactory)
|
||||
|
||||
private fun buildStories() = listOf(
|
||||
StoryItem(title = "💎 DS Components", factory = dsComponentsListStoryFactory),
|
||||
StoryItem(title = "🔘 Buttons", factory = buttonsStoryFactory),
|
||||
StoryItem(title = "🏷️ Badge", factory = tangemBadgeStoryFactory),
|
||||
StoryItem(title = "✨ Opportunities BG", factory = opportunitiesBGStoryFactory),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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.DsComponentsListStory
|
||||
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
|
||||
|
|
@ -15,6 +16,7 @@ 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.TangemHeaderRowStory
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.TangemLoaderStory
|
||||
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
|
||||
|
|
@ -28,6 +30,8 @@ import com.tangem.feature.tester.presentation.storybook.page.background.Northern
|
|||
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.ds.DsComponentsListStory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.loader.TangemLoaderStory
|
||||
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
|
||||
|
|
@ -73,6 +77,8 @@ internal fun StoryBookScreen(state: StoryBookUM, modifier: Modifier = Modifier)
|
|||
PlaceholderStory -> PlaceholderStory()
|
||||
ProgressIndicatorStory -> ProgressIndicatorStory()
|
||||
DeviceIconStory -> DeviceIconStory()
|
||||
is DsComponentsListStory -> DsComponentsListStory(state = storyState)
|
||||
is TangemLoaderStory -> TangemLoaderStory(state = storyState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,11 @@ package com.tangem.feature.tester.presentation.storybook.viewmodel
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
||||
import com.tangem.feature.tester.presentation.storybook.entity.DsStoryBookPage
|
||||
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.StoryPageFactory
|
||||
import com.tangem.feature.tester.presentation.storybook.page.ds.dsComponentsListStoryFactory
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -30,10 +32,10 @@ internal class StoryBookViewModel @Inject constructor() : ViewModel() {
|
|||
}
|
||||
|
||||
private fun onBackClick() {
|
||||
if (_uiState.value.currentPage !is StoryList) {
|
||||
_uiState.update { it.copy(currentPage = StoryList) }
|
||||
} else {
|
||||
router?.back()
|
||||
when (_uiState.value.currentPage) {
|
||||
is StoryList -> router?.back()
|
||||
is DsStoryBookPage -> onStoryClick(dsComponentsListStoryFactory)
|
||||
else -> _uiState.update { it.copy(currentPage = StoryList) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue