android: expressive theme, tonal palette, ShxSpacing/ShxShapes tokens
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c872246b8c
commit
fda3ec158c
1 file changed
+88
-58
+88
-58
@@ -13,9 +13,13 @@ import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialExpressiveTheme
|
||||
import androidx.compose.material3.MaterialShapes
|
||||
import androidx.compose.material3.MotionScheme
|
||||
import androidx.compose.material3.Shapes
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.material3.toShape
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
@@ -27,6 +31,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -38,8 +43,41 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
||||
val ConnectionCardRadius = 16.dp
|
||||
val ScreenPadding = 16.dp
|
||||
/** Spacing scale; use these instead of ad-hoc .dp literals. */
|
||||
object ShxSpacing
|
||||
{
|
||||
val xs = 4.dp
|
||||
val sm = 8.dp
|
||||
val md = 12.dp
|
||||
val lg = 16.dp
|
||||
val xl = 24.dp
|
||||
val xxl = 32.dp
|
||||
}
|
||||
|
||||
/** Shape tokens. [scheme] feeds MaterialTheme.shapes; the rest are named radii. */
|
||||
object ShxShapes
|
||||
{
|
||||
val cardRadius = 16.dp
|
||||
|
||||
val scheme = Shapes(
|
||||
extraSmall = RoundedCornerShape(6.dp),
|
||||
small = RoundedCornerShape(10.dp),
|
||||
medium = RoundedCornerShape(14.dp),
|
||||
large = RoundedCornerShape(16.dp),
|
||||
extraLarge = RoundedCornerShape(22.dp),
|
||||
)
|
||||
|
||||
/** Scalloped "cookie" used by the hero connect button (Expressive MaterialShapes). */
|
||||
@ExperimentalMaterial3ExpressiveApi
|
||||
val hero: Shape
|
||||
@Composable get() = MaterialShapes.Cookie9Sided.toShape()
|
||||
}
|
||||
|
||||
@Deprecated("Use ShxShapes.cardRadius", ReplaceWith("ShxShapes.cardRadius"))
|
||||
val ConnectionCardRadius = ShxShapes.cardRadius
|
||||
|
||||
@Deprecated("Use ShxSpacing.lg", ReplaceWith("ShxSpacing.lg"))
|
||||
val ScreenPadding = ShxSpacing.lg
|
||||
|
||||
val ProtonPurpleLight = Color(0xFF6D4AFF)
|
||||
val ProtonPurpleDark = Color(0xFF9C7CFF)
|
||||
@@ -49,34 +87,34 @@ val SuccessGreenDark = Color(0xFF28A671)
|
||||
private val LightColors = lightColorScheme(
|
||||
primary = ProtonPurpleLight,
|
||||
onPrimary = Color.White,
|
||||
primaryContainer = Color(0xFFEDE7FF),
|
||||
onPrimaryContainer = Color(0xFF2E1A7A),
|
||||
primaryContainer = Color(0xFFE7DFFF),
|
||||
onPrimaryContainer = Color(0xFF1F0A6B),
|
||||
inversePrimary = ProtonPurpleDark,
|
||||
secondary = Color(0xFF625B71),
|
||||
secondary = Color(0xFF5E5A7D),
|
||||
onSecondary = Color.White,
|
||||
secondaryContainer = Color(0xFFE8DEF8),
|
||||
onSecondaryContainer = Color(0xFF1D192B),
|
||||
secondaryContainer = Color(0xFFE4E0F9),
|
||||
onSecondaryContainer = Color(0xFF1A1833),
|
||||
tertiary = SuccessGreenLight,
|
||||
onTertiary = Color.White,
|
||||
tertiaryContainer = Color(0xFFC8F2DA),
|
||||
onTertiaryContainer = Color(0xFF07391D),
|
||||
background = Color(0xFFF7F7F8),
|
||||
onBackground = Color(0xFF1B1B20),
|
||||
surface = Color(0xFFF7F7F8),
|
||||
onSurface = Color(0xFF1B1B20),
|
||||
surfaceVariant = Color(0xFFEBEBEF),
|
||||
onSurfaceVariant = Color(0xFF57575F),
|
||||
surfaceDim = Color(0xFFDADAE0),
|
||||
surfaceBright = Color(0xFFF7F7F8),
|
||||
surfaceContainerLowest = Color.White,
|
||||
surfaceContainerLow = Color(0xFFF2F2F4),
|
||||
surfaceContainer = Color.White,
|
||||
surfaceContainerHigh = Color(0xFFF2F2F4),
|
||||
surfaceContainerHighest = Color(0xFFEBEBEF),
|
||||
outline = Color(0xFF797981),
|
||||
outlineVariant = Color(0xFFD0D0D6),
|
||||
inverseSurface = Color(0xFF2F2F35),
|
||||
inverseOnSurface = Color(0xFFF2F2F4),
|
||||
background = Color(0xFFFCF8FF),
|
||||
onBackground = Color(0xFF1C1B20),
|
||||
surface = Color(0xFFFCF8FF),
|
||||
onSurface = Color(0xFF1C1B20),
|
||||
surfaceVariant = Color(0xFFE5E1EC),
|
||||
onSurfaceVariant = Color(0xFF48454E),
|
||||
surfaceDim = Color(0xFFDCD8E0),
|
||||
surfaceBright = Color(0xFFFCF8FF),
|
||||
surfaceContainerLowest = Color(0xFFFFFFFF),
|
||||
surfaceContainerLow = Color(0xFFF6F2FA),
|
||||
surfaceContainer = Color(0xFFF0ECF4),
|
||||
surfaceContainerHigh = Color(0xFFEAE6EE),
|
||||
surfaceContainerHighest = Color(0xFFE5E1E9),
|
||||
outline = Color(0xFF79767F),
|
||||
outlineVariant = Color(0xFFC9C5D0),
|
||||
inverseSurface = Color(0xFF313036),
|
||||
inverseOnSurface = Color(0xFFF3EFF7),
|
||||
error = Color(0xFFD8303C),
|
||||
onError = Color.White,
|
||||
errorContainer = Color(0xFFFFDAD6),
|
||||
@@ -90,31 +128,31 @@ private val DarkColors = darkColorScheme(
|
||||
primaryContainer = Color(0xFF3B2C88),
|
||||
onPrimaryContainer = Color(0xFFEDE7FF),
|
||||
inversePrimary = ProtonPurpleLight,
|
||||
secondary = Color(0xFFCCC2DC),
|
||||
onSecondary = Color(0xFF332D41),
|
||||
secondaryContainer = Color(0xFF4A4458),
|
||||
onSecondaryContainer = Color(0xFFE8DEF8),
|
||||
secondary = Color(0xFFCBC4E8),
|
||||
onSecondary = Color(0xFF322F4D),
|
||||
secondaryContainer = Color(0xFF484564),
|
||||
onSecondaryContainer = Color(0xFFE4E0F9),
|
||||
tertiary = SuccessGreenDark,
|
||||
onTertiary = Color(0xFF00391B),
|
||||
tertiaryContainer = Color(0xFF005228),
|
||||
onTertiaryContainer = Color(0xFFC8F2DA),
|
||||
background = Color(0xFF17171A),
|
||||
onBackground = Color(0xFFE6E6E9),
|
||||
surface = Color(0xFF17171A),
|
||||
onSurface = Color(0xFFE6E6E9),
|
||||
surfaceVariant = Color(0xFF2C2C31),
|
||||
onSurfaceVariant = Color(0xFFC0C0C8),
|
||||
surfaceDim = Color(0xFF17171A),
|
||||
surfaceBright = Color(0xFF3B3B41),
|
||||
surfaceContainerLowest = Color(0xFF121214),
|
||||
surfaceContainerLow = Color(0xFF1F1F23),
|
||||
surfaceContainer = Color(0xFF242428),
|
||||
surfaceContainerHigh = Color(0xFF2C2C31),
|
||||
surfaceContainerHighest = Color(0xFF36363B),
|
||||
outline = Color(0xFF8B8B93),
|
||||
outlineVariant = Color(0xFF3D3D43),
|
||||
inverseSurface = Color(0xFFE6E6E9),
|
||||
inverseOnSurface = Color(0xFF2C2C31),
|
||||
background = Color(0xFF141318),
|
||||
onBackground = Color(0xFFE5E1E9),
|
||||
surface = Color(0xFF141318),
|
||||
onSurface = Color(0xFFE5E1E9),
|
||||
surfaceVariant = Color(0xFF48454E),
|
||||
onSurfaceVariant = Color(0xFFC9C5D0),
|
||||
surfaceDim = Color(0xFF141318),
|
||||
surfaceBright = Color(0xFF3A383E),
|
||||
surfaceContainerLowest = Color(0xFF0F0D13),
|
||||
surfaceContainerLow = Color(0xFF1C1B20),
|
||||
surfaceContainer = Color(0xFF201F24),
|
||||
surfaceContainerHigh = Color(0xFF2B292F),
|
||||
surfaceContainerHighest = Color(0xFF36343A),
|
||||
outline = Color(0xFF938F99),
|
||||
outlineVariant = Color(0xFF48454E),
|
||||
inverseSurface = Color(0xFFE5E1E9),
|
||||
inverseOnSurface = Color(0xFF313036),
|
||||
error = Color(0xFFFF8A8C),
|
||||
onError = Color(0xFF490005),
|
||||
errorContainer = Color(0xFF68000E),
|
||||
@@ -163,14 +201,6 @@ private val DarkStatusColors = ShxStatusColors(
|
||||
* semantics must stay green/purple/red regardless of the user's wallpaper. */
|
||||
val LocalShxStatusColors = staticCompositionLocalOf { LightStatusColors }
|
||||
|
||||
private val ShxShapes = Shapes(
|
||||
extraSmall = RoundedCornerShape(6.dp),
|
||||
small = RoundedCornerShape(10.dp),
|
||||
medium = RoundedCornerShape(14.dp),
|
||||
large = RoundedCornerShape(16.dp),
|
||||
extraLarge = RoundedCornerShape(22.dp),
|
||||
)
|
||||
|
||||
/**
|
||||
* Process-wide holder of the "use system colors" preference, so flipping it in
|
||||
* Settings re-themes every open Compose surface without recreating activities.
|
||||
@@ -236,6 +266,7 @@ private fun buildTypography(): Typography
|
||||
|
||||
private val ShxTypography = buildTypography()
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun ShxTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit)
|
||||
{
|
||||
@@ -251,11 +282,10 @@ fun ShxTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable ()
|
||||
}
|
||||
val statusColors = if (darkTheme) DarkStatusColors else LightStatusColors
|
||||
CompositionLocalProvider(LocalShxStatusColors provides statusColors) {
|
||||
/* MaterialExpressiveTheme/MotionScheme недоступны: в material3 1.4.0 они internal,
|
||||
а 1.5.0-alpha требует compose 1.10+ (minSdk 23). Вернуться при подъеме minSdk. */
|
||||
MaterialTheme(
|
||||
MaterialExpressiveTheme(
|
||||
colorScheme = colors,
|
||||
shapes = ShxShapes,
|
||||
motionScheme = MotionScheme.expressive(),
|
||||
shapes = ShxShapes.scheme,
|
||||
typography = ShxTypography,
|
||||
content = content,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user