Components
HeroUI v3 Calendar — date calendar with year picker, controlled state, week/day views, min/max, unavailable dates, multiple selection, read-only, focused value, cell indicators, multiple months, booking example and custom styles.
npx @21st-dev/cli@beta add hero_ui/heroui-calendarLoading preview...
"use client"
import type { CalendarDate, DateValue } from "@internationalized/date"
import { Button } from "@heroui/react"
import { getLocalTimeZone, isWeekend, today } from "@internationalized/date"
import { useState } from "react"
import { I18nProvider, useLocale } from "react-aria-components"
import Calendar from "@/components/ui/heroui-calendar"
function BookingCalendarInner() {
const [selectedDate, setSelectedDate] = useState<CalendarDate | null>(null)
const { locale } = useLocale()
const bookedDates = [5, 6, 12, 13, 14, 20]
const isDateUnavailable = (date: DateValue) => {
return isWeekend(date, locale) || bookedDates.includes(date.day)
}
return (
<div className="flex flex-col items-center gap-4">
<Calendar
aria-label="Booking date"
isDateUnavailable={isDateUnavailable}
minValue={today(getLocalTimeZone())}
value={selectedDate}
onChange={setSelectedDate}
>
<Calendar.Header>
<Calendar.Heading />
<Calendar.NavButton slot="previous" />
<Calendar.NavButton slot="next" />
</Calendar.Header>
<Calendar.Grid>
<Calendar.GridHeader>
{(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>}
</Calendar.GridHeader>
<Calendar.GridBody>
{(date) => (
<Calendar.Cell date={date}>
{({ formattedDate, isUnavailable }) => (
<>
{formattedDate}
{!isUnavailable &&
!isWeekend(date, locale) &&
bookedDates.includes(date.day) && <Calendar.CellIndicator />}
</>
)}
</Calendar.Cell>
)}
</Calendar.GridBody>
</Calendar.Grid>
</Calendar>
<div className="flex flex-col gap-2 text-center">
<div className="flex items-center justify-center gap-4 text-xs text-muted">
<span className="flex items-center gap-1">
<span className="size-2 rounded-full bg-muted" /> Has bookings
</span>
<span className="flex items-center gap-1">
<span className="size-2 rounded-full bg-default" /> Weekend/Unavailable
</span>
</div>
{selectedDate ? (
<Button size="sm" variant="primary">
Book {selectedDate.toString()}
</Button>
) : null}
</div>
</div>
)
}
export default function RealWorldExample() {
return (
<I18nProvider locale="en-US">
<BookingCalendarInner />
</I18nProvider>
)
}
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...