From d6e8981249ca49487f1dc65bd9491d1401d3478b Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Fri, 16 Oct 2026 13:25:20 +0200 Subject: [PATCH] Share the unnamed-calendar label, visibility switch and manager row --- .../calendula/ui/calendars/BackupScreen.kt | 3 +- .../calendula/ui/calendars/CalendarsScreen.kt | 85 +++++++++---------- .../calendula/ui/common/AccountGroups.kt | 2 +- .../ui/common/CalendarPickerGroups.kt | 2 +- .../calendula/ui/common/CalendarText.kt | 6 ++ .../ui/common/CalendarVisibilitySwitch.kt | 24 ++++++ .../calendula/ui/detail/EventDetailScreen.kt | 3 +- .../calendula/ui/edit/EventEditScreen.kt | 9 +- .../calendula/ui/filter/CalendarFilterList.kt | 5 +- .../ui/onboarding/HiddenCalendarsStep.kt | 26 ++---- .../ui/settings/EventFormSettings.kt | 3 +- .../ui/settings/NotificationSettings.kt | 5 +- 12 files changed, 93 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarVisibilitySwitch.kt diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/BackupScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/BackupScreen.kt index 02782798..d319ff0c 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/BackupScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/BackupScreen.kt @@ -53,6 +53,7 @@ import de.jeanlucmakiola.calendula.ui.common.CalendarColorChip import de.jeanlucmakiola.calendula.ui.common.CalendarFailure import de.jeanlucmakiola.calendula.ui.common.LeadingAvatar import de.jeanlucmakiola.calendula.ui.common.LocalManageCalendars +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.components.DialogAmountField import de.jeanlucmakiola.floret.components.DialogUnitDropdown @@ -317,7 +318,7 @@ private fun ExportCalendarPicker( calendars.forEachIndexed { index, calendar -> val isSelected = calendar.id in selected GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), summary = calendar.description, position = positionOf(index, calendars.size), leading = { CalendarColorChip(calendar.color) }, diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/CalendarsScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/CalendarsScreen.kt index e0702494..5be7aacf 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/CalendarsScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/calendars/CalendarsScreen.kt @@ -40,7 +40,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -73,6 +72,7 @@ import de.jeanlucmakiola.calendula.domain.stateLabels import de.jeanlucmakiola.calendula.data.calendar.CalendarColorPalette import de.jeanlucmakiola.calendula.ui.common.AccountKey import de.jeanlucmakiola.calendula.ui.common.CalendarColorChip +import de.jeanlucmakiola.calendula.ui.common.CalendarVisibilitySwitch import de.jeanlucmakiola.calendula.ui.common.accountGroupTitle import de.jeanlucmakiola.calendula.ui.common.groupByAccount import de.jeanlucmakiola.calendula.ui.common.LocalSoftenColors @@ -82,6 +82,7 @@ import de.jeanlucmakiola.calendula.ui.common.eventInk import de.jeanlucmakiola.calendula.ui.common.LeadingAvatar import de.jeanlucmakiola.calendula.ui.common.SourceLogo import de.jeanlucmakiola.calendula.ui.common.curatedSourcePackage +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.components.GroupedHint import de.jeanlucmakiola.floret.components.GroupedSectionHeader @@ -238,21 +239,10 @@ private fun CalendarsList( GroupedHint(stringResource(R.string.calendars_local_empty), style = MaterialTheme.typography.bodySmall) } else { local.forEachIndexed { index, calendar -> - val disabled = !calendar.isVisibleInSystem - GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, - summary = calendarRowSummary(calendar), - position = if (index == local.lastIndex) Position.Bottom else Position.Middle, - container = MaterialTheme.colorScheme.surfaceContainerHighest, - dimmed = disabled, - leading = { CalendarColorChip(calendar.color, dimIf(disabled)) }, - trailing = { - EnableSwitch( - calendarName = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, - enabled = !disabled, - onToggle = { enabled -> onSetVisible(calendar.id, enabled) }, - ) - }, + CalendarManagerRow( + calendar = calendar, + last = index == local.lastIndex, + onSetVisible = onSetVisible, onClick = { onEdit(calendar) }, ) } @@ -323,27 +313,10 @@ private fun CalendarsList( // bottom, dimmed and switchless. val ordered = cals.orderedForManager() ordered.forEachIndexed { index, calendar -> - val disabled = !calendar.isVisibleInSystem || calendar.isNotSynced - GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, - summary = calendarRowSummary(calendar), - position = if (index == ordered.lastIndex) Position.Bottom else Position.Middle, - container = MaterialTheme.colorScheme.surfaceContainerHighest, - dimmed = disabled, - leading = { CalendarColorChip(calendar.color, dimIf(disabled)) }, - trailing = if (calendar.hasVisibilitySwitch) { - { - EnableSwitch( - calendarName = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, - enabled = calendar.isVisibleInSystem, - onToggle = { enabled -> - onSetVisible(calendar.id, enabled) - }, - ) - } - } else { - null - }, + CalendarManagerRow( + calendar = calendar, + last = index == ordered.lastIndex, + onSetVisible = onSetVisible, ) } } @@ -682,17 +655,37 @@ private fun calendarRowSummary(calendar: CalendarSource): String? { * `Calendars.VISIBLE`. Unchecked drops the calendar out of every surface and * stops its reminders. Carries its own content description. */ +/** + * One calendar in a group: dimmed while switched off or not syncing, with the + * visibility switch only where it can change anything. + */ @Composable -private fun EnableSwitch( - calendarName: String, - enabled: Boolean, - onToggle: (Boolean) -> Unit, +private fun CalendarManagerRow( + calendar: CalendarSource, + last: Boolean, + onSetVisible: (Long, Boolean) -> Unit, + onClick: (() -> Unit)? = null, ) { - val label = stringResource(R.string.calendars_visibility_a11y, calendarName) - Switch( - checked = enabled, - onCheckedChange = onToggle, - modifier = Modifier.semantics { contentDescription = label }, + val disabled = !calendar.isVisibleInSystem || calendar.isNotSynced + GroupedRow( + title = calendar.displayName.orUnnamed(), + summary = calendarRowSummary(calendar), + position = if (last) Position.Bottom else Position.Middle, + container = MaterialTheme.colorScheme.surfaceContainerHighest, + dimmed = disabled, + leading = { CalendarColorChip(calendar.color, dimIf(disabled)) }, + trailing = if (calendar.hasVisibilitySwitch) { + { + CalendarVisibilitySwitch( + calendarName = calendar.displayName.orUnnamed(), + enabled = calendar.isVisibleInSystem, + onToggle = { enabled -> onSetVisible(calendar.id, enabled) }, + ) + } + } else { + null + }, + onClick = onClick, ) } diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/AccountGroups.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/AccountGroups.kt index 7ec3dfdc..c92c1ce3 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/AccountGroups.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/AccountGroups.kt @@ -57,7 +57,7 @@ fun List.groupByAccount(): List { */ @Composable fun accountGroupTitle(group: CalendarAccountGroup): String { - val label = group.label.ifBlank { stringResource(R.string.calendar_unnamed) } + val label = group.label.orUnnamed() return if (!group.ambiguous) { label } else { diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarPickerGroups.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarPickerGroups.kt index d9a6ce9f..af5c46df 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarPickerGroups.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarPickerGroups.kt @@ -114,7 +114,7 @@ private fun CalendarPickerGroup( ) calendars.forEachIndexed { index, calendar -> GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), position = if (index == calendars.lastIndex) Position.Bottom else Position.Middle, checked = calendar.id == selectedId, leading = { CalendarColorChip(calendar.color) }, diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarText.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarText.kt index cec15809..bbf01f26 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarText.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarText.kt @@ -3,10 +3,12 @@ package de.jeanlucmakiola.calendula.ui.common import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.unit.Dp +import de.jeanlucmakiola.calendula.R /** * The calendar surfaces' line-height treatment. Material wraps an 11sp glyph in @@ -55,3 +57,7 @@ fun rememberTrimmedLineHeight(style: TextStyle): Dp { with(density) { measurer.measure(LINE_SAMPLE, style.trimmedLines()).size.height.toDp() } } } + +/** A calendar or account name, or the "unnamed" label when it is blank. */ +@Composable +fun String.orUnnamed(): String = ifBlank { stringResource(R.string.calendar_unnamed) } diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarVisibilitySwitch.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarVisibilitySwitch.kt new file mode 100644 index 00000000..ca213600 --- /dev/null +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/CalendarVisibilitySwitch.kt @@ -0,0 +1,24 @@ +package de.jeanlucmakiola.calendula.ui.common + +import androidx.compose.material3.Switch +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import de.jeanlucmakiola.calendula.R + +/** The per-row switch writing the device's own `Calendars.VISIBLE`, as Settings does (#75). */ +@Composable +fun CalendarVisibilitySwitch( + calendarName: String, + enabled: Boolean, + onToggle: (Boolean) -> Unit, +) { + val label = stringResource(R.string.calendars_visibility_a11y, calendarName) + Switch( + checked = enabled, + onCheckedChange = onToggle, + modifier = Modifier.semantics { contentDescription = label }, + ) +} diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/detail/EventDetailScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/detail/EventDetailScreen.kt index a2029073..6b8ca58c 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/detail/EventDetailScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/detail/EventDetailScreen.kt @@ -90,6 +90,7 @@ import de.jeanlucmakiola.calendula.domain.TimeZoneOption import de.jeanlucmakiola.calendula.domain.timeZoneOptionOf import de.jeanlucmakiola.calendula.domain.zoneDescriptor import de.jeanlucmakiola.calendula.domain.zoneOrNull +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.IconInfoCard import de.jeanlucmakiola.floret.identity.LocalFloretDarkTheme import de.jeanlucmakiola.floret.identity.predictiveBack @@ -446,7 +447,7 @@ private fun EventDetailContent( iconContentDescription = stringResource(R.string.event_detail_calendar), ) { Text( - text = state.calendarName?.ifBlank { stringResource(R.string.calendar_unnamed) } + text = state.calendarName?.orUnnamed() ?: stringResource(R.string.event_detail_calendar_unknown), style = MaterialTheme.typography.titleMedium, ) diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/edit/EventEditScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/edit/EventEditScreen.kt index f1b7a1e0..356981fa 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/edit/EventEditScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/edit/EventEditScreen.kt @@ -33,6 +33,9 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Notes import androidx.compose.material.icons.filled.Add +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.IconInfoCard import de.jeanlucmakiola.floret.identity.LocalFloretDarkTheme import kotlinx.coroutines.launch @@ -85,11 +88,9 @@ import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester @@ -832,7 +833,7 @@ private fun EventEditContent( text = stringResource( R.string.event_edit_managed_hint, selectedCalendar?.displayName - ?.ifBlank { stringResource(R.string.calendar_unnamed) } + ?.orUnnamed() .orEmpty(), ), style = MaterialTheme.typography.bodySmall, @@ -939,7 +940,7 @@ private fun EventEditContent( ) { Text( text = selectedCalendar?.displayName - ?.ifBlank { stringResource(R.string.calendar_unnamed) } + ?.orUnnamed() ?: stringResource(R.string.event_edit_error_no_calendar), style = MaterialTheme.typography.titleMedium, color = if (selectedCalendar == null) { diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/filter/CalendarFilterList.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/filter/CalendarFilterList.kt index 9b37431a..7b292b9b 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/filter/CalendarFilterList.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/filter/CalendarFilterList.kt @@ -21,6 +21,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import de.jeanlucmakiola.calendula.R import de.jeanlucmakiola.calendula.domain.FailureReason import de.jeanlucmakiola.calendula.ui.common.CalendarColorChip +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.calendula.ui.common.sourceAppName import de.jeanlucmakiola.floret.components.GroupedListInset import de.jeanlucmakiola.floret.components.GroupedRow @@ -62,7 +63,7 @@ private fun FilterList( ) { Column(modifier = modifier.fillMaxWidth()) { groups.forEach { group -> - val account = group.account.ifBlank { stringResource(R.string.calendar_unnamed) } + val account = group.account.orUnnamed() Text( text = if (group.ambiguous) { stringResource( @@ -84,7 +85,7 @@ private fun FilterList( ) group.calendars.forEachIndexed { index, cal -> GroupedRow( - title = cal.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = cal.displayName.orUnnamed(), position = positionOf(index, group.calendars.size), minHeight = 56.dp, leading = { CalendarColorChip(cal.color) }, diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/onboarding/HiddenCalendarsStep.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/onboarding/HiddenCalendarsStep.kt index 86b57758..ea498de1 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/onboarding/HiddenCalendarsStep.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/onboarding/HiddenCalendarsStep.kt @@ -8,20 +8,19 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import de.jeanlucmakiola.calendula.R import de.jeanlucmakiola.calendula.domain.CalendarSource import de.jeanlucmakiola.calendula.domain.hasVisibilitySwitch import de.jeanlucmakiola.calendula.ui.common.CalendarColorChip +import de.jeanlucmakiola.calendula.ui.common.CalendarVisibilitySwitch +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.GroupedListInset import de.jeanlucmakiola.floret.components.GroupedRow import de.jeanlucmakiola.floret.components.OnboardingPrimaryButton @@ -122,7 +121,7 @@ internal fun HiddenCalendarsStep( calendars.forEachIndexed { index, calendar -> val off = !calendar.isVisibleInSystem GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), summary = calendar.accountName.takeIf { it.isNotBlank() }, position = when { calendars.size == 1 -> Position.Alone @@ -133,8 +132,8 @@ internal fun HiddenCalendarsStep( dimmed = off, trailing = if (calendar.hasVisibilitySwitch) { { - CalendarSwitch( - calendarName = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + CalendarVisibilitySwitch( + calendarName = calendar.displayName.orUnnamed(), enabled = !off, onToggle = { on -> onSetVisible(calendar.id, on) }, ) @@ -149,18 +148,3 @@ internal fun HiddenCalendarsStep( Spacer(Modifier.height(OnboardingSpace.md)) } } - -/** The per-row switch, writing the device's own `Calendars.VISIBLE` as Settings does. */ -@Composable -private fun CalendarSwitch( - calendarName: String, - enabled: Boolean, - onToggle: (Boolean) -> Unit, -) { - val label = stringResource(R.string.calendars_visibility_a11y, calendarName) - Switch( - checked = enabled, - onCheckedChange = onToggle, - modifier = Modifier.semantics { contentDescription = label }, - ) -} diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/EventFormSettings.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/EventFormSettings.kt index 4d44c310..590a0085 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/EventFormSettings.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/EventFormSettings.kt @@ -25,6 +25,7 @@ import de.jeanlucmakiola.calendula.ui.common.DurationPicker import de.jeanlucmakiola.calendula.ui.common.durationLabel import de.jeanlucmakiola.calendula.ui.common.eventFormFieldIcon import de.jeanlucmakiola.calendula.ui.common.eventFormFieldLabel +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.components.ExpandIcon import de.jeanlucmakiola.floret.components.GroupedHint @@ -129,7 +130,7 @@ internal fun EventFormScreen( durationCalendars.forEachIndexed { index, calendar -> val override = state.perCalendarEventDuration[calendar.id] GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), summary = override?.let { durationLabel(it) } ?: stringResource( R.string.settings_calendar_duration_inherits, diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/NotificationSettings.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/NotificationSettings.kt index bea57bad..b6fd7b28 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/NotificationSettings.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/settings/NotificationSettings.kt @@ -37,6 +37,7 @@ import de.jeanlucmakiola.calendula.ui.common.REMINDER_PRESETS import de.jeanlucmakiola.calendula.ui.common.ReminderDefaultPicker import de.jeanlucmakiola.calendula.ui.common.TimePickerAlert import de.jeanlucmakiola.calendula.ui.common.durationLabel +import de.jeanlucmakiola.calendula.ui.common.orUnnamed import de.jeanlucmakiola.floret.android.hasPermission import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.components.ExpandIcon @@ -172,7 +173,7 @@ internal fun NotificationsScreen( // own section — link there instead. if (calendar.id in state.managedCalendarIds) { GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), summary = stringResource(R.string.settings_calendar_reminders_managed_hint), position = Position.Alone, leading = { CalendarColorChip(calendar.color) }, @@ -189,7 +190,7 @@ internal fun NotificationsScreen( } val expanded = calendar.id in expandedCalendars GroupedRow( - title = calendar.displayName.ifBlank { stringResource(R.string.calendar_unnamed) }, + title = calendar.displayName.orUnnamed(), position = if (expanded) Position.Top else Position.Alone, leading = { CalendarColorChip(calendar.color) }, trailing = { ExpandIcon(expanded) },