Calendar
Choose a date or range in context.
Examples
"use client";
import { useState } from "react";
import { Calendar } from "@g4rcez/components";
import { startOfDay } from "date-fns";
function BasicCalendar() {
const [date, setDate] = useState<Date | undefined>(startOfDay(new Date()));
return (
<Calendar date={date} changeOnlyOnClick onChange={setDate} />
);
}- Study Typescript
- Start to learn Elixir
- CSS new features
"use client";
import { useState } from "react";
import { Calendar } from "@g4rcez/components";
import { add, endOfMonth, startOfDay, startOfMonth } from "date-fns";
import { AnimatePresence, motion } from "motion/react";
const d = startOfDay(new Date()); // Today
const todayISO = d.toISOString();
const futureDateISO = add(d, { days: 5 }).toISOString();
const eventDates = {
[todayISO]: ["Study Typescript", "Start to learn Elixir"],
[futureDateISO]: ["Go to the gym", "Learn about UX/UI"],
};
const options: Intl.DateTimeFormatOptions = {
day: "numeric",
weekday: "short",
month: "short",
year: "numeric",
};
function CalendarWithBookmark() {
const [date, setDate] = useState<Date | undefined>(d);
return (
<Card
title="Calendar + Bookmark"
className="grid grid-cols-1 lg:grid-cols-2 gap-6"
>
<Calendar
date={date}
changeOnlyOnClick
onChange={setDate}
onChangeYear={(d) => console.log("Year changed:", d.getFullYear())}
onChangeMonth={(d) => {
console.log("Month changed:", d.getMonth() + 1);
}}
styles={{
week: "border-b border-card-border",
weekDay:
"h-16 border-b border-l first:border-l-transparent border-t border-card-border",
dayFrame:
"h-16 border-card-border border-l border-r first:border-l-transparent last:border-r-transparent",
}}
RenderOnDay={({ date }) =>
date.toISOString() in eventDates ? (
<div className="absolute right-0 top-0 aspect-square size-5 text-sm rounded-full bg-warn text-warn-foreground items-center justify-center flex">
{eventDates[date.toISOString()].length}
</div>
) : null
}
/>
<AnimatePresence>
{date !== undefined && date.toISOString() in eventDates ? (
<motion.div
key={date.toISOString()}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
className="w-full h-full"
>
<header className="text-center pb-4 font-medium text-2xl">
{date.toLocaleDateString(undefined, options)}
</header>
<ul className="list-disc list-inside">
{eventDates[date.toISOString()].map((x) => (
<li key={x}>{x}</li>
))}
</ul>
</motion.div>
) : date !== undefined ? (
<motion.div
key={date.toISOString()}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
className="w-full h-full"
>
<header className="text-center pb-4 font-medium text-2xl">
{date.toLocaleDateString(undefined, options)}
</header>
<p>No events for this day.</p>
</motion.div>
) : null}
</AnimatePresence>
</Card>
);
}Selected From: 1/1/1970
Selected To: 1/6/1970
"use client";
import { useState } from "react";
import { Calendar } from "@g4rcez/components";
import { add, startOfDay } from "date-fns";
function RangeCalendar() {
const d = startOfDay(new Date());
const to = add(d, { days: 5 });
const [range, setRange] = useState({
from: d as Date | undefined,
to: to as Date | undefined,
});
return (
<Card title="Range calendar" className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<Calendar
markRange={true} // Mark range is usually true for range calendars
rangeMode
range={range}
changeOnlyOnClick
onChange={setRange as any}
labelRange={{ from: "Start", to: "End" }}
styles={{
week: "border-b border-card-border",
weekDay: "h-16 border-b border-card-border",
dayFrame:
"h-16 border-card-border border-l border-r first:border-l-transparent last:border-r-transparent",
}}
RenderOnDay={({ date }) =>
date.toISOString() in eventDates ? ( // Assuming eventDates is available
<div className="absolute right-1 bottom-1 aspect-square size-5 text-sm rounded-full bg-warn text-warn-foreground items-center justify-center flex">
{eventDates[date.toISOString()].length}
</div>
) : null
}
/>
<div className="flex flex-col gap-2">
<p>Selected From: {range.from?.toLocaleDateString()}</p>
<p>Selected To: {range.to?.toLocaleDateString()}</p>
</div>
</Card>
);
}When to use Calendar
Use when
Use Calendar when users need to inspect dates or choose a date or range in context.
Avoid when
Avoid Calendar for a single known date or when a compact input is enough.
Accessibility
Keep the calendar labeled, expose the selected date, and support previous/next month and date selection from the keyboard.
- Keep keyboard focus visible and follow the documented key commands.
- Provide an accessible name and connect descriptions or errors to the control.