From 95c31631fb1677f8457b4a73f25d16e737633fb5 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Thu, 15 Oct 2026 04:05:55 +0200 Subject: [PATCH] fix: show event titles instead of bare start times in a narrow month view --- src/components/calendar/MonthView.tsx | 12 ++++++++---- src/lib/__tests__/month-chip-time.test.ts | 16 ++++++++++++++++ src/lib/calendar-month-scroll.ts | 9 +++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/lib/__tests__/month-chip-time.test.ts diff --git a/src/components/calendar/MonthView.tsx b/src/components/calendar/MonthView.tsx index 3d37e6ec..9b3c1970 100644 --- a/src/components/calendar/MonthView.tsx +++ b/src/components/calendar/MonthView.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { View, Text, StyleSheet, Pressable } from 'react-native'; +import { View, Text, StyleSheet, Pressable, useWindowDimensions } from 'react-native'; import { addDays, endOfMonth, @@ -24,7 +24,7 @@ import { type EventDayIndex, type TimeFormat, } from '../../lib/calendar-utils'; -import { dayIndexIn, monthKeyOf, monthMask } from '../../lib/calendar-month-scroll'; +import { dayIndexIn, monthChipShowsTime, monthKeyOf, monthMask } from '../../lib/calendar-month-scroll'; import { isInactiveEvent } from '../../lib/calendar-participants'; import { eventBlockColors } from '../../lib/event-colors'; import { useCalendarLocale } from '../../lib/calendar-locale'; @@ -153,6 +153,8 @@ function MonthWeekRowInner({ onLongPressDate, }: MonthWeekRowProps) { const c = useColors(); + const { width } = useWindowDimensions(); + const chipTime = monthChipShowsTime(true, width / 7); if (variant === 'full') { return ( - {event.showWithoutTime + {event.showWithoutTime || !chipTime ? null : `${format(getEventStartDate(event), timePattern(timeFormat), { locale })} `} {event.title || ''} @@ -318,6 +320,8 @@ function FullWeekRow({ height: number; colors: ThemePalette; }) { + const { width } = useWindowDimensions(); + const showTime = monthChipShowsTime(showTimeInMonthView, width / 7); return ( {showWeekNumbers && ( @@ -357,7 +361,7 @@ function FullWeekRow({ const inactive = isInactiveEvent(event, currentUserEmails); const colors = eventBlockColors(getEventColor(event, calendars), inactive, c); // No time on events that fill the whole day. - const time = showTimeInMonthView && !event.showWithoutTime && !isTimedEventFullDayOnDate(event, d) + const time = showTime && !event.showWithoutTime && !isTimedEventFullDayOnDate(event, d) ? `${format(getEventStartDate(event), timePattern(timeFormat), { locale })} ` : ''; return ( diff --git a/src/lib/__tests__/month-chip-time.test.ts b/src/lib/__tests__/month-chip-time.test.ts new file mode 100644 index 00000000..ee4a66ea --- /dev/null +++ b/src/lib/__tests__/month-chip-time.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest'; +import { monthChipShowsTime } from '../calendar-month-scroll'; + +describe('monthChipShowsTime', () => { + it('drops the time in a phone-portrait cell so the title shows', () => { + expect(monthChipShowsTime(true, 412 / 7)).toBe(false); + }); + + it('keeps the time where the cell has room', () => { + expect(monthChipShowsTime(true, 915 / 7)).toBe(true); + }); + + it('never shows the time when the setting is off', () => { + expect(monthChipShowsTime(false, 200)).toBe(false); + }); +}); diff --git a/src/lib/calendar-month-scroll.ts b/src/lib/calendar-month-scroll.ts index 6f536490..763c4d17 100644 --- a/src/lib/calendar-month-scroll.ts +++ b/src/lib/calendar-month-scroll.ts @@ -87,3 +87,12 @@ export function dayIndexIn(days: Date[], date: Date): number { const diff = differenceInCalendarDays(date, days[0]); return diff >= 0 && diff < days.length ? diff : -1; } + +// Below this cell width a start time fills the whole chip and the title never +// shows, as on a phone in portrait (about 58 dp, less at a larger font). +const MIN_CELL_WIDTH_FOR_TIME = 80; + +/** Whether a full month cell of about `cellWidth` dp puts the start time before the title. */ +export function monthChipShowsTime(showTimeSetting: boolean, cellWidth: number): boolean { + return showTimeSetting && cellWidth >= MIN_CELL_WIDTH_FOR_TIME; +}