kanpeki
uicalendarsource: ok · hit
Calendar
npx shadcn add "https://kanpeki.vercel.app/r/calendar.json"free
Where it goes
calendar
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightreact-aria-components@internationalized/date
Registry dependencies
@kanpeki/cva@kanpeki/custom-plugin
Files4 · source cached 10/14/2026, 3:39:12 PM
src/registry/ui/calendar/index.ts
export * from "./calendar";
export * as Calendar from "./namespace";
export * from "./styles";
src/registry/ui/calendar/calendar.tsx
"use client";
import { getLocalTimeZone, isToday } from "@internationalized/date";
import type { VariantProps } from "cva";
import {
Calendar,
composeRenderProps,
type DateValue,
Heading,
CalendarCell as RACCalendarCell,
CalendarGrid as RACCalendarGrid,
CalendarGridBody as RACCalendarGridBody,
CalendarGridHeader as RACCalendarGridHeader,
CalendarHeaderCell as RACCalendarHeaderCell,
RangeCalendar,
} from "react-aria-components";
import { CalendarStyles } from "./styles";
export interface CalendarRootProps<T extends DateValue>
extends React.ComponentProps<typeof Calendar<T>>,
VariantProps<typeof CalendarStyles.Root> {}
export function CalendarRoot<T extends DateValue>({
className,
variant,
...props
}: CalendarRootProps<T>) {
return (
<Calendar
className={composeRenderProps(className, (className) =>
CalendarStyles.Root({
className,
variant,
})
)}
data-slot="calendar-root"
{...props}
/>
);
}
export interface RangeCalendarRootProps<T extends DateValue>
extends React.ComponentProps<typeof RangeCalendar<T>>,
VariantProps<typeof CalendarStyles.Root> {}
export function RangeCalendarRoot<T extends DateValue>({
className,
variant,
...props
}: RangeCalendarRootProps<T>) {
return (
<RangeCalendar
className={composeRenderProps(className, (className) =>
CalendarStyles.Root({
className,
variant,
})
)}
data-slot="range-calendar-root"
{...props}
/>
);
}
export interface CalendarHeaderProps extends React.ComponentProps<"header"> {}
export function CalendarHeader({ className, ...props }: CalendarHeaderProps) {
return (
<header
className={CalendarStyles.Header({ className })}
data-slot="calendar-header"
{...props}
/>
);
}
export interface CalendarMonthProps
extends React.ComponentProps<typeof Heading> {}
export function CalendarMonth({ className, ...props }: CalendarMonthProps) {
return (
<Heading
{...props}
className={CalendarStyles.Heading({ className })}
data-slot="calendar-month"
/>
);
}
export interface CalendarNavProps extends React.ComponentProps<"nav"> {}
export function CalendarNav({ className, ...props }: CalendarNavProps) {
return (
<nav
{...props}
className={CalendarStyles.Nav({ className })}
data-slot="calendar-nav"
/>
);
}
export interface CalendarGridProps
extends React.ComponentProps<typeof RACCalendarGrid> {}
export function CalendarGrid({ className, ...props }: CalendarGridProps) {
return (
<RACCalendarGrid
{...props}
className={CalendarStyles.Grid({ className })}
data-slot="calendar-grid"
/>
);
}
export interface CalendarGridHeaderProps
extends React.ComponentProps<typeof RACCalendarGridHeader> {}
export function CalendarGridHeader(props: CalendarGridHeaderProps) {
return <RACCalendarGridHeader {...props} data-slot="calendar-grid-header" />;
}
export interface CalendarHeaderCellProps
extends React.ComponentProps<typeof RACCalendarHeaderCell> {}
export function CalendarHeaderCell({
className,
...props
}: CalendarHeaderCellProps) {
return (
<RACCalendarHeaderCell
{...props}
className={CalendarStyles.HeaderCell({ className })}
data-slot="calendar-header-cell"
/>
);
}
export interface CalendarGridBodyProps
extends React.ComponentProps<typeof RACCalendarGridBody> {}
export function CalendarGridBody(props: CalendarGridBodyProps) {
return <RACCalendarGridBody {...props} data-slot="calendar-grid-body" />;
}
export interface CalendarCellProps
extends React.ComponentProps<typeof RACCalendarCell>,
Omit<VariantProps<(typeof CalendarStyles)["Cell"]>, "isToday"> {}
export function CalendarCell({
className,
shape,
...props
}: CalendarCellProps) {
return (
<RACCalendarCell
{...props}
className={composeRenderProps(className, (className, values) =>
CalendarStyles.Cell({
className,
isToday: isToday(values.date, getLocalTimeZone()),
shape,
})
)}
data-shape={shape}
data-slot="calendar-cell"
/>
);
}
src/registry/ui/calendar/styles.ts
import { cva } from "~/registry/lib/cva";
export const CalendarStyles = {
Cell: cva({
base: [
"relative grid size-8 select-none place-content-center whitespace-nowrap text-accent-foreground text-sm outline-hidden transition",
"hover:bg-accent hover:text-accent-foreground",
"disabled:cursor-not-allowed disabled:opacity-50",
"aria-disabled:cursor-not-allowed aria-disabled:opacity-50",
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
"selected:bg-primary selected:text-primary-foreground",
"group-data-[slot=range-calendar-root]:selected:bg-accent group-data-[slot=range-calendar-root]:selected:text-accent-foreground",
"group-data-[slot=range-calendar-root]:selection-start:bg-primary group-data-[slot=range-calendar-root]:selection-start:text-primary-foreground",
"group-data-[slot=range-calendar-root]:selection-end:bg-primary group-data-[slot=range-calendar-root]:selection-end:text-primary-foreground",
],
defaultVariants: {
shape: "default",
},
variants: {
isToday: {
true: [
"after:absolute after:start-1/2 after:bottom-1 after:z-10 after:-translate-x-1/2",
"after:size-[3px] after:rounded-full after:bg-current",
],
},
shape: {
default: [
"rounded-md group-data-[slot=range-calendar-root]:not-selection-start:not-selection-end:selected:rounded-none",
],
rounded: "rounded-full",
},
},
}),
Grid: cva({
base: [
"w-full",
"[&_tr]:mt-2 [&_tr]:flex [&_tr]:w-full [&_tr]:justify-between",
"[&_tr_td[aria-selected=true]]:bg-accent",
"[&_tr_td[aria-selected=true]:has([data-selection-start])]:rounded-l-md",
"[&_tr_td[aria-selected=true]:has([data-selection-end])]:rounded-r-md",
"group-data-[slot=calendar-root]:[&_tr_td[aria-selected=true]]:rounded-md",
"[&_tr_td[aria-selected=true]:has([data-selection-start][data-shape=rounded])]:rounded-l-full",
"[&_tr_td[aria-selected=true]:has([data-selection-end][data-shape=rounded])]:rounded-r-full",
"group-data-[slot=calendar-root]:[&_tr_td:has([data-shape=rounded])[aria-selected=true]]:rounded-full",
],
}),
Header: cva({
base: ["flex w-full justify-center gap-1 px-1 pb-5 sm:pb-4"],
}),
HeaderCell: cva({
base: ["w-8 rounded-md font-normal text-[0.8rem] text-muted-foreground"],
}),
Heading: cva({
base: ["font-medium text-sm"],
}),
Nav: cva({
base: ["flex w-full items-center justify-between gap-1"],
}),
Root: cva({
base: ["group"],
variants: {
variant: {
outline: "rounded-md border p-3 shadow-sm",
},
},
}),
};
src/registry/ui/calendar/namespace.ts
export {
CalendarCell as Cell,
CalendarGrid as Grid,
CalendarGridBody as GridBody,
CalendarGridHeader as GridHeader,
CalendarHeader as Header,
CalendarHeaderCell as HeaderCell,
CalendarMonth as Month,
CalendarNav as Nav,
CalendarRoot as Root,
RangeCalendarRoot as Range,
} from "./calendar";