TWIGS

Calendar

A date field component that allows users to enter and edit date.

Playground

April 2026
April 2026

Installation

Install in any React + Tailwind project:

$npx shadcn@latest add https://twigs.globirdenergy.com.au/r/calendar.json

Source

The exact file the registry serves to consumers.

'use client';

import * as React from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { DayPicker, getDefaultClassNames } from 'react-day-picker';
import { cn } from '@/lib/utils';
import { buttonVariants } from '@/registry/new-york/ui/button';

// Spec source: Figma "APP Re-design Phase 1" → page "Calendar ✅"
// Nav button 28x28 pill, border #e5e5e5; selected day uses GB pink
function Calendar({
  className,
  classNames,
  showOutsideDays = true,
  ...props
}: React.ComponentProps<typeof DayPicker>) {
  const defaults = getDefaultClassNames();
  return (
    <DayPicker
      data-slot="calendar"
      showOutsideDays={showOutsideDays}
      className={cn('p-3', className)}
      classNames={{
        ...defaults,
        months: cn(defaults.months, 'relative flex flex-col gap-4 sm:flex-row'),
        month: cn(defaults.month, 'flex flex-col gap-4'),
        month_caption: cn(defaults.month_caption, 'flex h-7 items-center justify-center'),
        caption_label: cn(defaults.caption_label, 'text-sm font-medium'),
        nav: cn(defaults.nav, 'absolute inset-x-0 top-0 flex items-center justify-between'),
        button_previous: cn(
          defaults.button_previous,
          buttonVariants({ variant: 'outline', size: 'icon' }),
          'size-7 rounded-full bg-transparent p-0 opacity-50 hover:opacity-100',
        ),
        button_next: cn(
          defaults.button_next,
          buttonVariants({ variant: 'outline', size: 'icon' }),
          'size-7 rounded-full bg-transparent p-0 opacity-50 hover:opacity-100',
        ),
        month_grid: cn(defaults.month_grid, 'w-full border-collapse space-x-1'),
        weekdays: cn(defaults.weekdays, 'flex'),
        weekday: cn(defaults.weekday, 'text-muted-foreground w-9 rounded-md text-[0.8rem] font-normal'),
        week: cn(defaults.week, 'mt-2 flex w-full'),
        day: cn(defaults.day, 'relative size-9 p-0 text-center text-sm focus-within:relative focus-within:z-20'),
        day_button: cn(
          defaults.day_button,
          buttonVariants({ variant: 'ghost' }),
          'size-9 rounded-full p-0 font-normal',
        ),
        selected: 'bg-primary text-primary-foreground rounded-full hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
        today: 'bg-accent text-accent-foreground rounded-full',
        range_start: 'bg-primary text-primary-foreground rounded-l-full',
        range_end: 'bg-primary text-primary-foreground rounded-r-full',
        range_middle: 'bg-accent text-accent-foreground rounded-none',
        outside: 'text-muted-foreground opacity-50',
        disabled: 'text-muted-foreground opacity-50',
        hidden: 'invisible',
        ...classNames,
      }}
      components={{
        Chevron: ({ orientation, ...rest }) =>
          orientation === 'left' ? (
            <ChevronLeft className="size-4" {...rest} />
          ) : (
            <ChevronRight className="size-4" {...rest} />
          ),
      }}
      {...props}
    />
  );
}

export { Calendar };