feat(ui): рестайл общих компонентов под дизайн-систему

- StationCard: обложка/иконка-заглушка, анимированное сердечко, pressScale
- MiniPlayer: elevated-бар, метка «СЕЙЧАС ИГРАЕТ», Crossfade play/pause
- SearchBar: surface-поле, акцентный курсор, скругление 14
- FilterChips: акцентный активный чип с анимацией цвета
- EmptyState: иконка-плашка + текст
- TrackListItem: thumb-заглушка, pressScale
This commit is contained in:
nk
2026-06-02 21:17:28 +03:00
parent ae406554de
commit d652dc399a
6 changed files with 276 additions and 122 deletions

View File

@@ -1,27 +1,49 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.MaterialTheme import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Radio
import com.radiola.ui.theme.RadiolaTheme
@Composable @Composable
fun EmptyState( fun EmptyState(
message: String, message: String,
modifier: Modifier = Modifier modifier: Modifier = Modifier,
icon: ImageVector = Lucide.Radio
) { ) {
val colors = RadiolaTheme.colors
Box( Box(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize().padding(32.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(
modifier = Modifier
.size(72.dp)
.clip(RoundedCornerShape(24.dp))
.background(colors.surface2),
contentAlignment = Alignment.Center
) {
Icon(icon, contentDescription = null, tint = colors.textMuted, modifier = Modifier.size(32.dp))
}
Spacer(Modifier.height(16.dp))
Text( Text(
text = message, text = message,
style = MaterialTheme.typography.bodyLarge, style = androidx.compose.material3.MaterialTheme.typography.bodyLarge,
color = Color(0xFF888888) color = colors.textSecondary,
textAlign = TextAlign.Center
) )
} }
}
} }

View File

@@ -1,13 +1,28 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.* import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.radiola.ui.theme.Motion
import com.radiola.ui.theme.RadiolaTheme
@Composable @Composable
fun FilterChips( fun FilterChips(
@@ -18,22 +33,49 @@ fun FilterChips(
) { ) {
LazyRow( LazyRow(
modifier = modifier, modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(9.dp),
contentPadding = PaddingValues(horizontal = 16.dp) contentPadding = PaddingValues(horizontal = 16.dp)
) { ) {
item { item {
FilterChip( Chip(label = "Все", selected = selectedTag == null) { onTagSelected(null) }
selected = selectedTag == null,
onClick = { onTagSelected(null) },
label = { Text("Все") }
)
} }
items(tags) { tag -> items(tags) { tag ->
FilterChip( Chip(label = tag, selected = selectedTag == tag) { onTagSelected(tag) }
selected = selectedTag == tag,
onClick = { onTagSelected(tag) },
label = { Text(tag) }
)
} }
} }
} }
@Composable
private fun Chip(label: String, selected: Boolean, onClick: () -> Unit) {
val colors = RadiolaTheme.colors
val bg by animateColorAsState(
targetValue = if (selected) colors.accent else colors.surface2,
animationSpec = tween(Motion.Medium),
label = "chipBg"
)
val fg by animateColorAsState(
targetValue = if (selected) colors.bgBase else colors.textSecondary,
animationSpec = tween(Motion.Medium),
label = "chipFg"
)
Text(
text = label,
color = fg,
fontWeight = FontWeight.SemiBold,
style = androidx.compose.material3.MaterialTheme.typography.labelLarge,
modifier = Modifier
.clip(RoundedCornerShape(18.dp))
.background(bg)
.border(
width = if (selected) 0.dp else 1.dp,
color = if (selected) Color.Transparent else colors.border,
shape = RoundedCornerShape(18.dp)
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onClick
)
.padding(horizontal = 16.dp, vertical = 9.dp)
)
}

View File

@@ -1,24 +1,33 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.composables.icons.lucide.Lucide import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Pause import com.composables.icons.lucide.Pause
import com.composables.icons.lucide.Play import com.composables.icons.lucide.Play
import com.composables.icons.lucide.Radio
import com.radiola.domain.model.Track import com.radiola.domain.model.Track
import com.radiola.ui.theme.Motion
import com.radiola.ui.theme.RadiolaTheme
import com.radiola.ui.theme.pressScale
@Composable @Composable
fun MiniPlayer( fun MiniPlayer(
@@ -29,42 +38,76 @@ fun MiniPlayer(
onPlayPause: () -> Unit, onPlayPause: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val colors = RadiolaTheme.colors
Row( Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.height(64.dp) .padding(horizontal = 16.dp)
.background(Color(0xFF1E1E1E)) .clip(RoundedCornerShape(18.dp))
.background(colors.elevated)
.border(1.dp, colors.border, RoundedCornerShape(18.dp))
.clickable(onClick = onClick) .clickable(onClick = onClick)
.padding(horizontal = 16.dp), .padding(8.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
AsyncImage( Box(
model = track?.coverUrl,
contentDescription = null,
modifier = Modifier modifier = Modifier
.size(48.dp) .size(48.dp)
.clip(RoundedCornerShape(6.dp)) .clip(RoundedCornerShape(12.dp))
.background(colors.surface2),
contentAlignment = Alignment.Center
) {
if (track?.coverUrl != null) {
AsyncImage(
model = track.coverUrl,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
) )
Spacer(modifier = Modifier.width(12.dp)) } else {
Icon(Lucide.Radio, null, tint = colors.textSecondary, modifier = Modifier.size(20.dp))
}
}
Spacer(Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = stationName, text = "СЕЙЧАС ИГРАЕТ",
style = MaterialTheme.typography.bodyMedium, color = colors.accent,
maxLines = 1 fontSize = 9.sp,
fontWeight = FontWeight.SemiBold,
letterSpacing = 1.sp
) )
Spacer(Modifier.height(2.dp))
Text( Text(
text = track?.let { "${it.artist}${it.song}" } ?: "", text = track?.let { "${it.artist}${it.song}" } ?: stationName,
style = MaterialTheme.typography.labelMedium, style = androidx.compose.material3.MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), color = colors.textPrimary,
maxLines = 1 maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
) )
} }
IconButton(onClick = onPlayPause) { Spacer(Modifier.width(8.dp))
Box(
modifier = Modifier
.pressScale()
.size(44.dp)
.clip(RoundedCornerShape(22.dp))
.background(colors.accent)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onPlayPause
),
contentAlignment = Alignment.Center
) {
Crossfade(targetState = isPlaying, animationSpec = tween(Motion.Fast), label = "miniPlay") { playing ->
Icon( Icon(
imageVector = if (isPlaying) Lucide.Pause else Lucide.Play, imageVector = if (playing) Lucide.Pause else Lucide.Play,
contentDescription = if (isPlaying) "Pause" else "Play", contentDescription = if (playing) "Пауза" else "Играть",
tint = Color.White tint = colors.bgBase,
modifier = Modifier.size(20.dp)
) )
} }
} }
}
} }

