Updated on 2026-08-14
This commit is contained in:
commit
79c581b209
8 changed files with 294 additions and 0 deletions
|
|
@ -0,0 +1,143 @@
|
|||
package com.tangem.core.ui.components.showcase
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseButtonModel
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* @param headerIconRes big header icon
|
||||
* @param headerText header text
|
||||
* @param showcaseItems list of bullet points
|
||||
* @param primaryButton primary button
|
||||
* @param secondaryButton secondary button
|
||||
* @param modifier compose modifier
|
||||
*
|
||||
* @see <a href = "https://www.figma.com/design/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?node-id=12620-90568&t=WeCOVTgeYfkr24Ff-4"
|
||||
* >Figma component</a>
|
||||
*/
|
||||
@Composable
|
||||
fun Showcase(
|
||||
@DrawableRes headerIconRes: Int,
|
||||
headerText: TextReference,
|
||||
showcaseItems: ImmutableList<ShowcaseItemModel>,
|
||||
primaryButton: ShowcaseButtonModel,
|
||||
secondaryButton: ShowcaseButtonModel,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
) {
|
||||
ShowcaseContent(
|
||||
headerIconRes = headerIconRes,
|
||||
headerText = headerText,
|
||||
showcaseItems = showcaseItems,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
)
|
||||
ShowcaseButtons(
|
||||
primaryButtonText = primaryButton.buttonText,
|
||||
onPrimaryClick = primaryButton.onClick,
|
||||
secondaryButtonText = secondaryButton.buttonText,
|
||||
onSecondaryClick = secondaryButton.onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowcaseButtons(
|
||||
primaryButtonText: TextReference,
|
||||
secondaryButtonText: TextReference,
|
||||
onPrimaryClick: () -> Unit,
|
||||
onSecondaryClick: () -> Unit,
|
||||
hint: TextReference? = null,
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
PrimaryButton(
|
||||
text = primaryButtonText.resolveReference(),
|
||||
onClick = onPrimaryClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
)
|
||||
SecondaryButton(
|
||||
text = secondaryButtonText.resolveReference(),
|
||||
onClick = onSecondaryClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
)
|
||||
hint?.let {
|
||||
Text(
|
||||
text = it.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 720)
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 720, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Showcase_Preview() {
|
||||
TangemThemePreview {
|
||||
Showcase(
|
||||
headerIconRes = R.drawable.ic_notifications_unread_24,
|
||||
headerText = resourceReference(R.string.user_push_notification_agreement_header),
|
||||
showcaseItems = persistentListOf(
|
||||
ShowcaseItemModel(
|
||||
R.drawable.ic_rocket_launch_24,
|
||||
resourceReference(R.string.user_push_notification_agreement_argument_one),
|
||||
),
|
||||
ShowcaseItemModel(
|
||||
R.drawable.ic_storefront_24,
|
||||
resourceReference(R.string.user_push_notification_agreement_argument_two),
|
||||
),
|
||||
),
|
||||
primaryButton = ShowcaseButtonModel(resourceReference(R.string.common_allow), {}),
|
||||
secondaryButton = ShowcaseButtonModel(resourceReference(R.string.common_later), {}),
|
||||
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.tangem.core.ui.components.showcase
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun ShowcaseContent(
|
||||
@DrawableRes headerIconRes: Int,
|
||||
headerText: TextReference,
|
||||
showcaseItems: ImmutableList<ShowcaseItemModel>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = headerIconRes),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.size(TangemTheme.dimens.size56),
|
||||
)
|
||||
Text(
|
||||
text = headerText.resolveReference(),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing34,
|
||||
end = TangemTheme.dimens.spacing34,
|
||||
top = TangemTheme.dimens.spacing28,
|
||||
),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing34,
|
||||
end = TangemTheme.dimens.spacing34,
|
||||
top = TangemTheme.dimens.spacing28,
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing24),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
repeat(showcaseItems.size) { index ->
|
||||
ShowcaseItem(
|
||||
iconRes = showcaseItems[index].iconRes,
|
||||
text = showcaseItems[index].text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.core.ui.components.showcase
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun ShowcaseItem(@DrawableRes iconRes: Int, text: TextReference) {
|
||||
Row {
|
||||
Icon(
|
||||
painter = painterResource(id = iconRes),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
)
|
||||
Text(
|
||||
text = text.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
modifier = Modifier.padding(start = TangemTheme.dimens.spacing20),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.core.ui.components.showcase.model
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
data class ShowcaseButtonModel(
|
||||
val buttonText: TextReference,
|
||||
val onClick: () -> Unit,
|
||||
)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.core.ui.components.showcase.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
data class ShowcaseItemModel(
|
||||
@DrawableRes val iconRes: Int,
|
||||
val text: TextReference,
|
||||
)
|
||||
11
core/ui/src/main/res/drawable/ic_notifications_unread_24.xml
Normal file
11
core/ui/src/main/res/drawable/ic_notifications_unread_24.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<group>
|
||||
|
||||
<clip-path android:pathData="M0,0h24v24h-24z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M11.998,21.692C11.501,21.692 11.075,21.515 10.722,21.161C10.369,20.807 10.192,20.382 10.192,19.885H13.808C13.808,20.383 13.631,20.809 13.276,21.163C12.922,21.516 12.496,21.692 11.998,21.692ZM4.5,18.885V17.385H6.308V9.923C6.308,8.578 6.723,7.389 7.553,6.356C8.383,5.322 9.449,4.661 10.75,4.373V3.75C10.75,3.403 10.871,3.108 11.114,2.865C11.357,2.622 11.652,2.5 11.999,2.5C12.346,2.5 12.641,2.622 12.884,2.865C13.128,3.108 13.25,3.403 13.25,3.75V3.95C13.086,4.246 12.956,4.547 12.859,4.854C12.763,5.16 12.704,5.478 12.683,5.808C12.569,5.787 12.458,5.769 12.35,5.754C12.242,5.738 12.125,5.731 12,5.731C10.842,5.731 9.854,6.14 9.035,6.959C8.217,7.777 7.808,8.765 7.808,9.923V17.385H16.192V11.133C16.422,11.215 16.664,11.279 16.919,11.325C17.174,11.371 17.432,11.391 17.692,11.385V17.385H19.5V18.885H4.5ZM17.482,9.202C16.718,9.202 16.069,8.935 15.534,8.4C14.998,7.866 14.731,7.217 14.731,6.453C14.731,5.689 14.998,5.04 15.533,4.505C16.067,3.97 16.716,3.702 17.479,3.702C18.243,3.702 18.893,3.969 19.428,4.504C19.963,5.038 20.231,5.687 20.231,6.451C20.231,7.214 19.963,7.864 19.429,8.399C18.895,8.934 18.245,9.202 17.482,9.202Z"/>
|
||||
|
||||
</group>
|
||||
|
||||
</vector>
|
||||
11
core/ui/src/main/res/drawable/ic_rocket_launch_24.xml
Normal file
11
core/ui/src/main/res/drawable/ic_rocket_launch_24.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<group>
|
||||
|
||||
<clip-path android:pathData="M0,0h24v24h-24z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M5.65,10.025L7.6,10.85C7.833,10.383 8.075,9.933 8.325,9.5C8.575,9.067 8.85,8.633 9.15,8.2L7.75,7.925L5.65,10.025ZM9.2,12.1L12.05,14.925C12.75,14.658 13.5,14.25 14.3,13.7C15.1,13.15 15.85,12.525 16.55,11.825C17.717,10.658 18.629,9.363 19.288,7.938C19.946,6.512 20.233,5.2 20.15,4C18.95,3.917 17.633,4.204 16.2,4.863C14.767,5.521 13.467,6.433 12.3,7.6C11.6,8.3 10.975,9.05 10.425,9.85C9.875,10.65 9.467,11.4 9.2,12.1ZM13.65,10.475C13.267,10.092 13.075,9.621 13.075,9.063C13.075,8.504 13.267,8.033 13.65,7.65C14.033,7.267 14.508,7.075 15.075,7.075C15.642,7.075 16.117,7.267 16.5,7.65C16.883,8.033 17.075,8.504 17.075,9.063C17.075,9.621 16.883,10.092 16.5,10.475C16.117,10.858 15.642,11.05 15.075,11.05C14.508,11.05 14.033,10.858 13.65,10.475ZM14.125,18.5L16.225,16.4L15.95,15C15.517,15.3 15.083,15.571 14.65,15.813C14.217,16.054 13.767,16.292 13.3,16.525L14.125,18.5ZM21.95,2.175C22.267,4.192 22.071,6.154 21.362,8.063C20.654,9.971 19.433,11.792 17.7,13.525L18.2,16C18.267,16.333 18.25,16.658 18.15,16.975C18.05,17.292 17.883,17.567 17.65,17.8L13.45,22L11.35,17.075L7.075,12.8L2.15,10.7L6.325,6.5C6.558,6.267 6.837,6.1 7.162,6C7.487,5.9 7.817,5.883 8.15,5.95L10.625,6.45C12.358,4.717 14.175,3.492 16.075,2.775C17.975,2.058 19.933,1.858 21.95,2.175ZM3.925,15.975C4.508,15.392 5.221,15.096 6.062,15.087C6.904,15.079 7.617,15.367 8.2,15.95C8.783,16.533 9.071,17.246 9.062,18.087C9.054,18.929 8.758,19.642 8.175,20.225C7.758,20.642 7.062,21 6.087,21.3C5.112,21.6 3.767,21.867 2.05,22.1C2.283,20.383 2.55,19.038 2.85,18.063C3.15,17.087 3.508,16.392 3.925,15.975ZM5.35,17.375C5.183,17.542 5.017,17.846 4.85,18.288C4.683,18.729 4.567,19.175 4.5,19.625C4.95,19.558 5.396,19.446 5.837,19.288C6.279,19.129 6.583,18.967 6.75,18.8C6.95,18.6 7.058,18.358 7.075,18.075C7.092,17.792 7,17.55 6.8,17.35C6.6,17.15 6.358,17.054 6.075,17.063C5.792,17.071 5.55,17.175 5.35,17.375Z"/>
|
||||
|
||||
</group>
|
||||
|
||||
</vector>
|
||||
11
core/ui/src/main/res/drawable/ic_storefront_24.xml
Normal file
11
core/ui/src/main/res/drawable/ic_storefront_24.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<group>
|
||||
|
||||
<clip-path android:pathData="M0,0h24v24h-24z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M21.025,11.05V19C21.025,19.55 20.829,20.021 20.438,20.413C20.046,20.804 19.575,21 19.025,21H5.025C4.475,21 4.004,20.804 3.612,20.413C3.221,20.021 3.025,19.55 3.025,19V11.05C2.642,10.7 2.346,10.25 2.137,9.7C1.929,9.15 1.925,8.55 2.125,7.9L3.175,4.5C3.308,4.067 3.546,3.708 3.887,3.425C4.229,3.142 4.625,3 5.075,3H18.975C19.425,3 19.817,3.138 20.15,3.412C20.483,3.688 20.725,4.05 20.875,4.5L21.925,7.9C22.125,8.55 22.121,9.142 21.913,9.675C21.704,10.208 21.408,10.667 21.025,11.05ZM14.225,10C14.675,10 15.017,9.846 15.25,9.538C15.483,9.229 15.575,8.883 15.525,8.5L14.975,5H13.025V8.7C13.025,9.05 13.142,9.354 13.375,9.613C13.608,9.871 13.892,10 14.225,10ZM9.725,10C10.108,10 10.421,9.871 10.663,9.613C10.904,9.354 11.025,9.05 11.025,8.7V5H9.075L8.525,8.5C8.458,8.9 8.546,9.25 8.787,9.55C9.029,9.85 9.342,10 9.725,10ZM5.275,10C5.575,10 5.837,9.892 6.062,9.675C6.287,9.458 6.425,9.183 6.475,8.85L7.025,5H5.075L4.075,8.35C3.975,8.683 4.029,9.042 4.237,9.425C4.446,9.808 4.792,10 5.275,10ZM18.775,10C19.258,10 19.608,9.808 19.825,9.425C20.042,9.042 20.092,8.683 19.975,8.35L18.925,5H17.025L17.575,8.85C17.625,9.183 17.763,9.458 17.987,9.675C18.212,9.892 18.475,10 18.775,10ZM5.025,19H19.025V11.95C18.942,11.983 18.888,12 18.862,12H18.775C18.325,12 17.929,11.925 17.587,11.775C17.246,11.625 16.908,11.383 16.575,11.05C16.275,11.35 15.933,11.583 15.55,11.75C15.167,11.917 14.758,12 14.325,12C13.875,12 13.454,11.917 13.063,11.75C12.671,11.583 12.325,11.35 12.025,11.05C11.742,11.35 11.413,11.583 11.038,11.75C10.663,11.917 10.258,12 9.825,12C9.342,12 8.904,11.917 8.512,11.75C8.121,11.583 7.775,11.35 7.475,11.05C7.125,11.4 6.779,11.646 6.437,11.788C6.096,11.929 5.708,12 5.275,12H5.162C5.121,12 5.075,11.983 5.025,11.95V19Z"/>
|
||||
|
||||
</group>
|
||||
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue