mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-11-04 10:13:59 +00:00
feat(surface): implement Frutiger-Aero themed surfaces with glass and acrylic styles
This commit is contained in:
parent
fa9ad9981c
commit
4da5b25a5c
@ -0,0 +1,465 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package dev.krtirtho.spotube.core.ui.base
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
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.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* The Frutiger-Aero material families available to [BaseSurface].
|
||||
*
|
||||
* - [Watery]: deep aqua water with caustic light and bubbles.
|
||||
* - [Icy]: pale frosted ice with crystalline facets and frost.
|
||||
* - [Chrome]: brushed metal with a hard specular reflection.
|
||||
* - [Acrylic]: translucent tinted panel with fine grain.
|
||||
* - [Glass]: clear, glossy glass with a strong sheen.
|
||||
*/
|
||||
enum class SurfaceStyle {
|
||||
Watery,
|
||||
Icy,
|
||||
Chrome,
|
||||
Acrylic,
|
||||
Glass,
|
||||
}
|
||||
|
||||
/**
|
||||
* A themed surface panel rendered in one of the Frutiger-Aero [SurfaceStyle] materials.
|
||||
*
|
||||
* Distinct from [androidx.compose.material3.Surface] — this draws decorative material
|
||||
* backgrounds (gradients, gloss, grain, bubbles, facets) and provides a matching
|
||||
* [LocalContentColor] so text/content inside stays legible.
|
||||
*/
|
||||
@Composable
|
||||
fun BaseSurface(
|
||||
modifier: Modifier = Modifier,
|
||||
style: SurfaceStyle = SurfaceStyle.Glass,
|
||||
shape: Shape = RectangleShape,
|
||||
elevation: Dp? = null,
|
||||
contentColor: Color? = null,
|
||||
contentPadding: PaddingValues = PaddingValues.Zero,
|
||||
contentAlignment: Alignment = Alignment.TopStart,
|
||||
content: @Composable BoxScope.() -> Unit,
|
||||
) {
|
||||
val isLight = MaterialTheme.colorScheme.surface.luminance() > 0.5f
|
||||
val onSurface = MaterialTheme.colorScheme.onSurface
|
||||
|
||||
val resolvedElevation = elevation ?: when (style) {
|
||||
SurfaceStyle.Watery -> 14.dp
|
||||
SurfaceStyle.Icy -> 12.dp
|
||||
SurfaceStyle.Chrome -> 10.dp
|
||||
SurfaceStyle.Acrylic -> 16.dp
|
||||
SurfaceStyle.Glass -> 12.dp
|
||||
}
|
||||
val resolvedContentColor = contentColor ?: when (style) {
|
||||
SurfaceStyle.Watery -> Color.White
|
||||
SurfaceStyle.Icy -> if (isLight) Color(0xFF0B3A55) else Color(0xFFDCEBF7)
|
||||
SurfaceStyle.Chrome -> Color(0xFF1B2733)
|
||||
SurfaceStyle.Acrylic, SurfaceStyle.Glass -> onSurface
|
||||
}
|
||||
val ambient = when (style) {
|
||||
SurfaceStyle.Watery -> Color(0xFF0E6FB0).copy(alpha = 0.38f)
|
||||
SurfaceStyle.Icy -> Color(0xFF3FA9E0).copy(alpha = 0.3f)
|
||||
SurfaceStyle.Chrome -> Color.Black.copy(alpha = 0.3f)
|
||||
SurfaceStyle.Acrylic -> onSurface.copy(alpha = 0.22f)
|
||||
SurfaceStyle.Glass -> onSurface.copy(alpha = 0.18f)
|
||||
}
|
||||
val spot = ambient.copy(alpha = (ambient.alpha + 0.08f).coerceAtMost(1f))
|
||||
|
||||
val borderBrush = when (style) {
|
||||
SurfaceStyle.Watery -> Brush.verticalGradient(
|
||||
listOf(Color.White.copy(alpha = 0.7f), Color.White.copy(alpha = 0.12f)),
|
||||
)
|
||||
|
||||
SurfaceStyle.Icy -> Brush.verticalGradient(
|
||||
listOf(Color.White.copy(alpha = 0.95f), Color.White.copy(alpha = 0.35f)),
|
||||
)
|
||||
|
||||
SurfaceStyle.Chrome -> Brush.verticalGradient(
|
||||
listOf(Color.White.copy(alpha = 0.95f), Color.Black.copy(alpha = 0.28f)),
|
||||
)
|
||||
|
||||
SurfaceStyle.Acrylic -> Brush.verticalGradient(
|
||||
listOf(Color.White.copy(alpha = 0.5f), Color.White.copy(alpha = 0.12f)),
|
||||
)
|
||||
|
||||
SurfaceStyle.Glass -> Brush.verticalGradient(
|
||||
listOf(Color.White.copy(alpha = 0.9f), Color.White.copy(alpha = 0.3f)),
|
||||
)
|
||||
}
|
||||
|
||||
// Translucent materials (Glass, Acrylic) must not use a drop shadow: it is drawn
|
||||
// behind the node and, because the panel is see-through, shows up as a dark inset
|
||||
// shape. Their depth comes from the edge, sheen and bevel instead.
|
||||
val castsShadow = style != SurfaceStyle.Glass && style != SurfaceStyle.Acrylic
|
||||
|
||||
CompositionLocalProvider(LocalContentColor provides resolvedContentColor) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.then(
|
||||
if (castsShadow) {
|
||||
Modifier.shadow(
|
||||
elevation = resolvedElevation,
|
||||
shape = shape,
|
||||
ambientColor = ambient,
|
||||
spotColor = spot,
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
.clip(shape)
|
||||
.drawWithCache {
|
||||
onDrawBehind { drawSurfaceMaterial(style, isLight) }
|
||||
}
|
||||
.border(BorderStroke(1.dp, borderBrush), shape)
|
||||
.padding(contentPadding),
|
||||
contentAlignment = contentAlignment,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DrawScope.drawSurfaceMaterial(style: SurfaceStyle, isLight: Boolean) {
|
||||
when (style) {
|
||||
SurfaceStyle.Watery -> drawWatery(isLight)
|
||||
SurfaceStyle.Icy -> drawIcy(isLight)
|
||||
SurfaceStyle.Chrome -> drawChrome()
|
||||
SurfaceStyle.Acrylic -> drawAcrylic(isLight)
|
||||
SurfaceStyle.Glass -> drawGlass(isLight)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DrawScope.drawGlass(isLight: Boolean) {
|
||||
// See-through glass: a faint blue-tinted fill so whatever is behind shows through,
|
||||
// defined by its bright edge, sheen and shadow rather than an opaque body.
|
||||
val tint = if (isLight) Color(0xFFCFE0F2) else Color(0xFF9FB8D6)
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
listOf(
|
||||
tint.copy(alpha = if (isLight) 0.4f else 0.2f),
|
||||
tint.copy(alpha = if (isLight) 0.24f else 0.1f),
|
||||
),
|
||||
),
|
||||
)
|
||||
drawGloss(if (isLight) 0.55f else 0.16f)
|
||||
drawBottomReflection(if (isLight) 0.4f else 0.1f)
|
||||
drawInnerBevel(isLight)
|
||||
drawBubbles(seed = 11, count = 3, alpha = if (isLight) 0.4f else 0.14f)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawAcrylic(isLight: Boolean) {
|
||||
// See-through acrylic: a translucent tinted sheet with a fine grain.
|
||||
val tint = if (isLight) Color(0xFFCFD9E8) else Color(0xFF8FA2B8)
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
listOf(
|
||||
tint.copy(alpha = if (isLight) 0.45f else 0.22f),
|
||||
tint.copy(alpha = if (isLight) 0.28f else 0.12f),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// Fine grain so the panel reads as a translucent acrylic sheet.
|
||||
val random = Random(23)
|
||||
repeat(180) {
|
||||
val light = random.nextBoolean()
|
||||
drawCircle(
|
||||
color = if (light) {
|
||||
Color.White.copy(alpha = if (isLight) 0.16f else 0.06f)
|
||||
} else {
|
||||
Color.Black.copy(alpha = if (isLight) 0.06f else 0.08f)
|
||||
},
|
||||
radius = 0.7f,
|
||||
center = Offset(random.nextFloat() * size.width, random.nextFloat() * size.height),
|
||||
)
|
||||
}
|
||||
drawGloss(if (isLight) 0.4f else 0.12f, heightFraction = 0.45f)
|
||||
drawInnerBevel(isLight)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawChrome() {
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
0f to Color(0xFFF8FBFF),
|
||||
0.16f to Color(0xFFD6DEE7),
|
||||
0.4f to Color(0xFF8E99A8),
|
||||
0.5f to Color(0xFFEDF2F7),
|
||||
0.62f to Color(0xFF9AA5B4),
|
||||
1f to Color(0xFF6C7787),
|
||||
),
|
||||
)
|
||||
// Hard specular reflection near the top.
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.White.copy(alpha = 0.85f), Color.Transparent),
|
||||
startY = size.height * 0.05f,
|
||||
endY = size.height * 0.22f,
|
||||
),
|
||||
)
|
||||
// Darkened lower edge for the metal bevel.
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.25f)),
|
||||
startY = size.height * 0.78f,
|
||||
endY = size.height,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawIcy(isLight: Boolean) {
|
||||
val colors = if (isLight) {
|
||||
listOf(Color(0xFFF4FCFF), Color(0xFFCBE9FB), Color(0xFF9BD3F0))
|
||||
} else {
|
||||
// Snowy-night ice: dim slate-blue with faint frost.
|
||||
listOf(Color(0xFF2A3B4D), Color(0xFF1B2A39), Color(0xFF0F1A26))
|
||||
}
|
||||
drawRect(brush = Brush.verticalGradient(colors))
|
||||
|
||||
val frost = if (isLight) Color.White else Color(0xFFB8CCE0)
|
||||
|
||||
// Crystalline facets (kept inset so they are never clipped by the shape).
|
||||
val random = Random(37)
|
||||
repeat(4) {
|
||||
val s = size.minDimension * (0.2f + random.nextFloat() * 0.3f)
|
||||
val x = random.nextFloat() * (size.width - s).coerceAtLeast(0f)
|
||||
val y = random.nextFloat() * (size.height - s).coerceAtLeast(0f)
|
||||
val path = Path().apply {
|
||||
moveTo(x, y)
|
||||
lineTo(x + s, y + s * 0.4f)
|
||||
lineTo(x + s * 0.4f, y + s)
|
||||
close()
|
||||
}
|
||||
drawPath(path, frost.copy(alpha = if (isLight) 0.25f else 0.12f))
|
||||
}
|
||||
|
||||
// Frost speckles.
|
||||
repeat(90) {
|
||||
drawCircle(
|
||||
color = frost.copy(alpha = if (isLight) 0.5f else 0.28f),
|
||||
radius = 0.8f,
|
||||
center = Offset(random.nextFloat() * size.width, random.nextFloat() * size.height),
|
||||
)
|
||||
}
|
||||
drawGloss(if (isLight) 0.6f else 0.12f, heightFraction = 0.5f)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawWatery(isLight: Boolean) {
|
||||
val colors = if (isLight) {
|
||||
listOf(Color(0xFFA6E3FF), Color(0xFF3FB6EA), Color(0xFF0E6FB0))
|
||||
} else {
|
||||
// Moonlit night water: deep blue with a pale silver sheen.
|
||||
listOf(Color(0xFF1C3A5E), Color(0xFF102942), Color(0xFF071827))
|
||||
}
|
||||
drawRect(brush = Brush.verticalGradient(colors))
|
||||
|
||||
val sheen = if (isLight) Color.White else Color(0xFFB9D2F0)
|
||||
|
||||
// Caustic / moonlight pooling from the surface.
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(sheen.copy(alpha = if (isLight) 0.35f else 0.22f), Color.Transparent),
|
||||
startY = 0f,
|
||||
endY = size.height * 0.5f,
|
||||
),
|
||||
)
|
||||
|
||||
val random = Random(53)
|
||||
repeat(5) {
|
||||
val rx = size.width * (0.12f + random.nextFloat() * 0.2f)
|
||||
val cx = rx + random.nextFloat() * (size.width - 2 * rx).coerceAtLeast(0f)
|
||||
val cy = rx * 0.5f + random.nextFloat() * (size.height * 0.6f - rx).coerceAtLeast(0f)
|
||||
drawOval(
|
||||
brush = Brush.radialGradient(
|
||||
colors = listOf(sheen.copy(alpha = if (isLight) 0.3f else 0.18f), Color.Transparent),
|
||||
center = Offset(cx, cy),
|
||||
radius = rx,
|
||||
),
|
||||
topLeft = Offset(cx - rx, cy - rx * 0.5f),
|
||||
size = Size(rx * 2f, rx),
|
||||
)
|
||||
}
|
||||
|
||||
drawBubbles(seed = 71, count = 6, alpha = if (isLight) 0.4f else 0.22f)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawGloss(alpha: Float, heightFraction: Float = 0.5f) {
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.White.copy(alpha = alpha), Color.Transparent),
|
||||
startY = 0f,
|
||||
endY = size.height * heightFraction,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawBottomReflection(alpha: Float) {
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.Transparent, Color.White.copy(alpha = alpha)),
|
||||
startY = size.height * 0.7f,
|
||||
endY = size.height,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/** A bright inner top edge plus a shaded inner bottom edge, giving the pane a glass bevel. */
|
||||
private fun DrawScope.drawInnerBevel(isLight: Boolean) {
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.White.copy(alpha = if (isLight) 0.85f else 0.22f), Color.Transparent),
|
||||
startY = 0f,
|
||||
endY = size.height * 0.1f,
|
||||
),
|
||||
)
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(Color.Transparent, Color.Black.copy(alpha = if (isLight) 0.08f else 0.28f)),
|
||||
startY = size.height * 0.9f,
|
||||
endY = size.height,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawBubbles(seed: Int, count: Int, alpha: Float) {
|
||||
val random = Random(seed)
|
||||
repeat(count) {
|
||||
val radius = size.minDimension * (0.05f + random.nextFloat() * 0.14f)
|
||||
// Keep bubbles inset so they are never clipped into hard arcs at the edges.
|
||||
val cx = radius + random.nextFloat() * (size.width - 2 * radius).coerceAtLeast(0f)
|
||||
val cy = radius + random.nextFloat() * (size.height - 2 * radius).coerceAtLeast(0f)
|
||||
val center = Offset(cx, cy)
|
||||
drawCircle(
|
||||
brush = Brush.radialGradient(
|
||||
colors = listOf(Color.White.copy(alpha = alpha), Color.White.copy(alpha = 0f)),
|
||||
center = center,
|
||||
radius = radius,
|
||||
),
|
||||
radius = radius,
|
||||
center = center,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@BaseUIPhonePreview
|
||||
@BaseUIDesktopPreview
|
||||
@Composable
|
||||
private fun BaseSurfacePreview() {
|
||||
BaseUIPreview {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(20.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
||||
) {
|
||||
SurfaceStyle.entries.forEach { style ->
|
||||
BaseSurface(
|
||||
style = style,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(84.dp),
|
||||
) {
|
||||
Text(
|
||||
text = style.name,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BaseUIPhonePreview
|
||||
@Composable
|
||||
private fun BaseSurfaceGridPreview() {
|
||||
BaseUIPreview {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(20.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
||||
) {
|
||||
SurfaceStyle.entries.chunked(2).forEach { rowStyles ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(14.dp),
|
||||
) {
|
||||
rowStyles.forEach { style ->
|
||||
BaseSurface(
|
||||
style = style,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(140.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Text(
|
||||
text = style.name,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Text(
|
||||
text = "Frutiger Aero",
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
repeat(2 - rowStyles.size) {
|
||||
androidx.compose.foundation.layout.Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.graphics.lerp
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -219,19 +220,51 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
val isLight = scheme.surface.luminance() > 0.5f
|
||||
|
||||
val containerLighter = if (isLight) Color.White else scheme.surfaceContainerHigh
|
||||
val containerDarker = if (isLight) Color(0xFFF2F2F4) else scheme.surfaceContainer
|
||||
val containerPressed = if (isLight) Color(0xFFE0E0E3) else scheme.surfaceContainerHighest
|
||||
val highlight = if (isLight) Color.White.copy(alpha = 0.9f) else Color.White.copy(alpha = 0.06f)
|
||||
// ------------------------------------------------------------------
|
||||
// Frutiger-Aero glass palette.
|
||||
//
|
||||
// Surfaces are glossy, top-lit gradients with a strong white specular
|
||||
// highlight and translucent "glass" edges, lifted by soft, coloured
|
||||
// shadows — the aqua/glass language of Frutiger-Aero.
|
||||
// ------------------------------------------------------------------
|
||||
val glassTop = if (isLight) {
|
||||
Color.White
|
||||
} else {
|
||||
lerp(scheme.surfaceContainerHigh, Color.White, 0.10f)
|
||||
}
|
||||
val glassBottom = if (isLight) {
|
||||
lerp(scheme.surface, Color.White, 0.04f)
|
||||
} else {
|
||||
scheme.surfaceContainer
|
||||
}
|
||||
val glassPressed = if (isLight) {
|
||||
lerp(scheme.surfaceContainerHighest, Color.White, 0.06f)
|
||||
} else {
|
||||
lerp(scheme.surfaceContainerHighest, Color.Black, 0.08f)
|
||||
}
|
||||
|
||||
val gloss = if (isLight) Color.White.copy(alpha = 0.75f) else Color.White.copy(alpha = 0.18f)
|
||||
val glossSoft = if (isLight) Color.White.copy(alpha = 0.5f) else Color.White.copy(alpha = 0.12f)
|
||||
val glassEdge = if (isLight) Color.White.copy(alpha = 0.95f) else Color.White.copy(alpha = 0.22f)
|
||||
val glassBorder = if (isLight) {
|
||||
lerp(scheme.outlineVariant, Color.White, 0.55f)
|
||||
} else {
|
||||
scheme.outlineVariant.copy(alpha = 0.5f)
|
||||
}
|
||||
val shadowColor = scheme.onSurface
|
||||
val border = scheme.outlineVariant
|
||||
|
||||
val secondaryContainer = scheme.secondaryContainer
|
||||
val secondaryContainerPressed = secondaryContainer.copy(alpha = if (isLight) 0.85f else 0.92f)
|
||||
val secondaryHighlight =
|
||||
if (isLight) Color.White.copy(alpha = 0.5f) else Color.White.copy(alpha = 0.08f)
|
||||
fun glassBrush(top: Color, bottom: Color): Brush =
|
||||
Brush.verticalGradient(listOf(top, bottom))
|
||||
|
||||
val defaultShape = RoundedCornerShape(14.dp)
|
||||
fun aqua(accent: Color): Brush = Brush.verticalGradient(
|
||||
listOf(
|
||||
lerp(accent, Color.White, 0.45f),
|
||||
accent,
|
||||
lerp(accent, Color.Black, 0.14f),
|
||||
)
|
||||
)
|
||||
|
||||
val defaultShape = RoundedCornerShape(16.dp)
|
||||
val defaultShapeState =
|
||||
BaseUITheme.InteractionState<Shape>(defaultShape, defaultShape, defaultShape, defaultShape)
|
||||
val noBorder = BaseUITheme.Border(Color.Transparent, 0.dp)
|
||||
@ -239,231 +272,208 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
val noShadow = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent)
|
||||
val noShadowState = BaseUITheme.InteractionState(noShadow, noShadow, noShadow, noShadow)
|
||||
val defaultButtonPadding = BaseUITheme.InteractionState(
|
||||
PaddingValues(horizontal = 20.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 20.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 20.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 20.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 22.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 22.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 22.dp, vertical = 10.dp),
|
||||
PaddingValues(horizontal = 22.dp, vertical = 10.dp),
|
||||
)
|
||||
val iconButtonPadding = BaseUITheme.InteractionState(
|
||||
PaddingValues(8.dp),
|
||||
PaddingValues(8.dp),
|
||||
PaddingValues(8.dp),
|
||||
PaddingValues(8.dp),
|
||||
PaddingValues(9.dp),
|
||||
PaddingValues(9.dp),
|
||||
PaddingValues(9.dp),
|
||||
PaddingValues(9.dp),
|
||||
)
|
||||
|
||||
// --- Glass (outline) -------------------------------------------------
|
||||
val outlineColors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
highlight = gloss,
|
||||
),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
highlight = Color.White.copy(alpha = if (isLight) 0.9f else 0.26f),
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerPressed, containerPressed)),
|
||||
background = glassBrush(glassPressed, glassPressed),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
highlight = glossSoft,
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
highlight = gloss,
|
||||
),
|
||||
)
|
||||
val outlineShadow = BaseUITheme.InteractionState(
|
||||
val glassShadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
8.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
shadowColor.copy(alpha = 0.16f),
|
||||
shadowColor.copy(alpha = 0.2f),
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
14.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.26f)
|
||||
shadowColor.copy(alpha = 0.26f),
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
2.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.08f),
|
||||
shadowColor.copy(alpha = 0.1f)
|
||||
shadowColor.copy(alpha = 0.1f),
|
||||
shadowColor.copy(alpha = 0.12f),
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
8.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
shadowColor.copy(alpha = 0.16f),
|
||||
shadowColor.copy(alpha = 0.2f),
|
||||
),
|
||||
)
|
||||
val outlineBorder = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(border, 0.5.dp),
|
||||
hovered = BaseUITheme.Border(border, 0.5.dp),
|
||||
pressed = BaseUITheme.Border(border.copy(alpha = 0.7f), 0.5.dp),
|
||||
focused = BaseUITheme.Border(border, 0.5.dp),
|
||||
val glassBorderState = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
hovered = BaseUITheme.Border(glassEdge, 1.dp),
|
||||
pressed = BaseUITheme.Border(glassBorder.copy(alpha = 0.7f), 1.dp),
|
||||
focused = BaseUITheme.Border(glassEdge, 1.dp),
|
||||
)
|
||||
|
||||
// --- Aqua accent (primary) -------------------------------------------
|
||||
val primaryEdge = lerp(scheme.primary, Color.White, 0.5f)
|
||||
val primaryColors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
normal = BaseUITheme.ButtonColors(aqua(scheme.primary), scheme.onPrimary, gloss),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
aqua(scheme.primary),
|
||||
scheme.onPrimary,
|
||||
Color.White.copy(alpha = if (isLight) 0.9f else 0.3f),
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.primary.copy(alpha = 0.85f),
|
||||
scheme.primary
|
||||
)
|
||||
glassBrush(
|
||||
lerp(scheme.primary, Color.Black, 0.16f),
|
||||
lerp(scheme.primary, Color.Black, 0.24f),
|
||||
),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
scheme.onPrimary,
|
||||
glossSoft,
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(aqua(scheme.primary), scheme.onPrimary, gloss),
|
||||
)
|
||||
val primaryShadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
10.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.35f),
|
||||
scheme.primary.copy(alpha = 0.4f)
|
||||
scheme.primary.copy(alpha = 0.42f),
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
16.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.45f),
|
||||
scheme.primary.copy(alpha = 0.5f)
|
||||
scheme.primary.copy(alpha = 0.5f),
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
3.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.2f),
|
||||
scheme.primary.copy(alpha = 0.25f)
|
||||
scheme.primary.copy(alpha = 0.22f),
|
||||
scheme.primary.copy(alpha = 0.28f),
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
10.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.35f),
|
||||
scheme.primary.copy(alpha = 0.4f)
|
||||
scheme.primary.copy(alpha = 0.42f),
|
||||
),
|
||||
)
|
||||
val primaryBorder = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
hovered = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
pressed = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
focused = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
normal = BaseUITheme.Border(primaryEdge, 1.dp),
|
||||
hovered = BaseUITheme.Border(primaryEdge, 1.dp),
|
||||
pressed = BaseUITheme.Border(primaryEdge.copy(alpha = 0.8f), 1.dp),
|
||||
focused = BaseUITheme.Border(primaryEdge, 1.dp),
|
||||
)
|
||||
|
||||
// --- Secondary (soft aqua glass) -------------------------------------
|
||||
val secondaryBase = scheme.secondaryContainer
|
||||
val secondaryColors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
secondaryContainer,
|
||||
secondaryContainer.copy(alpha = if (secondaryContainer.luminance() > 0.5f) 0.92f else 1f)
|
||||
)
|
||||
),
|
||||
foreground = scheme.onSecondaryContainer,
|
||||
highlight = secondaryHighlight,
|
||||
glassBrush(lerp(secondaryBase, Color.White, 0.5f), secondaryBase),
|
||||
scheme.onSecondaryContainer,
|
||||
gloss,
|
||||
),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
secondaryContainer,
|
||||
secondaryContainer.copy(alpha = if (secondaryContainer.luminance() > 0.5f) 0.92f else 1f)
|
||||
)
|
||||
),
|
||||
foreground = scheme.onSecondaryContainer,
|
||||
highlight = secondaryHighlight,
|
||||
glassBrush(lerp(secondaryBase, Color.White, 0.55f), secondaryBase),
|
||||
scheme.onSecondaryContainer,
|
||||
Color.White.copy(alpha = if (isLight) 0.85f else 0.24f),
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
secondaryContainerPressed,
|
||||
secondaryContainerPressed
|
||||
)
|
||||
glassBrush(
|
||||
lerp(secondaryBase, Color.Black, 0.08f),
|
||||
lerp(secondaryBase, Color.Black, 0.14f),
|
||||
),
|
||||
foreground = scheme.onSecondaryContainer,
|
||||
highlight = secondaryHighlight,
|
||||
scheme.onSecondaryContainer,
|
||||
glossSoft,
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
secondaryContainer,
|
||||
secondaryContainer.copy(alpha = if (secondaryContainer.luminance() > 0.5f) 0.92f else 1f)
|
||||
)
|
||||
),
|
||||
foreground = scheme.onSecondaryContainer,
|
||||
highlight = secondaryHighlight,
|
||||
glassBrush(lerp(secondaryBase, Color.White, 0.5f), secondaryBase),
|
||||
scheme.onSecondaryContainer,
|
||||
gloss,
|
||||
),
|
||||
)
|
||||
val secondaryShadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
8.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
secondaryBase.copy(alpha = 0.4f),
|
||||
secondaryBase.copy(alpha = 0.5f),
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
14.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.26f)
|
||||
secondaryBase.copy(alpha = 0.5f),
|
||||
secondaryBase.copy(alpha = 0.6f),
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
2.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.08f),
|
||||
shadowColor.copy(alpha = 0.1f)
|
||||
secondaryBase.copy(alpha = 0.3f),
|
||||
secondaryBase.copy(alpha = 0.35f),
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
8.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
secondaryBase.copy(alpha = 0.4f),
|
||||
secondaryBase.copy(alpha = 0.5f),
|
||||
),
|
||||
)
|
||||
val secondaryBorder = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(secondaryContainer.copy(alpha = 0.5f), 0.5.dp),
|
||||
hovered = BaseUITheme.Border(secondaryContainer.copy(alpha = 0.5f), 0.5.dp),
|
||||
pressed = BaseUITheme.Border(secondaryContainer.copy(alpha = 0.5f), 0.5.dp),
|
||||
focused = BaseUITheme.Border(secondaryContainer.copy(alpha = 0.5f), 0.5.dp),
|
||||
normal = BaseUITheme.Border(lerp(secondaryBase, Color.White, 0.5f), 1.dp),
|
||||
hovered = BaseUITheme.Border(lerp(secondaryBase, Color.White, 0.6f), 1.dp),
|
||||
pressed = BaseUITheme.Border(lerp(secondaryBase, Color.White, 0.4f), 1.dp),
|
||||
focused = BaseUITheme.Border(lerp(secondaryBase, Color.White, 0.5f), 1.dp),
|
||||
)
|
||||
|
||||
// --- Ghost -----------------------------------------------------------
|
||||
val ghostColors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(Color.Transparent, Color.Transparent)),
|
||||
background = glassBrush(Color.Transparent, Color.Transparent),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = Color.Transparent,
|
||||
),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
containerPressed.copy(alpha = 0.5f),
|
||||
containerPressed.copy(alpha = 0.5f)
|
||||
)
|
||||
background = glassBrush(
|
||||
lerp(scheme.surfaceContainerHigh, Color.White, 0.1f),
|
||||
scheme.surfaceContainer,
|
||||
),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = Color.Transparent,
|
||||
highlight = glossSoft,
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerPressed, containerPressed)),
|
||||
background = glassBrush(glassPressed, glassPressed),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = Color.Transparent,
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(Color.Transparent, Color.Transparent)),
|
||||
background = glassBrush(Color.Transparent, Color.Transparent),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = Color.Transparent,
|
||||
),
|
||||
@ -472,8 +482,8 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
val outlineStyle = BaseUITheme.ButtonStyle(
|
||||
outlineColors,
|
||||
defaultShapeState,
|
||||
outlineShadow,
|
||||
outlineBorder,
|
||||
glassShadow,
|
||||
glassBorderState,
|
||||
defaultButtonPadding
|
||||
)
|
||||
val primaryStyle = BaseUITheme.ButtonStyle(
|
||||
@ -501,8 +511,8 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
val outlineIconStyle = BaseUITheme.ButtonStyle(
|
||||
outlineColors,
|
||||
defaultShapeState,
|
||||
outlineShadow,
|
||||
outlineBorder,
|
||||
glassShadow,
|
||||
glassBorderState,
|
||||
iconButtonPadding
|
||||
)
|
||||
val primaryIconStyle = BaseUITheme.ButtonStyle(
|
||||
@ -534,20 +544,20 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
focused = scheme.onSurface,
|
||||
)
|
||||
|
||||
val checkBoxShape = RoundedCornerShape(6.dp)
|
||||
val checkBoxShape = RoundedCornerShape(7.dp)
|
||||
val checkBoxShapeState =
|
||||
BaseUITheme.InteractionState<Shape>(checkBoxShape, checkBoxShape, checkBoxShape, checkBoxShape)
|
||||
val noPadding =
|
||||
BaseUITheme.InteractionState(PaddingValues(0.dp), PaddingValues(0.dp), PaddingValues(0.dp), PaddingValues(0.dp))
|
||||
|
||||
val chipTabShape = RoundedCornerShape(10.dp)
|
||||
val chipTabShape = RoundedCornerShape(999.dp)
|
||||
val chipTabShapeState =
|
||||
BaseUITheme.InteractionState<Shape>(chipTabShape, chipTabShape, chipTabShape, chipTabShape)
|
||||
val chipTabPadding = BaseUITheme.InteractionState(
|
||||
PaddingValues(horizontal = 14.dp, vertical = 4.dp),
|
||||
PaddingValues(horizontal = 14.dp, vertical = 4.dp),
|
||||
PaddingValues(horizontal = 14.dp, vertical = 4.dp),
|
||||
PaddingValues(horizontal = 14.dp, vertical = 4.dp),
|
||||
PaddingValues(horizontal = 16.dp, vertical = 6.dp),
|
||||
PaddingValues(horizontal = 16.dp, vertical = 6.dp),
|
||||
PaddingValues(horizontal = 16.dp, vertical = 6.dp),
|
||||
PaddingValues(horizontal = 16.dp, vertical = 6.dp),
|
||||
)
|
||||
|
||||
val toggleShape = RoundedCornerShape(50)
|
||||
@ -575,16 +585,16 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
),
|
||||
textField = TextFieldTheme(
|
||||
background = BaseUITheme.InteractionState(
|
||||
normal = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
hovered = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
pressed = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
focused = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
normal = glassBrush(glassTop, glassBottom),
|
||||
hovered = glassBrush(glassTop, glassBottom),
|
||||
pressed = glassBrush(glassPressed, glassPressed),
|
||||
focused = glassBrush(glassTop, glassBottom),
|
||||
),
|
||||
highlight = BaseUITheme.InteractionState(
|
||||
normal = highlight,
|
||||
hovered = highlight,
|
||||
pressed = highlight,
|
||||
focused = highlight,
|
||||
normal = gloss,
|
||||
hovered = gloss,
|
||||
pressed = glossSoft,
|
||||
focused = Color.White.copy(alpha = if (isLight) 0.85f else 0.22f),
|
||||
),
|
||||
shape = BaseUITheme.InteractionState(
|
||||
normal = defaultShape,
|
||||
@ -593,53 +603,48 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
focused = defaultShape,
|
||||
),
|
||||
border = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(border.copy(alpha = 0.85f), 0.5.dp),
|
||||
hovered = BaseUITheme.Border(border.copy(alpha = 0.85f), 0.5.dp),
|
||||
pressed = BaseUITheme.Border(border, 0.5.dp),
|
||||
focused = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
normal = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
hovered = BaseUITheme.Border(glassEdge, 1.dp),
|
||||
pressed = BaseUITheme.Border(glassBorder.copy(alpha = 0.7f), 1.dp),
|
||||
focused = BaseUITheme.Border(primaryEdge, 1.5.dp),
|
||||
),
|
||||
shadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
8.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.26f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.26f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.14f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
9.dp,
|
||||
hovered = BaseUITheme.Shadow(
|
||||
10.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.2f),
|
||||
scheme.primary.copy(alpha = 0.25f)
|
||||
shadowColor.copy(alpha = 0.18f),
|
||||
shadowColor.copy(alpha = 0.22f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
4.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.1f),
|
||||
shadowColor.copy(alpha = 0.12f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
10.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.22f),
|
||||
scheme.primary.copy(alpha = 0.28f)
|
||||
),
|
||||
),
|
||||
padding = PaddingValues(horizontal = 14.dp, vertical = 10.dp),
|
||||
padding = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
|
||||
textStyle = TextStyle.Default,
|
||||
cursor = SolidColor(scheme.primary),
|
||||
foreground = textFieldForeground,
|
||||
),
|
||||
autoCompleteMenuTheme = AutoCompleteMenuTheme(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.surfaceContainerHigh,
|
||||
scheme.surfaceContainer
|
||||
)
|
||||
),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
border = BaseUITheme.Border(border, 0.5.dp),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
border = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
padding = PaddingValues(0.dp),
|
||||
shadowElevation = 8.dp,
|
||||
shadowElevation = 16.dp,
|
||||
),
|
||||
slider = SliderTheme(
|
||||
trackActiveColor = BaseUITheme.InteractionState(
|
||||
@ -649,10 +654,10 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
focused = scheme.primary,
|
||||
),
|
||||
trackInactiveColor = BaseUITheme.InteractionState(
|
||||
normal = border.copy(alpha = 0.6f),
|
||||
hovered = border.copy(alpha = 0.6f),
|
||||
pressed = border.copy(alpha = 0.6f),
|
||||
focused = border.copy(alpha = 0.6f),
|
||||
normal = glassBorder,
|
||||
hovered = glassBorder,
|
||||
pressed = glassBorder,
|
||||
focused = glassBorder,
|
||||
),
|
||||
thumbColor = BaseUITheme.InteractionState(
|
||||
normal = scheme.primary,
|
||||
@ -664,94 +669,44 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
normal = BaseUITheme.Shadow(
|
||||
5.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.35f),
|
||||
scheme.primary.copy(alpha = 0.4f)
|
||||
scheme.primary.copy(alpha = 0.4f),
|
||||
scheme.primary.copy(alpha = 0.45f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
8.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.4f),
|
||||
scheme.primary.copy(alpha = 0.45f),
|
||||
scheme.primary.copy(alpha = 0.5f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
2.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.2f),
|
||||
scheme.primary.copy(alpha = 0.25f)
|
||||
scheme.primary.copy(alpha = 0.25f),
|
||||
scheme.primary.copy(alpha = 0.3f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
5.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.35f),
|
||||
scheme.primary.copy(alpha = 0.4f)
|
||||
scheme.primary.copy(alpha = 0.4f),
|
||||
scheme.primary.copy(alpha = 0.45f)
|
||||
),
|
||||
),
|
||||
stepActiveColor = scheme.onPrimary.copy(alpha = 0.5f),
|
||||
stepActiveColor = Color.White.copy(alpha = 0.7f),
|
||||
stepInactiveColor = scheme.onSurface.copy(alpha = 0.25f),
|
||||
),
|
||||
checkBox = CheckBoxTheme(
|
||||
selected = BaseUITheme.ButtonStyle(
|
||||
colors = primaryColors,
|
||||
shape = checkBoxShapeState,
|
||||
shadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.3f),
|
||||
scheme.primary.copy(alpha = 0.35f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
8.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.4f),
|
||||
scheme.primary.copy(alpha = 0.45f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.2f),
|
||||
scheme.primary.copy(alpha = 0.25f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.3f),
|
||||
scheme.primary.copy(alpha = 0.35f)
|
||||
),
|
||||
),
|
||||
shadow = primaryShadow,
|
||||
border = primaryBorder,
|
||||
padding = noPadding,
|
||||
),
|
||||
unselected = BaseUITheme.ButtonStyle(
|
||||
colors = outlineColors,
|
||||
shape = checkBoxShapeState,
|
||||
shadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
3.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
5.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.2f),
|
||||
shadowColor.copy(alpha = 0.24f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.08f),
|
||||
shadowColor.copy(alpha = 0.1f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
3.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
),
|
||||
),
|
||||
border = outlineBorder,
|
||||
shadow = glassShadow,
|
||||
border = glassBorderState,
|
||||
padding = noPadding,
|
||||
),
|
||||
checkmarkColor = scheme.onPrimary,
|
||||
@ -767,131 +722,24 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
unselected = BaseUITheme.ButtonStyle(
|
||||
colors = outlineColors,
|
||||
shape = chipTabShapeState,
|
||||
shadow = outlineShadow,
|
||||
border = outlineBorder,
|
||||
shadow = glassShadow,
|
||||
border = glassBorderState,
|
||||
padding = chipTabPadding,
|
||||
),
|
||||
),
|
||||
toggle = BaseUITheme.ToggleTheme(
|
||||
checked = BaseUITheme.ButtonStyle(
|
||||
colors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.primary.copy(alpha = 0.85f),
|
||||
scheme.primary
|
||||
)
|
||||
),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(scheme.primary, scheme.primary)),
|
||||
foreground = scheme.onPrimary,
|
||||
highlight = Color.White.copy(alpha = 0.25f),
|
||||
),
|
||||
),
|
||||
colors = primaryColors,
|
||||
shape = toggleShapeState,
|
||||
shadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
4.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.3f),
|
||||
scheme.primary.copy(alpha = 0.35f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.4f),
|
||||
scheme.primary.copy(alpha = 0.45f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.2f),
|
||||
scheme.primary.copy(alpha = 0.25f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
4.dp,
|
||||
true,
|
||||
scheme.primary.copy(alpha = 0.3f),
|
||||
scheme.primary.copy(alpha = 0.35f)
|
||||
),
|
||||
),
|
||||
border = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
hovered = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
pressed = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
focused = BaseUITheme.Border(scheme.primary, 0.5.dp),
|
||||
),
|
||||
shadow = primaryShadow,
|
||||
border = primaryBorder,
|
||||
padding = togglePadding,
|
||||
),
|
||||
unchecked = BaseUITheme.ButtonStyle(
|
||||
colors = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
),
|
||||
hovered = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
),
|
||||
pressed = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerPressed, containerPressed)),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
),
|
||||
focused = BaseUITheme.ButtonColors(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
foreground = scheme.onSurface,
|
||||
highlight = highlight,
|
||||
),
|
||||
),
|
||||
colors = outlineColors,
|
||||
shape = toggleShapeState,
|
||||
shadow = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Shadow(
|
||||
4.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
),
|
||||
hovered = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.26f)
|
||||
),
|
||||
pressed = BaseUITheme.Shadow(
|
||||
1.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.08f),
|
||||
shadowColor.copy(alpha = 0.1f)
|
||||
),
|
||||
focused = BaseUITheme.Shadow(
|
||||
4.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
),
|
||||
),
|
||||
border = BaseUITheme.InteractionState(
|
||||
normal = BaseUITheme.Border(border, 0.5.dp),
|
||||
hovered = BaseUITheme.Border(border, 0.5.dp),
|
||||
pressed = BaseUITheme.Border(border.copy(alpha = 0.7f), 0.5.dp),
|
||||
focused = BaseUITheme.Border(border, 0.5.dp),
|
||||
),
|
||||
shadow = glassShadow,
|
||||
border = glassBorderState,
|
||||
padding = togglePadding,
|
||||
),
|
||||
thumb = BaseUITheme.InteractionState(
|
||||
@ -928,61 +776,62 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
),
|
||||
),
|
||||
card = BaseUITheme.CardTheme(
|
||||
background = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
border = BaseUITheme.Border(border, 0.5.dp),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
border = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
padding = PaddingValues(0.dp),
|
||||
shadow = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
12.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.15f),
|
||||
shadowColor.copy(alpha = 0.18f)
|
||||
shadowColor.copy(alpha = 0.16f),
|
||||
shadowColor.copy(alpha = 0.2f)
|
||||
),
|
||||
),
|
||||
listRowTile = BaseUITheme.ListRowTheme(
|
||||
background = BaseUITheme.AdvancedInteractionState(
|
||||
normal = Brush.verticalGradient(listOf(Color.Transparent, Color.Transparent)),
|
||||
hovered = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
pressed = Brush.verticalGradient(listOf(containerPressed, containerPressed)),
|
||||
focused = Brush.verticalGradient(listOf(containerLighter, containerDarker)),
|
||||
selected = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.primaryContainer.copy(alpha = 0.3f),
|
||||
scheme.primaryContainer.copy(alpha = 0.3f)
|
||||
)
|
||||
normal = glassBrush(Color.Transparent, Color.Transparent),
|
||||
hovered = glassBrush(glassTop, glassBottom),
|
||||
pressed = glassBrush(glassPressed, glassPressed),
|
||||
focused = glassBrush(glassTop, glassBottom),
|
||||
selected = glassBrush(
|
||||
lerp(scheme.primaryContainer, Color.White, 0.4f),
|
||||
scheme.primaryContainer,
|
||||
),
|
||||
disabled = Brush.verticalGradient(
|
||||
listOf(
|
||||
containerLighter.copy(alpha = 0.5f),
|
||||
containerDarker.copy(alpha = 0.5f)
|
||||
)
|
||||
disabled = glassBrush(
|
||||
glassTop.copy(alpha = 0.5f),
|
||||
glassBottom.copy(alpha = 0.5f),
|
||||
),
|
||||
),
|
||||
shape = BaseUITheme.AdvancedInteractionState(
|
||||
normal = RoundedCornerShape(8.dp),
|
||||
hovered = RoundedCornerShape(8.dp),
|
||||
pressed = RoundedCornerShape(8.dp),
|
||||
focused = RoundedCornerShape(8.dp),
|
||||
selected = RoundedCornerShape(8.dp),
|
||||
disabled = RoundedCornerShape(8.dp),
|
||||
normal = RoundedCornerShape(10.dp),
|
||||
hovered = RoundedCornerShape(10.dp),
|
||||
pressed = RoundedCornerShape(10.dp),
|
||||
focused = RoundedCornerShape(10.dp),
|
||||
selected = RoundedCornerShape(10.dp),
|
||||
disabled = RoundedCornerShape(10.dp),
|
||||
),
|
||||
border = BaseUITheme.AdvancedInteractionState(
|
||||
normal = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
hovered = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
hovered = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
pressed = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
focused = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
focused = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
selected = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
disabled = BaseUITheme.Border(Color.Transparent, 0.dp),
|
||||
),
|
||||
shadow = BaseUITheme.AdvancedInteractionState(
|
||||
normal = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
hovered = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
pressed = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
focused = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
selected = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
disabled = BaseUITheme.Shadow(0.dp, false, Color.Transparent, Color.Transparent),
|
||||
normal = noShadow,
|
||||
hovered = BaseUITheme.Shadow(
|
||||
6.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.12f),
|
||||
shadowColor.copy(alpha = 0.16f)
|
||||
),
|
||||
padding = PaddingValues(horizontal = 8.dp, vertical = 6.dp),
|
||||
pressed = noShadow,
|
||||
focused = noShadow,
|
||||
selected = noShadow,
|
||||
disabled = noShadow,
|
||||
),
|
||||
padding = PaddingValues(horizontal = 10.dp, vertical = 8.dp),
|
||||
textStyle = BaseUITheme.AdvancedInteractionState(
|
||||
normal = TextStyle.Default,
|
||||
hovered = TextStyle.Default,
|
||||
@ -1001,17 +850,12 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
),
|
||||
),
|
||||
dialog = BaseUITheme.DialogTheme(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.surface,
|
||||
scheme.surfaceContainerHigh,
|
||||
)
|
||||
),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
scrim = Color.Black.copy(alpha = 0.42f),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
border = BaseUITheme.Border(border, 0.5.dp),
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
border = BaseUITheme.Border(glassEdge, 1.dp),
|
||||
shadow = BaseUITheme.Shadow(
|
||||
24.dp,
|
||||
28.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.3f),
|
||||
shadowColor.copy(alpha = 0.4f)
|
||||
@ -1019,27 +863,20 @@ fun rememberBaseUITheme(): BaseUITheme {
|
||||
padding = PaddingValues(24.dp),
|
||||
),
|
||||
dropdownMenu = BaseUITheme.DropdownMenuTheme(
|
||||
background = Brush.verticalGradient(
|
||||
listOf(
|
||||
scheme.surfaceContainerHigh,
|
||||
scheme.surfaceContainer,
|
||||
)
|
||||
),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
border = BaseUITheme.Border(border, 0.5.dp),
|
||||
background = glassBrush(glassTop, glassBottom),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
border = BaseUITheme.Border(glassBorder, 1.dp),
|
||||
shadow = BaseUITheme.Shadow(
|
||||
12.dp,
|
||||
16.dp,
|
||||
true,
|
||||
shadowColor.copy(alpha = 0.2f),
|
||||
shadowColor.copy(alpha = 0.25f)
|
||||
),
|
||||
itemHoverBackground = Brush.verticalGradient(
|
||||
listOf(containerLighter, containerDarker)
|
||||
shadowColor.copy(alpha = 0.22f),
|
||||
shadowColor.copy(alpha = 0.28f)
|
||||
),
|
||||
itemHoverBackground = glassBrush(glassTop, glassBottom),
|
||||
itemForeground = scheme.onSurface,
|
||||
itemHighlight = highlight,
|
||||
padding = PaddingValues(4.dp),
|
||||
itemPadding = PaddingValues(horizontal = 14.dp, vertical = 10.dp),
|
||||
itemHighlight = gloss,
|
||||
padding = PaddingValues(6.dp),
|
||||
itemPadding = PaddingValues(horizontal = 14.dp, vertical = 11.dp),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -24,15 +24,27 @@ import androidx.compose.ui.unit.dp
|
||||
|
||||
fun Modifier.highlight(color: Color): Modifier =
|
||||
drawWithCache {
|
||||
val highlightBrush = Brush.verticalGradient(
|
||||
colors = listOf(color, Color.Transparent),
|
||||
// Frutiger-Aero glass: a bright specular sheen across the top half plus a
|
||||
// faint reflection rising from the bottom edge.
|
||||
val topGloss = Brush.verticalGradient(
|
||||
colors = listOf(color, color.copy(alpha = color.alpha * 0.25f), Color.Transparent),
|
||||
startY = 0f,
|
||||
endY = size.height * 0.5f,
|
||||
endY = size.height * 0.55f,
|
||||
)
|
||||
val bottomReflection = Brush.verticalGradient(
|
||||
colors = listOf(Color.Transparent, color.copy(alpha = color.alpha * 0.3f)),
|
||||
startY = size.height * 0.72f,
|
||||
endY = size.height,
|
||||
)
|
||||
onDrawWithContent {
|
||||
drawContent()
|
||||
drawRect(
|
||||
brush = highlightBrush,
|
||||
brush = topGloss,
|
||||
topLeft = androidx.compose.ui.geometry.Offset.Zero,
|
||||
size = size,
|
||||
)
|
||||
drawRect(
|
||||
brush = bottomReflection,
|
||||
topLeft = androidx.compose.ui.geometry.Offset.Zero,
|
||||
size = size,
|
||||
)
|
||||
|
||||
@ -50,9 +50,6 @@ import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.chrisbanes.haze.HazeState
|
||||
import dev.chrisbanes.haze.blur.HazeColorEffect
|
||||
import dev.chrisbanes.haze.blur.blurEffect
|
||||
import dev.chrisbanes.haze.hazeEffect
|
||||
import dev.krtirtho.spotube.NavigationItem
|
||||
import dev.krtirtho.spotube.core.navigation.NavigationState
|
||||
import dev.krtirtho.spotube.core.navigation.Navigator
|
||||
@ -85,21 +82,13 @@ fun AppSidebar(
|
||||
var expanded by rememberSaveable { mutableStateOf(true) }
|
||||
val width by animateDpAsState(targetValue = if (expanded) 236.dp else 86.dp)
|
||||
val currentLibraryTab by libraryState.currentTab.collectAsState()
|
||||
val surfaceTint = MaterialTheme.colorScheme.surface.copy(alpha = 0.85f)
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxHeight()
|
||||
.width(width)
|
||||
.hazeEffect(hazeState) {
|
||||
blurEffect {
|
||||
blurRadius = 20.dp
|
||||
colorEffects = listOf(
|
||||
HazeColorEffect.tint(surfaceTint)
|
||||
)
|
||||
}
|
||||
},
|
||||
.width(width),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user