Skip to content

Calendar

Calendar is a month grid that stays on the page. Click a day, or Tab into the grid and move with the arrow keys:

September 2026
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

No day chosen

CalendarDemo.tsx
import { Paragraph, View } from '@hozo/core'
import { Calendar } from '@hozo/ui'
import { useState } from 'react'
type Day = { year: number; month: number; day: number }
// Pinned so the page shows the same month whenever it is read.
const TODAY: Day = { year: 2026, month: 9, day: 24 }
const pad = (n: number) => String(n).padStart(2, '0')
export function CalendarDemo() {
const [day, setDay] = useState<Day | null>(null)
return (
<View className="items-start gap-3">
<Calendar
accessibilityLabel="Delivery day"
locale="en-US"
today={TODAY}
defaultMonth={{ year: 2026, month: 9 }}
min={TODAY}
value={day}
onChange={setDay}
/>
<Paragraph className="text-sm text-hozo-text-body">
{day ? `Delivery: ${day.year}-${pad(day.month)}-${pad(day.day)}` : 'No day chosen'}
</Paragraph>
</View>
)
}
  • Dates are plain records: { year, month, day }, with month from 1 to 12. There is no Date and no time zone, so the 24th stays the 24th wherever the page is read.
  • value and onChange hold the chosen day. With range, they hold { start, end } instead.
  • The keyboard:
    • the arrows move by a day or a week
    • Home and End go to the start and end of the week
    • Page Up and Page Down move by a month
    • Enter chooses the day
  • min and max disable the days outside them. That is why the days before the 24th cannot be chosen here.
  • locale names the month and the weekdays, and firstDayOfWeek overrides where the week starts.
  • today marks a day. It defaults to the device’s date, and the example pins it so the page reads the same on any day.