View File

@@ -1,10 +1,8 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
@@ -14,6 +12,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Lucide import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Search import com.composables.icons.lucide.Search
import com.radiola.ui.theme.RadiolaTheme
@Composable @Composable
fun SearchBar( fun SearchBar(
@@ -22,22 +21,23 @@ fun SearchBar(
placeholder: String = "Поиск станции...", placeholder: String = "Поиск станции...",
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val colors = RadiolaTheme.colors
TextField( TextField(
value = query, value = query,
onValueChange = onQueryChange, onValueChange = onQueryChange,
modifier = modifier modifier = modifier.fillMaxWidth(),
.fillMaxWidth() shape = RoundedCornerShape(14.dp),
.background(Color(0xFF2A2A2A), RoundedCornerShape(8.dp)), placeholder = { Text(placeholder, color = colors.textMuted) },
placeholder = { Text(placeholder, color = Color(0xFF888888)) }, leadingIcon = { Icon(Lucide.Search, contentDescription = null, tint = colors.textMuted) },
leadingIcon = { Icon(Lucide.Search, contentDescription = null, tint = Color(0xFF888888)) },
singleLine = true, singleLine = true,
colors = TextFieldDefaults.colors( colors = TextFieldDefaults.colors(
focusedContainerColor = Color(0xFF2A2A2A), focusedContainerColor = colors.surface,
unfocusedContainerColor = Color(0xFF2A2A2A), unfocusedContainerColor = colors.surface,
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
focusedTextColor = Color.White, cursorColor = colors.accent,
unfocusedTextColor = Color.White focusedTextColor = colors.textPrimary,
unfocusedTextColor = colors.textPrimary
) )
) )
} }

View File

@@ -1,27 +1,31 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.composables.icons.lucide.Heart import com.composables.icons.lucide.Heart
import com.composables.icons.lucide.Lucide import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Radio
import com.radiola.domain.model.Station import com.radiola.domain.model.Station
import com.radiola.ui.theme.Motion
import com.radiola.ui.theme.RadiolaTheme
import com.radiola.ui.theme.pressScale
@Composable @Composable
fun StationCard( fun StationCard(
@@ -31,61 +35,76 @@ fun StationCard(
onFavoriteClick: () -> Unit, onFavoriteClick: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Card( val colors = RadiolaTheme.colors
val interaction = remember { MutableInteractionSource() }
val heartTint by animateColorAsState(
targetValue = if (isFavorite) colors.accent else colors.textPrimary,
animationSpec = tween(Motion.Medium),
label = "heartTint"
)
Column(
modifier = modifier modifier = modifier
.aspectRatio(1f) .pressScale(interactionSource = interaction)
.clickable(onClick = onClick), .clickable(interactionSource = interaction, indication = null, onClick = onClick)
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(containerColor = Color(0xFF1E1E1E))
) { ) {
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.fillMaxSize()) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.weight(1f) .aspectRatio(1f)
.clip(RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)) .clip(RoundedCornerShape(16.dp))
.background( .background(colors.surface2)
Brush.linearGradient(
colors = listOf(
Color(0xFF667eea),
Color(0xFF764ba2)
)
)
)
) { ) {
if (!station.coverUrl.isNullOrBlank()) {
AsyncImage( AsyncImage(
model = station.coverUrl, model = station.coverUrl,
contentDescription = station.name, contentDescription = station.name,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop contentScale = ContentScale.Crop
) )
} } else {
Text( Icon(
text = station.name, Lucide.Radio,
style = MaterialTheme.typography.bodyMedium, contentDescription = null,
modifier = Modifier.padding(12.dp), tint = colors.textMuted,
maxLines = 1 modifier = Modifier.align(Alignment.Center).size(34.dp)
) )
} }
IconButton( Box(
onClick = onFavoriteClick,
modifier = Modifier modifier = Modifier
.align(Alignment.TopEnd) .align(Alignment.TopEnd)
.padding(4.dp) .padding(10.dp)
.size(32.dp) .size(32.dp)
.background( .clip(RoundedCornerShape(16.dp))
color = Color.Black.copy(alpha = 0.4f), .background(androidx.compose.ui.graphics.Color.Black.copy(alpha = 0.4f))
shape = RoundedCornerShape(8.dp) .clickable(onClick = onFavoriteClick),
) contentAlignment = Alignment.Center
) { ) {
Icon( Icon(
imageVector = Lucide.Heart, imageVector = Lucide.Heart,
contentDescription = if (isFavorite) "В избранном" else "Добавить в избранное", contentDescription = if (isFavorite) "В избранном" else "В избранное",
tint = if (isFavorite) Color(0xFFFF4081) else Color.White, tint = heartTint,
modifier = Modifier.size(18.dp) modifier = Modifier.size(17.dp)
) )
} }
} }
Spacer(Modifier.height(10.dp))
Text(
text = station.name,
style = androidx.compose.material3.MaterialTheme.typography.titleMedium,
color = colors.textPrimary,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
if (station.genre.isNotBlank()) {
Text(
text = station.genre,
style = androidx.compose.material3.MaterialTheme.typography.labelMedium,
color = colors.textSecondary,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
fontWeight = FontWeight.Normal
)
}
} }
} }

