Skip to content

Commit ddc9acf

Browse files
committedMar 17, 2025·
feat(sanity): use time input in calendar (#8921)
1 parent 88dbdb0 commit ddc9acf

File tree

7 files changed

+33
-75
lines changed

7 files changed

+33
-75
lines changed
 

‎packages/sanity/src/core/components/inputs/DateInputs/calendar/Calendar.tsx

+26-59
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import {ChevronLeftIcon, ChevronRightIcon, EarthGlobeIcon} from '@sanity/icons'
22
import {Box, Flex, Grid, Select, Text} from '@sanity/ui'
3-
import {addDays, addMonths, setDate, setHours, setMinutes, setMonth, setYear} from 'date-fns'
4-
import {range} from 'lodash'
3+
import {
4+
addDays,
5+
addMonths,
6+
format,
7+
parse,
8+
setDate,
9+
setHours,
10+
setMinutes,
11+
setMonth,
12+
setYear,
13+
} from 'date-fns'
514
import {
615
type ComponentProps,
716
type FormEvent,
@@ -19,8 +28,9 @@ import {Button} from '../../../../../ui-components/button/Button'
1928
import {TooltipDelayGroupProvider} from '../../../../../ui-components/tooltipDelayGroupProvider/TooltipDelayGroupProvider'
2029
import useDialogTimeZone from '../../../../scheduledPublishing/hooks/useDialogTimeZone'
2130
import useTimeZone from '../../../../scheduledPublishing/hooks/useTimeZone'
31+
import {TimeInput} from '../TimeInput'
2232
import {CalendarMonth} from './CalendarMonth'
23-
import {ARROW_KEYS, DEFAULT_TIME_PRESETS, HOURS_24} from './constants'
33+
import {ARROW_KEYS, DEFAULT_TIME_PRESETS} from './constants'
2434
import {features} from './features'
2535
import {type CalendarLabels, type MonthNames} from './types'
2636
import {formatTime} from './utils'
@@ -119,29 +129,21 @@ export const Calendar = forwardRef(function Calendar(
119129
[onSelect, selectedDate],
120130
)
121131

122-
const handleMinutesChange = useCallback(
123-
(event: FormEvent<HTMLSelectElement>) => {
124-
const m = Number(event.currentTarget.value)
125-
onSelect(setMinutes(selectedDate, m))
126-
},
127-
[onSelect, selectedDate],
128-
)
129-
130-
const handleHoursChange = useCallback(
131-
(event: FormEvent<HTMLSelectElement>) => {
132-
const m = Number(event.currentTarget.value)
133-
onSelect(setHours(selectedDate, m))
134-
},
135-
[onSelect, selectedDate],
136-
)
137-
138132
const handleTimeChange = useCallback(
139133
(hours: number, mins: number) => {
140134
onSelect(setHours(setMinutes(selectedDate, mins), hours))
141135
},
142136
[onSelect, selectedDate],
143137
)
144138

139+
const handleTimeChangeInputChange = useCallback(
140+
(event: FormEvent<HTMLInputElement>) => {
141+
const date = parse(event.currentTarget.value, 'HH:mm', new Date())
142+
handleTimeChange(date.getHours(), date.getMinutes())
143+
},
144+
[handleTimeChange],
145+
)
146+
145147
const ref = useRef<HTMLDivElement | null>(null)
146148

147149
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
@@ -328,46 +330,11 @@ export const Calendar = forwardRef(function Calendar(
328330
{selectTime && (
329331
<>
330332
<Flex align="center">
331-
<Flex align="center" flex={1}>
332-
<Box>
333-
<Select
334-
aria-label={labels.selectHour}
335-
fontSize={1}
336-
padding={2}
337-
radius={2}
338-
value={selectedDate?.getHours()}
339-
onChange={handleHoursChange}
340-
>
341-
{HOURS_24.map((h) => (
342-
<option key={h} value={h}>
343-
{`${h}`.padStart(2, '0')}
344-
</option>
345-
))}
346-
</Select>
347-
</Box>
348-
349-
<Box paddingX={1}>
350-
<Text size={1}>:</Text>
351-
</Box>
352-
353-
<Box>
354-
<Select
355-
aria-label={labels.selectMinute}
356-
fontSize={1}
357-
padding={2}
358-
radius={2}
359-
value={selectedDate?.getMinutes()}
360-
onChange={handleMinutesChange}
361-
>
362-
{range(0, 60, timeStep).map((m) => (
363-
<option key={m} value={m}>
364-
{`${m}`.padStart(2, '0')}
365-
</option>
366-
))}
367-
</Select>
368-
</Box>
369-
</Flex>
370-
333+
<TimeInput
334+
aria-label={labels.selectTime}
335+
value={format(selectedDate, 'HH:mm')}
336+
onChange={handleTimeChangeInputChange}
337+
/>
371338
<Box marginLeft={2}>
372339
<Button text={labels.setToCurrentTime} mode="bleed" onClick={handleNowClick} />
373340
</Box>

‎packages/sanity/src/core/components/inputs/DateInputs/calendar/constants.ts

-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import {range} from 'lodash'
2-
31
export const DEFAULT_MONTH_NAMES = [
42
'January',
53
'February',
@@ -17,8 +15,6 @@ export const DEFAULT_MONTH_NAMES = [
1715

1816
export const DEFAULT_WEEK_DAY_NAMES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
1917

20-
export const HOURS_24 = range(0, 24)
21-
2218
export const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']
2319

2420
export const DEFAULT_TIME_PRESETS = [

‎packages/sanity/src/core/components/inputs/DateInputs/calendar/types.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ export interface CalendarLabels {
77
goToNextYear: string
88
goToPreviousMonth: string
99
goToNextMonth: string
10-
selectHour: string
11-
selectMinute: string
10+
selectTime: string
1211
setToCurrentTime: string
1312
tooltipText: string
1413
monthNames: MonthNames

‎packages/sanity/src/core/form/inputs/DateInputs/__tests__/CommonDateTimeInput.test.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ const CALENDAR_LABELS: CalendarLabels = {
4242
goToNextYear: 'Next year',
4343
goToNextMonth: 'Go to next month',
4444
goToPreviousMonth: 'Go to previous month',
45-
selectHour: 'Select hour',
46-
selectMinute: 'Select minute',
45+
selectTime: 'Select time',
4746
setToCurrentTime: 'Set to current time',
4847
monthNames: [
4948
'January',

‎packages/sanity/src/core/form/inputs/DateInputs/utils.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ export function getCalendarLabels(
2020
goToNextYear: t('calendar.action.go-to-next-year'),
2121
goToPreviousYear: t('calendar.action.go-to-previous-year'),
2222
setToCurrentTime: t('calendar.action.set-to-current-time'),
23-
selectHour: t('calendar.action.select-hour'),
24-
selectMinute: t('calendar.action.select-minute'),
23+
selectTime: t('calendar.action.select-time'),
2524
tooltipText: t('calendar.button.tooltip-text'),
2625
monthNames: [
2726
t('calendar.month-names.january'),

‎packages/sanity/src/core/i18n/bundles/studio.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,8 @@ export const studioLocaleStrings = defineLocalesResources('studio', {
147147
'calendar.action.go-to-yesterday': 'Yesterday',
148148
/** Label for switch that controls whether or not to include time in given timestamp */
149149
'calendar.action.include-time-label': 'Include time',
150-
/** Action message for selecting the hour */
151-
'calendar.action.select-hour': 'Select hour',
152-
/** Action message for selecting the minute */
153-
'calendar.action.select-minute': 'Select minute',
150+
/** Action message for selecting the time */
151+
'calendar.action.select-time': 'Select time',
154152
/** Action message for setting to the current time */
155153
'calendar.action.set-to-current-time': 'Set to current time',
156154
/** Label for selecting an hour preset. Receives a `time` param as a string on hh:mm format and a `date` param as a Date instance denoting the preset date */

‎packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseTypePicker.test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ describe('ReleaseTypePicker', () => {
152152
// Select the 10th day in the calendar month
153153
fireEvent.click(within(Calendar).getByTestId('calendar-next-month'))
154154
fireEvent.click(within(CalendarMonth).getByText('10'))
155-
fireEvent.change(screen.getByLabelText('Select hour'), {target: {value: 10}})
156-
fireEvent.change(screen.getByLabelText('Select minute'), {target: {value: 55}})
155+
fireEvent.change(screen.getByLabelText('Select time'), {target: {value: '10:55'}})
156+
fireEvent.blur(screen.getByLabelText('Select time'))
157157
expect(mockUpdateRelease).not.toHaveBeenCalled()
158158

159159
// Close the popup and check if the release is updated

0 commit comments

Comments
 (0)
Please sign in to comment.