Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-17 16:42:57 +03:00
parent 7a5933253b
commit 2f5ed09224
41 changed files with 414 additions and 320 deletions

View file

@ -0,0 +1,33 @@
package com.tangem.core.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import com.tangem.core.ui.res.TangemTheme
/**
* A composable that draws a fade effect at the bottom of the screen. Used on screens with a list of repeating
* elements and floating button at the bottom of the screen.
*/
@Composable
fun BottomFade(modifier: Modifier = Modifier, backgroundColor: Color = TangemTheme.colors.background.secondary) {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
Box(
modifier = modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size100 + bottomBarHeight)
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
backgroundColor,
),
),
),
)
}

View file

@ -1,12 +0,0 @@
package com.tangem.core.ui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@Composable
fun SystemBarsEffect(block: SystemUiController.() -> Unit) {
val systemUiController = rememberSystemUiController()
SideEffect { block(systemUiController) }
}

View file

@ -0,0 +1,61 @@
package com.tangem.core.ui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.res.LocalIsInDarkTheme
/**
* Provides the ability to set a scrim for 3-button navigation
*
* Automatically makes navigation bar transparent when the composable is disposed.
*
* Usage example: [com.tangem.feature.tokendetails.presentation.TokenDetailsFragment]
*/
@Composable
fun NavigationBar3ButtonsScrim() {
val systemUiController = rememberSystemUiController()
val isDarkTheme = LocalIsInDarkTheme.current
SideEffect {
systemUiController.isNavigationBarContrastEnforced = true
}
LaunchedEffect(systemUiController.isNavigationBarContrastEnforced) {
if (systemUiController.isNavigationBarContrastEnforced.not()) {
systemUiController.isNavigationBarContrastEnforced = true
}
}
DisposableEffect(isDarkTheme) {
onDispose {
systemUiController.isNavigationBarContrastEnforced = false
}
}
}
/**
* Provides the ability to set dark/light icons in cases where the darkness of the screen differs from that
* provided in [TangemTheme].
*
* Automatically returns the icon colors to their original state when the composable is disposed.
*
* Usage example: [com.tangem.feature.qrscanning.QrScanningFragment]
*/
@Composable
fun SystemBarsIconsDisposable(darkIcons: Boolean, isNavigationBarContrastEnforced: Boolean = false) {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.systemBarsDarkContentEnabled = darkIcons
systemUiController.isNavigationBarContrastEnforced = isNavigationBarContrastEnforced
}
val isDarkTheme = LocalIsInDarkTheme.current
DisposableEffect(isDarkTheme) {
onDispose {
systemUiController.systemBarsDarkContentEnabled = !isDarkTheme
systemUiController.isNavigationBarContrastEnforced = false
}
}
}

View file

@ -1,13 +1,14 @@
package com.tangem.core.ui.components.bottomsheets
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.WindowInsetsZero
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
@ -15,6 +16,7 @@ import kotlinx.coroutines.launch
* Tangem bottom sheet with custom draggable header and config
*
* @param config data model containing logic and ui models
* @param
* @param content custom bottom sheet content
*/
@OptIn(ExperimentalMaterial3Api::class)
@ -22,20 +24,33 @@ import kotlinx.coroutines.launch
inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
config: TangemBottomSheetConfig,
containerColor: Color = TangemTheme.colors.background.primary,
addBottomInsets: Boolean = true,
crossinline content: @Composable ColumnScope.(T) -> Unit,
) {
var isVisible by remember { mutableStateOf(value = config.isShow) }
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
if (isVisible && config.content is T) {
ModalBottomSheet(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.sizeIn(maxHeight = LocalWindowSize.current.height - statusBarHeight),
onDismissRequest = config.onDismissRequest,
sheetState = sheetState,
containerColor = containerColor,
shape = TangemTheme.shapes.bottomSheetLarge,
windowInsets = WindowInsetsZero,
dragHandle = { TangemBottomSheetDraggableHeader(color = containerColor) },
) {
content(config.content)
if (addBottomInsets) {
Column(
// FIXME temporary solution to fix height of the bottom sheet
modifier = Modifier.navigationBarsPadding(),
) {
content(config.content)
}
} else {
content(config.content)
}
}
}

View file

@ -81,6 +81,7 @@ data class TangemDimens internal constructor(
val size90: Dp = 90.dp,
val size93: Dp = 93.dp,
val size96: Dp = 96.dp,
val size100: Dp = 100.dp,
val size102: Dp = 102.dp,
val size108: Dp = 108.dp,
val size110: Dp = 110.dp,

View file

@ -5,9 +5,10 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.ProvideTextStyle
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.haptic.HapticManager
import com.tangem.core.ui.haptic.MockHapticManager
import com.tangem.core.ui.windowsize.WindowSize
@Composable
@ -25,6 +26,16 @@ fun TangemTheme(
.also { it.update(themeColors) }
val shapes = remember { TangemShapes(dimens) }
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = !isDark,
isNavigationBarContrastEnforced = false,
)
}
MaterialTheme(
colors = materialThemeColors(colors = themeColors, isDark = isDark),
) {

View file

@ -0,0 +1,12 @@
package com.tangem.core.ui.utils
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
object WindowInsetsZero : WindowInsets {
override fun getBottom(density: Density): Int = 0
override fun getLeft(density: Density, layoutDirection: LayoutDirection): Int = 0
override fun getRight(density: Density, layoutDirection: LayoutDirection): Int = 0
override fun getTop(density: Density): Int = 0
}