View File

@@ -1,17 +1,26 @@
package com.radiola.ui.components package com.radiola.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Music
import com.radiola.domain.model.Track import com.radiola.domain.model.Track
import com.radiola.ui.theme.RadiolaTheme
import com.radiola.ui.theme.pressScale
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -23,38 +32,57 @@ fun TrackListItem(
onClick: () -> Unit = {}, onClick: () -> Unit = {},
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val colors = RadiolaTheme.colors
val interaction = remember { MutableInteractionSource() }
Row( Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.clickable(onClick = onClick) .pressScale(interactionSource = interaction)
.padding(horizontal = 16.dp, vertical = 10.dp), .clickable(interactionSource = interaction, indication = null, onClick = onClick)
.padding(horizontal = 16.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Box(
modifier = Modifier
.size(44.dp)
.clip(RoundedCornerShape(10.dp))
.background(colors.surface2),
contentAlignment = Alignment.Center
) {
if (!track.coverUrl.isNullOrBlank()) {
AsyncImage( AsyncImage(
model = track.coverUrl, model = track.coverUrl,
contentDescription = null, contentDescription = null,
modifier = Modifier modifier = Modifier.fillMaxSize(),
.size(48.dp) contentScale = ContentScale.Crop
.clip(RoundedCornerShape(8.dp))
) )
} else {
Icon(Lucide.Music, null, tint = colors.textSecondary, modifier = Modifier.size(20.dp))
}
}
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = "${track.artist}${track.song}", text = "${track.artist}${track.song}",
style = MaterialTheme.typography.bodyMedium, style = androidx.compose.material3.MaterialTheme.typography.titleMedium,
maxLines = 1 color = colors.textPrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
) )
Text( Text(
text = track.stationName, text = track.stationName,
style = MaterialTheme.typography.labelMedium, style = androidx.compose.material3.MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) color = colors.textSecondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
) )
} }
timestamp?.let { timestamp?.let {
Spacer(Modifier.width(8.dp))
Text( Text(
text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(it)), text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(it)),
style = MaterialTheme.typography.labelMedium, style = androidx.compose.material3.MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f) color = colors.textMuted
) )
} }
} }