Show today's date in the toolbar today button (#282)
The jump-to-today action in the app bar drew `Icons.Default.Today`, a generic calendar glyph. It now draws the current day number inside an outlined rounded box, so the bar tells you what day it is as well as taking you there. Shared by all four calendar views, so it changes everywhere at once. - The box fills the same 24dp icon slot `AppBarSpacing` measures its trailing insets from (`IconSize` went from private to internal so the glyph and the spacing math cannot drift apart). No spacing value changed. - Outlined rather than the month grid's filled circle: that circle means "this cell is today", and a filled accent here would sit heavier than the stroke icons beside it. - The day comes from `rememberCurrentMinute()` through a `derivedStateOf`, so the button rolls over at midnight — and across a timezone change — while recomposing only when the number actually changes, not on every minute tick. - The content description is unchanged, still the sentence "Go to today". ### Also here A review of the branch turned up a loose end in #113, which this branch is merged on top of: the day and week **loading skeletons** still painted one solid `surfaceContainer` column. With the hour grid on that is no longer what a loaded column looks like — the column recedes to `surface` and the container colour moves onto the cells — so the skeleton flashed a solid block into a gapped grid on arrival, the exact resize its own comment promises not to do. Both skeletons now read `LocalShowHourGrid` and draw the same cells. ### Deviation from the issue The issue asked to watch the width at large font scales. Rather than measuring and adapting, the number is held at a fixed size — `12.dp` converted to sp at draw time, so it ignores the font scale. It is an icon glyph sharing a bar with stroke icons, a growing two-digit day is exactly the width pressure #165 measured, and screen readers get the meaning from the content description either way. A small number is also strictly more than the old icon said, never less. Closes #220 Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/282
This commit is contained in:
@@ -32,6 +32,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
three-letter form and the day view drops the weekday, rather than trailing off
|
||||
mid-word at large font sizes. The view switcher, the title and the agenda's
|
||||
range bar also line up with the grid underneath them ([#165]).
|
||||
- The jump-to-today button in the toolbar now shows today's date. It drew a
|
||||
generic calendar icon, which told you nothing you didn't already know from
|
||||
tapping it; it now carries the current day number in an outlined box, so the
|
||||
bar says what day it is as well as taking you there. It rolls over at midnight
|
||||
on its own ([#220]).
|
||||
|
||||
### Fixed
|
||||
- **A long location no longer runs off the edge of its field.** The location on
|
||||
@@ -1611,3 +1616,4 @@ automatically, with zero telemetry and no internet permission.
|
||||
[#253]: https://codeberg.org/jlmakiola/calendula/issues/253
|
||||
[#273]: https://codeberg.org/jlmakiola/calendula/issues/273
|
||||
[#113]: https://codeberg.org/jlmakiola/calendula/issues/113
|
||||
[#220]: https://codeberg.org/jlmakiola/calendula/issues/220
|
||||
|
||||
@@ -26,7 +26,8 @@ object AppBarSpacing {
|
||||
|
||||
private val IconButtonSize = 48.dp
|
||||
|
||||
private val IconSize = 24.dp
|
||||
/** M3's icon slot inside an icon button; the today glyph fills the same box. */
|
||||
internal val IconSize = 24.dp
|
||||
|
||||
/**
|
||||
* End padding for a container-backed control that ends the bar, measured to
|
||||
|
||||
@@ -1,26 +1,81 @@
|
||||
package de.jeanlucmakiola.calendula.ui.common
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Today
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.jeanlucmakiola.calendula.R
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
|
||||
private val GlyphShape = RoundedCornerShape(7.dp)
|
||||
private val GlyphBorder = 1.5.dp
|
||||
|
||||
/**
|
||||
* Height of the day number. Expressed in dp and converted to sp at draw time so
|
||||
* it does not follow the font scale: this is an icon glyph sharing the bar with
|
||||
* stroke icons, and a two-digit day that grew with the text would push the bar
|
||||
* past the width #165 measured it to. The button's content description carries
|
||||
* the meaning for screen readers, so nothing is lost by holding it still.
|
||||
*/
|
||||
private val GlyphTextHeight = 12.dp
|
||||
|
||||
/**
|
||||
* The top-bar "jump to today" icon button, shared by every calendar view's app
|
||||
* bar (#60). Shown in place of the fade-in FAB pill when the user moves the
|
||||
* today control into the toolbar; renders nothing when [show] is false, so it
|
||||
* drops straight into an app bar's `actions` slot without a wrapping condition.
|
||||
*
|
||||
* The glyph is the current day number in an outlined box rather than a generic
|
||||
* calendar icon (#220), so the bar also says what day it is. Outlined rather
|
||||
* than the month grid's filled circle, which reads as "this cell is today" and
|
||||
* would sit heavier here than the stroke icons beside it.
|
||||
*/
|
||||
@Composable
|
||||
fun TodayAction(show: Boolean, onToday: () -> Unit) {
|
||||
if (!show) return
|
||||
IconButton(onClick = onToday) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Today,
|
||||
contentDescription = stringResource(R.string.today_jump_action),
|
||||
)
|
||||
val now = rememberCurrentMinute()
|
||||
// Only the day number is read, so the bar recomposes at midnight rather
|
||||
// than on every minute tick.
|
||||
val day by remember {
|
||||
derivedStateOf { now.value.toLocalDateTime(TimeZone.currentSystemDefault()).date.day }
|
||||
}
|
||||
val description = stringResource(R.string.today_jump_action)
|
||||
IconButton(
|
||||
onClick = onToday,
|
||||
modifier = Modifier.semantics { contentDescription = description },
|
||||
) {
|
||||
val textSize = with(LocalDensity.current) { GlyphTextHeight.toSp() }
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(AppBarSpacing.IconSize)
|
||||
.border(GlyphBorder, LocalContentColor.current, GlyphShape),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
text = day.toString(),
|
||||
fontSize = textSize,
|
||||
lineHeight = textSize,
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = TextAlign.Center,
|
||||
color = LocalContentColor.current,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,7 +861,12 @@ private fun DayLoading() {
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
|
||||
// Same scale resolution as the loaded timeline, so the skeleton's column
|
||||
// doesn't resize the moment the real day arrives.
|
||||
val totalHeight = scale.hourHeight(maxHeight) * 24
|
||||
val hourHeight = scale.hourHeight(maxHeight)
|
||||
val totalHeight = hourHeight * 24
|
||||
// The skeleton wears the loaded column's own ground, so the arrival of
|
||||
// the real day doesn't flash a solid block into a gapped grid.
|
||||
val showHourGrid = LocalShowHourGrid.current
|
||||
val hourPx = with(LocalDensity.current) { hourHeight.toPx() }
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@@ -874,7 +879,11 @@ private fun DayLoading() {
|
||||
.weight(1f)
|
||||
.height(totalHeight)
|
||||
.padding(horizontal = 2.dp)
|
||||
.background(MaterialTheme.colorScheme.surfaceContainer),
|
||||
.background(
|
||||
if (showHourGrid) MaterialTheme.colorScheme.surface
|
||||
else MaterialTheme.colorScheme.surfaceContainer,
|
||||
)
|
||||
.hourGridCells(showHourGrid, hourPx, MaterialTheme.colorScheme.surfaceContainer),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,7 +1042,14 @@ private fun WeekLoading() {
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
|
||||
// Same scale resolution as the loaded timeline, so the skeleton's
|
||||
// columns don't resize the moment the real week arrives.
|
||||
val totalHeight = scale.hourHeight(maxHeight) * 24
|
||||
val hourHeight = scale.hourHeight(maxHeight)
|
||||
val totalHeight = hourHeight * 24
|
||||
// The skeleton wears the loaded columns' own ground, so the arrival
|
||||
// of the real week doesn't flash solid blocks into a gapped grid.
|
||||
val showHourGrid = LocalShowHourGrid.current
|
||||
val hourPx = with(LocalDensity.current) { hourHeight.toPx() }
|
||||
val columnGround = if (showHourGrid) MaterialTheme.colorScheme.surface
|
||||
else MaterialTheme.colorScheme.surfaceContainer
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@@ -1056,7 +1063,12 @@ private fun WeekLoading() {
|
||||
.weight(1f)
|
||||
.height(totalHeight)
|
||||
.padding(horizontal = 2.dp)
|
||||
.background(MaterialTheme.colorScheme.surfaceContainer),
|
||||
.background(columnGround)
|
||||
.hourGridCells(
|
||||
showHourGrid,
|
||||
hourPx,
|
||||
MaterialTheme.colorScheme.surfaceContainer,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user