diff --git a/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt b/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt index f634737..630f339 100644 --- a/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt +++ b/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt @@ -4,6 +4,7 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.border import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement @@ -158,8 +159,31 @@ internal const val BOARD_Y_FRACTION = 0.47f * merely looking tight at 427dp (Pixel emulator). Sizing from the container * makes five seats fit at any width by construction. */ -internal fun opponentSeatWidthDp(availableWidthDp: Float): Float = - (availableWidthDp * 0.16f).coerceIn(52f, 72f) +/** + * Competing treatments for an opponent seat, switchable at runtime so they can + * be compared on a real device instead of argued about from screenshots. + */ +enum class SeatStyle(val label: String) { + /** Avatar and fan stacked over a full-width name plate. Most information. */ + PLATE("Plate"), + + /** One horizontal pill: avatar beside a compact name and stack. */ + BADGE("Badge"), + + /** Avatar-led, name and stack tucked under it. Least width. */ + CHIP("Chip"); + + fun next(): SeatStyle = entries[(ordinal + 1) % entries.size] +} + +internal fun opponentSeatWidthDp( + availableWidthDp: Float, + style: SeatStyle = SeatStyle.PLATE, +): Float = when (style) { + SeatStyle.PLATE -> (availableWidthDp * 0.16f).coerceIn(52f, 72f) + SeatStyle.BADGE -> (availableWidthDp * 0.26f).coerceIn(88f, 112f) + SeatStyle.CHIP -> (availableWidthDp * 0.13f).coerceIn(44f, 58f) +} /** * Five seats spread edge to edge with equal gaps, staggered into three lanes so @@ -206,37 +230,63 @@ fun TableScreen(vm: PokerViewModel) { val tableTalk = state.visibleTableTalk() val status = snap?.let(::tableStatus) - Column( + // Raise sizing is hoisted here so it can overlay the felt. Left inside the + // control column it grew the controls, which shrank the weighted table and + // visibly reshaped the oval into a circle every time Raise was tapped. + var sizingRaise by remember(offer?.token) { mutableStateOf(false) } + var seatStyle by remember { mutableStateOf(SeatStyle.PLATE) } + + Box( modifier = Modifier .fillMaxSize() .background(Night) .systemBarsPadding(), ) { - TableHeader(snap, state.gameConfig) - PokerTable( - snapshot = snap, - status = status, - tableTalk = tableTalk, - handSummary = handSummary, - // Fill the space the two-stage raise control freed instead of locking - // an aspect ratio and leaving ~178dp of dead felt below the hero. - modifier = Modifier - .fillMaxWidth() - .weight(1f), - ) - TableControls( - offer = offer, - handSummary = handSummary, - nextHandRequested = state.nextHandRequested, - rebuyRequired = state.heroNeedsRebuy, - buyIn = state.gameConfig?.buyIn ?: DEFAULT_BUY_IN, - coachReview = coachReview, - heroFolded = snap?.seats?.firstOrNull { it.index == HERO_SEAT }?.folded == true, - onFold = vm::fold, - onCheckCall = vm::checkOrCall, - onRaise = vm::raiseTo, - onNextHand = vm::nextHand, - ) + Column(modifier = Modifier.fillMaxSize()) { + TableHeader( + snapshot = snap, + config = state.gameConfig, + seatStyle = seatStyle, + onCycleSeatStyle = { seatStyle = seatStyle.next() }, + ) + PokerTable( + snapshot = snap, + status = status, + tableTalk = tableTalk, + handSummary = handSummary, + seatStyle = seatStyle, + // Weighted against a control area whose height no longer changes, + // so the felt keeps one shape for the whole hand. + modifier = Modifier + .fillMaxWidth() + .weight(1f), + ) + TableControls( + offer = offer, + handSummary = handSummary, + nextHandRequested = state.nextHandRequested, + rebuyRequired = state.heroNeedsRebuy, + buyIn = state.gameConfig?.buyIn ?: DEFAULT_BUY_IN, + coachReview = coachReview, + heroFolded = snap?.seats?.firstOrNull { it.index == HERO_SEAT }?.folded == true, + onFold = vm::fold, + onCheckCall = vm::checkOrCall, + onOpenRaise = { sizingRaise = true }, + onNextHand = vm::nextHand, + ) + } + + if (sizingRaise && offer != null) { + RaiseSizingSheet( + offer = offer, + onDismiss = { sizingRaise = false }, + onRaise = { token, amount -> + sizingRaise = false + vm.raiseTo(token, amount) + }, + modifier = Modifier.align(Alignment.BottomCenter), + ) + } } } @@ -244,6 +294,8 @@ fun TableScreen(vm: PokerViewModel) { private fun TableHeader( snapshot: TableSnapshot?, config: CashGameConfig?, + seatStyle: SeatStyle, + onCycleSeatStyle: () -> Unit, ) { Row( modifier = Modifier @@ -253,7 +305,10 @@ private fun TableHeader( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { - Column(verticalArrangement = Arrangement.spacedBy(1.dp)) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(1.dp), + ) { Text( "HAND ${snapshot?.handNumber ?: 1}", color = Cream, @@ -268,6 +323,26 @@ private fun TableHeader( letterSpacing = 1.4.sp, ) } + Surface( + modifier = Modifier + .padding(end = 8.dp) + .clickable(onClick = onCycleSeatStyle), + shape = RoundedCornerShape(50), + color = Color.White.copy(alpha = 0.10f), + border = androidx.compose.foundation.BorderStroke( + 1.dp, + TableGold.copy(alpha = 0.45f), + ), + ) { + Text( + "SEATS · ${seatStyle.label.uppercase()}", + modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp), + color = TableGold, + fontWeight = FontWeight.Bold, + fontSize = 10.sp, + letterSpacing = 1.sp, + ) + } Surface( shape = RoundedCornerShape(50), color = Color.Black.copy(alpha = 0.24f), @@ -297,6 +372,7 @@ private fun PokerTable( status: TableStatus?, tableTalk: com.jsjdesigns.poker.bot.TableTalkLine?, handSummary: HandSummary?, + seatStyle: SeatStyle, modifier: Modifier = Modifier, ) { val seats = snapshot?.seats.orEmpty() @@ -313,7 +389,7 @@ private fun PokerTable( // Seat width and position both come from the measured table, so five // seats fit with real gaps on a 384dp phone as well as a 427dp emulator. - val seatWidth = opponentSeatWidthDp(maxWidth.value) + val seatWidth = opponentSeatWidthDp(maxWidth.value, seatStyle) val placements = opponentSeatPlacements(maxWidth.value, seatWidth) seats.filter { it.index != HERO_SEAT } .forEachIndexed { index, seat -> @@ -323,6 +399,7 @@ private fun PokerTable( isTurn = snapshot?.toAct == seat.index, isWinner = seat.index in winners, width = seatWidth.dp, + style = seatStyle, modifier = Modifier.offset( x = placement.leftDp.dp, // Placement gives where the avatar centre belongs on the @@ -424,6 +501,35 @@ private fun TableFelt(modifier: Modifier = Modifier) { @Composable private fun OpponentSeat( + seat: SeatSnapshot, + isTurn: Boolean, + isWinner: Boolean, + width: Dp, + style: SeatStyle, + modifier: Modifier = Modifier, +) { + when (style) { + SeatStyle.PLATE -> PlateSeat(seat, isTurn, isWinner, width, modifier) + SeatStyle.BADGE -> BadgeSeat(seat, isTurn, isWinner, width, modifier) + SeatStyle.CHIP -> ChipSeat(seat, isTurn, isWinner, width, modifier) + } +} + +private fun seatHighlight(isTurn: Boolean, isWinner: Boolean): Color = when { + isWinner -> TableGold + isTurn -> GoldLight + else -> Color.White.copy(alpha = 0.12f) +} + +@Composable +private fun seatStackLabel(seat: SeatSnapshot): String = when { + seat.folded -> "folded" + seat.allIn -> "ALL IN" + else -> "${seat.stack}" +} + +@Composable +private fun PlateSeat( seat: SeatSnapshot, isTurn: Boolean, isWinner: Boolean, @@ -444,11 +550,7 @@ private fun OpponentSeat( verticalArrangement = Arrangement.spacedBy(4.dp), ) { Box(contentAlignment = Alignment.Center) { - val highlight = when { - isWinner -> TableGold - isTurn -> GoldLight - else -> Color.White.copy(alpha = 0.12f) - } + val highlight = seatHighlight(isTurn, isWinner) Box( modifier = Modifier .border( @@ -538,6 +640,152 @@ private fun OpponentSeat( } } +/** + * Badge: one horizontal pill, avatar beside a compact name and stack. + * + * Trades vertical height for width. The seat occupies about one row instead of + * three, which leaves more open felt between the arc and the pot. + */ +@Composable +private fun BadgeSeat( + seat: SeatSnapshot, + isTurn: Boolean, + isWinner: Boolean, + width: Dp, + modifier: Modifier = Modifier, +) { + val faded = seat.folded && !isWinner + val avatar = (width * 0.42f).coerceIn(30.dp, 42.dp) + Column( + modifier = modifier.width(width).alpha(if (faded) 0.4f else 1f), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(3.dp), + ) { + Box(contentAlignment = Alignment.CenterStart) { + if (!seat.folded && !(seat.revealed && seat.hole != null)) { + HoleCardFan( + cardWidth = (width * 0.21f).coerceIn(16.dp, 24.dp), + modifier = Modifier.align(Alignment.CenterEnd).offset(x = 4.dp), + ) + } + Surface( + shape = RoundedCornerShape(50), + color = Panel, + border = androidx.compose.foundation.BorderStroke( + if (isTurn || isWinner) 2.dp else 1.dp, + seatHighlight(isTurn, isWinner), + ), + ) { + Row( + modifier = Modifier.padding(end = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp), + ) { + OpponentAvatar(seat, size = avatar) + Column(modifier = Modifier.weight(1f, fill = false)) { + Text( + seat.name, + color = Cream, + fontWeight = FontWeight.Bold, + fontSize = 10.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + seatStackLabel(seat), + color = if (seat.folded) Muted.copy(alpha = 0.7f) else TableGold, + fontWeight = FontWeight.Bold, + fontSize = 11.sp, + ) + } + } + } + if (seat.isButton) { + DealerButton(Modifier.align(Alignment.BottomStart).offset(y = 6.dp)) + } + } + if (seat.revealed && seat.hole != null) { + Row(horizontalArrangement = Arrangement.spacedBy(3.dp)) { + repeat(2) { i -> + CardImage( + seat.hole?.getOrNull(i), + Modifier.size((width * 0.34f).coerceIn(26.dp, 40.dp), (width * 0.51f).coerceIn(39.dp, 60.dp)), + ) + } + } + } + if (seat.committedThisRound > 0 && !seat.folded) BetMarker(seat.committedThisRound) + } +} + +/** + * Chip: avatar-led with the name and stack tucked beneath. + * + * The narrowest option, which buys the most separation between neighbours on a + * small screen at the cost of showing less at a glance. + */ +@Composable +private fun ChipSeat( + seat: SeatSnapshot, + isTurn: Boolean, + isWinner: Boolean, + width: Dp, + modifier: Modifier = Modifier, +) { + val faded = seat.folded && !isWinner + Column( + modifier = modifier.width(width).alpha(if (faded) 0.4f else 1f), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { + Box(contentAlignment = Alignment.Center) { + if (!seat.folded && !(seat.revealed && seat.hole != null)) { + HoleCardFan( + cardWidth = (width * 0.30f).coerceIn(16.dp, 22.dp), + modifier = Modifier.align(Alignment.TopEnd).offset(x = 10.dp, y = (-6).dp), + ) + } + Box( + modifier = Modifier.border( + width = if (isTurn || isWinner) 2.dp else 1.dp, + color = seatHighlight(isTurn, isWinner), + shape = CircleShape, + ).padding(2.dp), + ) { + OpponentAvatar(seat, size = (width * 0.78f).coerceIn(34.dp, 46.dp)) + } + if (seat.isButton) { + DealerButton(Modifier.align(Alignment.BottomStart).offset(x = (-6).dp, y = 4.dp)) + } + } + if (seat.revealed && seat.hole != null) { + Row(horizontalArrangement = Arrangement.spacedBy(2.dp)) { + repeat(2) { i -> + CardImage( + seat.hole?.getOrNull(i), + Modifier.size((width * 0.44f).coerceIn(22.dp, 32.dp), (width * 0.66f).coerceIn(33.dp, 48.dp)), + ) + } + } + } + Text( + seat.name, + color = Cream, + fontWeight = FontWeight.Bold, + fontSize = 10.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + seatStackLabel(seat), + color = if (seat.folded) Muted.copy(alpha = 0.7f) else TableGold, + fontWeight = FontWeight.Bold, + fontSize = 11.sp, + ) + if (seat.committedThisRound > 0 && !seat.folded) BetMarker(seat.committedThisRound) + } +} + /** * Two face-down cards fanned like a real hand. * @@ -870,7 +1118,7 @@ private fun TableControls( heroFolded: Boolean, onFold: (Long) -> Unit, onCheckCall: (Long) -> Unit, - onRaise: (Long, Int) -> Unit, + onOpenRaise: () -> Unit, onNextHand: (Int) -> Unit, ) { Surface( @@ -878,7 +1126,7 @@ private fun TableControls( color = Night, ) { when { - offer != null -> DecisionControls(offer, onFold, onCheckCall, onRaise) + offer != null -> DecisionControls(offer, onFold, onCheckCall, onOpenRaise) handSummary != null -> CompletionControls( summary = handSummary, nextHandRequested = nextHandRequested, @@ -908,158 +1156,174 @@ private fun DecisionControls( offer: DecisionOffer, onFold: (Long) -> Unit, onCheckCall: (Long) -> Unit, - onRaise: (Long, Int) -> Unit, + onOpenRaise: () -> Unit, ) { val buttons = buttonsFor(offer) - var sizingRaise by remember(offer.token) { mutableStateOf(false) } - var raiseTo by remember(offer.token) { mutableIntStateOf(buttons.fixedRaiseTo) } - - BackHandler(enabled = sizingRaise) { - sizingRaise = false - } - Column( modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 10.dp), + ) { + PrimaryDecisionButtons( + offer = offer, + buttons = buttons, + onFold = onFold, + onCheckCall = onCheckCall, + onOpenRaise = onOpenRaise, + ) + } +} + +/** + * Raise sizing, presented as a sheet over the felt. + * + * It must not live in the control column: growing that column shrinks the + * weighted table above it, which visibly reshapes the oval every time Raise is + * tapped. Overlaying leaves the table untouched. + */ +@Composable +private fun RaiseSizingSheet( + offer: DecisionOffer, + onDismiss: () -> Unit, + onRaise: (Long, Int) -> Unit, + modifier: Modifier = Modifier, +) { + val buttons = buttonsFor(offer) + var raiseTo by remember(offer.token) { mutableIntStateOf(buttons.fixedRaiseTo) } + BackHandler(enabled = true) { onDismiss() } + + Column( + modifier = modifier .fillMaxWidth() .background( Brush.verticalGradient( - listOf(Color.Transparent, Night.copy(alpha = 0.95f), Night), + listOf(Color.Transparent, Night.copy(alpha = 0.97f), Night), ), ) .padding(horizontal = 14.dp, vertical = 10.dp), verticalArrangement = Arrangement.spacedBy(CONTROL_GAP), ) { - if (!sizingRaise) { - PrimaryDecisionButtons( - offer = offer, - buttons = buttons, - onFold = onFold, - onCheckCall = onCheckCall, - onOpenRaise = { sizingRaise = true }, - ) - } else { - val amount = raiseConfirmationAmount(buttons, raiseTo) + val amount = raiseConfirmationAmount(buttons, raiseTo) + Row( + modifier = Modifier + .fillMaxWidth() + .height(TOUCH_TARGET), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + BackToActionsButton { onDismiss() } + Column(horizontalAlignment = Alignment.End) { + Text( + "RAISE TO", + color = Muted, + fontWeight = FontWeight.Bold, + fontSize = 12.sp, + letterSpacing = 1.4.sp, + ) + Text( + "$amount", + color = GoldLight, + fontWeight = FontWeight.ExtraBold, + fontSize = 24.sp, + ) + } + } + + if (buttons.showSlider) { Row( modifier = Modifier .fillMaxWidth() .height(TOUCH_TARGET), - horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - BackToActionsButton { sizingRaise = false } - Column(horizontalAlignment = Alignment.End) { - Text( - "RAISE TO", - color = Muted, - fontWeight = FontWeight.Bold, - fontSize = 12.sp, - letterSpacing = 1.4.sp, - ) - Text( - "$amount", - color = GoldLight, - fontWeight = FontWeight.ExtraBold, - fontSize = 24.sp, + FineTuneButton("−") { + raiseTo = adjustRaiseAmount(raiseTo, -1, buttons) + } + // A Slider draws a ~16dp track inside a 48dp accessibility touch + // target, so 32dp of it is invisible. Laying it out at 48dp adds + // 16dp of phantom space above and below, which is why a uniform + // gap rendered as ~20dp around the slider and ~4dp between the + // filled buttons. Reserve only the visible height and let the + // touch target overflow, so declared gaps are the real gaps. + Box( + modifier = Modifier + .weight(1f) + .height(SLIDER_VISIBLE_HEIGHT), + contentAlignment = Alignment.Center, + ) { + Slider( + value = amount.toFloat(), + onValueChange = { raiseTo = it.roundToInt() }, + valueRange = buttons.sliderMin.toFloat()..buttons.sliderMax.toFloat(), + colors = SliderDefaults.colors( + thumbColor = GoldLight, + activeTrackColor = TableGold, + inactiveTrackColor = Color.White.copy(alpha = 0.12f), + ), + modifier = Modifier.requiredHeight(TOUCH_TARGET), ) } + FineTuneButton("+") { + raiseTo = adjustRaiseAmount(raiseTo, 1, buttons) + } } - - if (buttons.showSlider) { - Row( - modifier = Modifier - .fillMaxWidth() - .height(TOUCH_TARGET), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - FineTuneButton("−") { - raiseTo = adjustRaiseAmount(raiseTo, -1, buttons) - } - // A Slider draws a ~16dp track inside a 48dp accessibility touch - // target, so 32dp of it is invisible. Laying it out at 48dp adds - // 16dp of phantom space above and below, which is why a uniform - // gap rendered as ~20dp around the slider and ~4dp between the - // filled buttons. Reserve only the visible height and let the - // touch target overflow, so declared gaps are the real gaps. - Box( + val presets = raisePresets(offer, buttons) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp), + ) { + presets.forEach { preset -> + Button( + onClick = { raiseTo = preset.amount }, modifier = Modifier .weight(1f) - .height(SLIDER_VISIBLE_HEIGHT), - contentAlignment = Alignment.Center, + .height(48.dp), + contentPadding = PaddingValues(horizontal = 4.dp), + colors = ButtonDefaults.buttonColors( + containerColor = if (amount == preset.amount) { + TableGold.copy(alpha = 0.2f) + } else { + Color.White.copy(alpha = 0.12f) + }, + contentColor = if (amount == preset.amount) GoldLight else Muted, + ), + shape = RoundedCornerShape(9.dp), ) { - Slider( - value = amount.toFloat(), - onValueChange = { raiseTo = it.roundToInt() }, - valueRange = buttons.sliderMin.toFloat()..buttons.sliderMax.toFloat(), - colors = SliderDefaults.colors( - thumbColor = GoldLight, - activeTrackColor = TableGold, - inactiveTrackColor = Color.White.copy(alpha = 0.12f), - ), - modifier = Modifier.requiredHeight(TOUCH_TARGET), + Text( + "${preset.label} ${preset.amount}", + fontWeight = FontWeight.Bold, + fontSize = 11.sp, + maxLines = 1, ) } - FineTuneButton("+") { - raiseTo = adjustRaiseAmount(raiseTo, 1, buttons) - } } - val presets = raisePresets(offer, buttons) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(6.dp), - ) { - presets.forEach { preset -> - Button( - onClick = { raiseTo = preset.amount }, - modifier = Modifier - .weight(1f) - .height(48.dp), - contentPadding = PaddingValues(horizontal = 4.dp), - colors = ButtonDefaults.buttonColors( - containerColor = if (amount == preset.amount) { - TableGold.copy(alpha = 0.2f) - } else { - Color.White.copy(alpha = 0.12f) - }, - contentColor = if (amount == preset.amount) GoldLight else Muted, - ), - shape = RoundedCornerShape(9.dp), - ) { - Text( - "${preset.label} ${preset.amount}", - fontWeight = FontWeight.Bold, - fontSize = 11.sp, - maxLines = 1, - ) - } - } - } - } else { - Text( - if (amount >= buttons.sliderMax) { - "Your stack leaves one legal raise: all in for $amount." - } else { - "There is one legal raise size: $amount." - }, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), - color = Cream.copy(alpha = 0.82f), - fontSize = 13.sp, - textAlign = TextAlign.Center, - ) } - - Spacer(Modifier.height(GROUP_GAP - CONTROL_GAP)) - ActionButton( - title = if (amount >= buttons.sliderMax) "Confirm all in" else "Confirm raise", - detail = if (amount >= buttons.sliderMax) "$amount" else "to $amount", - container = Brush.verticalGradient(listOf(GoldLight, Color(0xFFC79A38))), - content = Color(0xFF22190A), - modifier = Modifier.fillMaxWidth(), - onClick = { onRaise(offer.token, amount) }, + } else { + Text( + if (amount >= buttons.sliderMax) { + "Your stack leaves one legal raise: all in for $amount." + } else { + "There is one legal raise size: $amount." + }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + color = Cream.copy(alpha = 0.82f), + fontSize = 13.sp, + textAlign = TextAlign.Center, ) } + + Spacer(Modifier.height(GROUP_GAP - CONTROL_GAP)) + ActionButton( + title = if (amount >= buttons.sliderMax) "Confirm all in" else "Confirm raise", + detail = if (amount >= buttons.sliderMax) "$amount" else "to $amount", + container = Brush.verticalGradient(listOf(GoldLight, Color(0xFFC79A38))), + content = Color(0xFF22190A), + modifier = Modifier.fillMaxWidth(), + onClick = { onRaise(offer.token, amount) }, + ) } } @@ -1448,9 +1712,10 @@ private fun CardImage(index: Int?, modifier: Modifier) { Image( painter = painterResource(if (index != null) cardFace(index) else cardBack()), contentDescription = index?.let { Card(it).toString() } ?: "Face-down card", + // No clip and no backing plate: the artwork is already a rounded card + // with its own border, drawn at the same 2:3 ratio it is laid out at. + // Clipping again at a different radius cut into that border. contentScale = ContentScale.Fit, - modifier = modifier - .clip(RoundedCornerShape(6.dp)) - .background(Color(0xFFFFFDF8)), + modifier = modifier, ) }