From 65805a15af3dbd85712c6706219c07d3385fe1ba Mon Sep 17 00:00:00 2001 From: b-dev-mobile Date: Thu, 9 Jul 2026 21:20:26 +0000 Subject: [PATCH] =?UTF-8?q?design(calendar):=20=D0=BC=D0=B5=D1=81=D1=8F?= =?UTF-8?q?=D1=87=D0=BD=D0=B0=D1=8F=20=D1=81=D0=B5=D1=82=D0=BA=D0=B0=201:1?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=B6=D0=B8=D0=B2=D0=BE=D0=B9=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BC=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _calendar-month-view-mobile.css: месяц — белая карточка r12 с рамкой и паддингом 12; дни недели — круги 40 #F5F5F5 (16/500, были пилюли); ячейки — карточки #FDFDFD r4 с тенью, высота 120 (были gridline 66), зазор 4; номер дня 14/500 справа-сверху; «сегодня» — зелёная плашка 40×24 r4 с белым числом (был круг); события — пилюли #ECF9DE с рамкой #70B62B r4, текст 10/12, до 3 в ячейке; вне месяца — серые. Co-Authored-By: Claude Fable 5 --- .../feature/calendar/CalendarComponents.kt | 174 ++++++++++-------- 1 file changed, 96 insertions(+), 78 deletions(-) diff --git a/feature/calendar/src/main/java/ru/forbion/f7cloud/feature/calendar/CalendarComponents.kt b/feature/calendar/src/main/java/ru/forbion/f7cloud/feature/calendar/CalendarComponents.kt index 7ce1731..dc4a3c0 100644 --- a/feature/calendar/src/main/java/ru/forbion/f7cloud/feature/calendar/CalendarComponents.kt +++ b/feature/calendar/src/main/java/ru/forbion/f7cloud/feature/calendar/CalendarComponents.kt @@ -392,54 +392,58 @@ fun CalendarMonthGrid( ) { val days = CalendarRepository.monthGridDays(month) val today = LocalDate.now() + // Живая тема (_calendar-month-view-mobile.css): месяц — белая карточка r12 с рамкой, + // внутри дни недели — круги 40 (#F5F5F5, 16/500) и ячейки-карточки #FDFDFD r4 + // с тенью, зазор 4. Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(6.dp), + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)) + .background(Color.White) + .border(1.dp, F7Colors.Border, RoundedCornerShape(12.dp)) + .padding(12.dp), + verticalArrangement = Arrangement.spacedBy(4.dp), ) { - // Заголовок дней недели — серые пилюли (по макету «Календарь · Месяц») Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(4.dp), ) { weekDayLabels.forEach { label -> - Box( - modifier = Modifier - .weight(1f) - .clip(RoundedCornerShape(100.dp)) - .background(F7Colors.Grey2) - .padding(vertical = 6.dp), - contentAlignment = Alignment.Center, - ) { - Text( - text = label, - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.Medium, - color = F7Colors.TextSecondary, - ) + Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) { + Box( + modifier = Modifier + .size(40.dp) + .clip(CircleShape) + .background(F7Colors.Grey2), + contentAlignment = Alignment.Center, + ) { + Text( + text = label, + style = MaterialTheme.typography.bodyLarge, + fontWeight = FontWeight.Medium, + color = F7Colors.TextPrimary, + ) + } } } } - // Гридлайн-сетка без скруглений (по макету) - Column( - modifier = Modifier - .fillMaxWidth() - .border(0.5.dp, F7Colors.Grey3), - ) { - days.chunked(7).forEach { week -> - Row(modifier = Modifier.fillMaxWidth()) { - week.forEach { day -> - val inMonth = day.month == month.month - val dayEvents = eventsByDay[day].orEmpty() - CalendarDayCell( - day = day.dayOfMonth, - inMonth = inMonth, - isToday = day == today, - selected = day == selectedDay, - events = dayEvents, - onClick = { onSelectDay(day) }, - modifier = Modifier.weight(1f), - ) - } + days.chunked(7).forEach { week -> + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + week.forEach { day -> + val inMonth = day.month == month.month + val dayEvents = eventsByDay[day].orEmpty() + CalendarDayCell( + day = day.dayOfMonth, + inMonth = inMonth, + isToday = day == today, + selected = day == selectedDay, + events = dayEvents, + onClick = { onSelectDay(day) }, + modifier = Modifier.weight(1f), + ) } } } @@ -456,65 +460,79 @@ private fun CalendarDayCell( onClick: () -> Unit, modifier: Modifier = Modifier, ) { - val cellBg = when { - isToday -> F7Colors.Green10 - selected -> F7Colors.PrimaryLight - else -> F7Colors.Surface - } + // Живая тема: ячейка — карточка #FDFDFD r4 с тонкой тенью, высота 120, паддинг 4; + // номер дня 14/500 СПРАВА-сверху (чужой месяц — серый); «сегодня» — зелёная плашка + // 40×24 r4 с белым числом; выбранный день подсвечиваем #ECF9DE (наша адаптация тапа). Column( modifier = modifier - .heightIn(min = 66.dp) - .border(0.5.dp, F7Colors.Grey3) - .background(cellBg) + .height(120.dp) + .shadow( + elevation = 1.dp, + shape = RoundedCornerShape(4.dp), + spotColor = F7Colors.Border, + ) + .clip(RoundedCornerShape(4.dp)) + .background(if (selected) F7Colors.PrimaryLight else Color(0xFFFDFDFD)) .clickable(onClick = onClick) - .padding(horizontal = 4.dp, vertical = 4.dp), + .padding(4.dp), verticalArrangement = Arrangement.spacedBy(2.dp), ) { - // Номер дня сверху-слева; сегодня — в зелёном круге - Box( - modifier = Modifier - .size(22.dp) - .then(if (isToday) Modifier.clip(CircleShape).background(F7Colors.Primary) else Modifier), - contentAlignment = Alignment.Center, - ) { - Text( - text = day.toString(), - style = MaterialTheme.typography.bodySmall, - fontWeight = if (isToday) FontWeight.SemiBold else FontWeight.Normal, - color = when { - isToday -> F7Colors.TextOnPrimary - !inMonth -> F7Colors.TextMuted - else -> F7Colors.TextPrimary - }, - ) - } - if (inMonth) { - events.take(2).forEach { event -> - CalendarDayEventPill(event.summary.ifBlank { "Событие" }) - } - if (events.size > 2) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { + if (isToday) { + Box( + modifier = Modifier + .width(40.dp) + .height(24.dp) + .clip(RoundedCornerShape(4.dp)) + .background(F7Colors.Primary), + contentAlignment = Alignment.Center, + ) { + Text( + text = day.toString(), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + color = Color.White, + ) + } + } else { Text( - "+${events.size - 2}", - style = MaterialTheme.typography.labelSmall, - color = F7Colors.Primary, + text = day.toString(), + style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium, + color = if (inMonth) F7Colors.TextPrimary else F7Colors.TextSecondary, ) } } + events.take(3).forEach { event -> + CalendarDayEventPill(event.summary.ifBlank { "Событие" }, muted = !inMonth) + } + if (events.size > 3) { + Text( + "+${events.size - 3}", + style = MaterialTheme.typography.labelSmall, + color = F7Colors.Primary, + fontWeight = FontWeight.Medium, + ) + } } } @Composable -private fun CalendarDayEventPill(text: String) { +private fun CalendarDayEventPill(text: String, muted: Boolean = false) { + // Живая тема: пилюля события — фон #ECF9DE, рамка #70B62B, r4, текст 10/12; + // вне текущего месяца — серые с белым текстом. Text( text = text, modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(4.dp)) - .background(F7Colors.PrimaryLight) - .padding(horizontal = 4.dp, vertical = 1.dp), - style = MaterialTheme.typography.labelSmall, - color = F7Colors.PrimaryDark, + .background(if (muted) F7Colors.TextSecondary else F7Colors.PrimaryLight) + .border(1.dp, if (muted) F7Colors.TextSecondary else F7Colors.Primary, RoundedCornerShape(4.dp)) + .padding(horizontal = 4.dp, vertical = 2.dp), + fontSize = 10.sp, + lineHeight = 12.sp, + fontWeight = FontWeight.Medium, + color = if (muted) Color.White else F7Colors.TextPrimary, maxLines = 1, overflow = TextOverflow.Ellipsis, )