Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b8da92157 |
@@ -123,7 +123,6 @@ 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.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@@ -745,7 +744,7 @@ internal fun WeekdayHeader(weekStart: DayOfWeek, showWeekNumbers: Boolean) {
|
||||
.padding(horizontal = AppBarSpacing.Inset, vertical = 4.dp),
|
||||
) {
|
||||
// Reserve the gutter so the weekday labels stay over their day columns.
|
||||
if (showWeekNumbers) Spacer(Modifier.width(rememberWeekNumberGutter()))
|
||||
if (showWeekNumbers) Spacer(Modifier.width(WEEK_NUMBER_GUTTER))
|
||||
days.forEach { dow ->
|
||||
val isWeekend = dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY
|
||||
val javaDow = java.time.DayOfWeek.of(dow.ordinal + 1)
|
||||
@@ -763,34 +762,9 @@ internal fun WeekdayHeader(weekStart: DayOfWeek, showWeekNumbers: Boolean) {
|
||||
|
||||
private val EVENT_ROW_HEIGHT = 20.dp
|
||||
private val DAY_NUMBER_HEIGHT = 22.dp
|
||||
/** Padding between the week-number pill's edge and the number inside it. */
|
||||
private val WEEK_NUMBER_PADDING = 6.dp
|
||||
|
||||
/** The widest week number an ISO year reaches; digits are tabular, so one
|
||||
* measurement of it prices every week in the grid. */
|
||||
private const val WEEK_NUMBER_SAMPLE = "53"
|
||||
|
||||
/**
|
||||
* Width of the optional left calendar-week gutter (#25), measured rather than
|
||||
* fixed: it is sized to the number it seats at the style the pill draws it in,
|
||||
* so it follows the font scale instead of reserving slack for it, and spends
|
||||
* nothing more on a column the grid would rather hand to the seven days (#213).
|
||||
*/
|
||||
@Composable
|
||||
private fun rememberWeekNumberGutter(): Dp {
|
||||
val measurer = rememberTextMeasurer()
|
||||
val density = LocalDensity.current
|
||||
val style = weekNumberStyle()
|
||||
return remember(style, density, measurer) {
|
||||
val text = with(density) { measurer.measure(WEEK_NUMBER_SAMPLE, style).size.width.toDp() }
|
||||
text + (WEEK_NUMBER_PADDING + CELL_GAP) * 2
|
||||
}
|
||||
}
|
||||
|
||||
/** The week number's own style — a step down from the day numbers beside it. */
|
||||
@Composable
|
||||
private fun weekNumberStyle() =
|
||||
MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.Bold)
|
||||
/** Width of the optional left calendar-week gutter (#25); narrow, since it only
|
||||
* seats a one- or two-digit week number in a full-height tonal pill. */
|
||||
private val WEEK_NUMBER_GUTTER = 40.dp
|
||||
private val DAY_NUMBER_GAP = 4.dp
|
||||
private val CELL_TOP_PADDING = 6.dp
|
||||
/** Named separately because the split style's selection outline draws its own
|
||||
@@ -1512,7 +1486,7 @@ internal fun SplitMonthGrid(
|
||||
WeekNumberGutter(
|
||||
weekStart = week.days.first(),
|
||||
modifier = Modifier
|
||||
.width(rememberWeekNumberGutter())
|
||||
.width(WEEK_NUMBER_GUTTER)
|
||||
.fillMaxHeight(),
|
||||
)
|
||||
}
|
||||
@@ -2033,7 +2007,7 @@ private fun MonthWeekRow(
|
||||
WeekNumberGutter(
|
||||
weekStart = week.days.first(),
|
||||
modifier = Modifier
|
||||
.width(rememberWeekNumberGutter())
|
||||
.width(WEEK_NUMBER_GUTTER)
|
||||
.fillMaxHeight(),
|
||||
)
|
||||
}
|
||||
@@ -2448,7 +2422,8 @@ private fun WeekNumberGutter(weekStart: LocalDate, modifier: Modifier = Modifier
|
||||
) {
|
||||
Text(
|
||||
text = weekNumber.toString(),
|
||||
style = weekNumberStyle(),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
package de.jeanlucmakiola.calendula.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
/**
|
||||
* Default Material 3 Expressive typography. Custom font + tuned scale will
|
||||
* land in a later UI-design iteration; the defaults are intentional for V1
|
||||
* scaffolding to keep the foundation lean.
|
||||
* Tracking the two label roles the calendar grids are set in. Material gives
|
||||
* both 0.5sp, tuned for isolated UI labels with room around them; a month chip
|
||||
* is a text box some 37dp wide, where 0.5sp on an 11sp glyph spends most of a
|
||||
* character on spacing alone. 0.1sp is what Material itself sets labelLarge to,
|
||||
* so the label family stays coherent (#190).
|
||||
*/
|
||||
val CalendulaTypography = Typography()
|
||||
private val LabelTracking = 0.1.sp
|
||||
|
||||
/**
|
||||
* Material 3 Expressive typography with the label roles' tracking tightened.
|
||||
* Everything else is the default scale.
|
||||
*/
|
||||
val CalendulaTypography: Typography = Typography().let { base ->
|
||||
base.copy(
|
||||
labelMedium = base.labelMedium.copy(letterSpacing = LabelTracking),
|
||||
labelSmall = base.labelSmall.copy(letterSpacing = LabelTracking),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ private fun WeekDayHeader(
|
||||
}
|
||||
|
||||
/** Calendar-week badge shown in the header gutter, deliberately set apart with a
|
||||
* filled box and bold number — at the month grid's size, so the two agree (#213). */
|
||||
* filled box and bold number. */
|
||||
@Composable
|
||||
private fun WeekNumberBadge(weekNumber: Int, modifier: Modifier = Modifier) {
|
||||
val label = stringResource(R.string.week_number_label)
|
||||
@@ -583,9 +583,9 @@ private fun WeekNumberBadge(weekNumber: Int, modifier: Modifier = Modifier) {
|
||||
) {
|
||||
Text(
|
||||
text = weekNumber.toString(),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp),
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.jeanlucmakiola.calendula.ui.theme
|
||||
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@@ -48,6 +49,19 @@ class FontsTest {
|
||||
assertThat(typography.labelSmall.fontFamily).isEqualTo(plain)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `picking a font keeps the tightened label tracking`() {
|
||||
// The font picker only swaps the family; the tracking the grids are laid
|
||||
// out against has to survive it (#190).
|
||||
val typography = calendulaTypography(
|
||||
brand = BundledFont.Lora.family,
|
||||
plain = BundledFont.AtkinsonHyperlegible.family,
|
||||
)
|
||||
|
||||
assertThat(typography.labelSmall.letterSpacing).isEqualTo(0.1.sp)
|
||||
assertThat(typography.labelMedium.letterSpacing).isEqualTo(0.1.sp)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a null role keeps that role's default family while the other is applied`() {
|
||||
val plain = BundledFont.Lora.family
|
||||
|
||||
Reference in New Issue
Block a user