Skip to content
SuperCoach

Components · Inputs

Calendar

Beta

Shows and picks dates, such as scheduled sessions.

November 2026

Session with Sara: Thu, 12 Nov

When to use

  • To pick a date when seeing the month helps: which days are free for a session, which week a check-in falls in.
  • To pick a range, such as the period of a check-in report.
  • Inline on a page or in a card, when the calendar is the main thing the coach works with.

When not to use

  • In a form field: use a Date picker, which opens this calendar in a popover and keeps the form compact.
  • For dates far in the past, such as a date of birth, a calendar is slow. Use the month and year menus (below) or three inputs for day, month and year.
  • To show a schedule of sessions with times: that is a scheduling view, not a date input.

Anatomy

November 2026
  1. 1. Month caption: month and year in the calendar's locale
  2. 2. Previous and next month buttons, at the edges of the caption row
  3. 3. Weekday names, starting on the locale's first day of the week
  4. 4. Day: a button in the grid; here the selected day

The calendar is shadcn's wrapper around React DayPicker. Dates come from the locale you pass, so month and weekday names, the first day of the week and the screen reader labels all follow the language.

Variants

Range: check-in report
November 2026
Month and year menus: date of birth
March 1994
  • Single date (mode="single"): one selected day, as in the first example.
  • Range (mode="range"): start and end in primary, the days between in accent. Use it for report periods and plan phases.
  • Several dates (mode="multiple"): for picking training days across a month.
  • Month and year menus (captionLayout="dropdown"): replaces the caption with two menus. Set startMonth and endMonth to a sensible span.
  • Several months (numberOfMonths={2}): side by side on wide screens, stacked on narrow ones. Good for ranges that cross a month.

States

November 2026

Fridays and 1–7 Nov are unavailable.

StateWhat changesToken
HoverAccent fill on the daybg-accent, text-accent-foreground
Focus-visibleRing around the focused day, raised above its neighboursborder-ring, ring-ring/50, z-(--z-raised)
TodayAccent fillbg-accent, text-accent-foreground
SelectedPrimary fillbg-primary, text-primary-foreground
Range start and endPrimary fill, rounded on the outer sidebg-primary, rounded-s-md, rounded-e-md
Range middleAccent fill, square cornersbg-accent, text-accent-foreground
Outside the monthMuted text, still selectabletext-muted-foreground
DisabledMuted text; the day button is disabled, so it also drops to half opacitytext-muted-foreground, opacity-(--opacity-disabled)

The selected day uses the same pair as the primary button. In Coach, white on orange is 2.8:1 until decision #3 is settled.

Usage guidelines

Do.Dates written as on the Content page: weekday, day, short month.
Don't.Numeric dates. 11/02 is 2 November in the US and 11 February in the Gulf.
  • Disable days that can't be picked (the coach's days off, fully booked days) and say why in text next to the calendar. Color alone doesn't explain it.
  • Open on the month that matters: the selected date's month, or the program's start month (defaultMonth).
  • Keep outside days visible (the default). They help coaches see the week a date belongs to.
  • Pass the locale and numerals="latn" every time, so Arabic screens show Arabic month names with Western digits (QUESTIONS Q22).

Content guidelines

  • Selected dates shown next to the calendar follow the Content formats: "Thu, 12 Nov" and "الخميس، 12 نوفمبر"; ranges "2–15 Nov".
  • Explain disabled days in one line: "Fridays and 1–7 Nov are unavailable."
  • Give the calendar an aria-label that says what the date is for: "Session date", not "Calendar".

Accessibility

KeyDoes
TabMoves between the month buttons and the grid; the grid is one tab stop
Arrow keysMove one day or one week (left and right follow the reading direction)
Home / EndFirst or last day of the week
Page up / downPrevious or next month
Shift + Page up / downPrevious or next year
Enter, SpaceSelects the focused day
  • The month is a table with role="grid", labelled with the month and year. Each day is a button labelled with the visible number first, then the full date: a screen reader announces "12, Thursday, November 12th, 2026, selected" or, on Arabic screens, the same in Arabic. Starting with the number keeps the visible label in the name (WCAG 2.5.3), so voice-control users can say "click 12".
  • Today is announced with "Today" in front of the date.
  • Disabled days are skipped by the arrow keys and announced as unavailable.
  • The month buttons are labelled "Go to the Previous Month" and "Go to the Next Month", in Arabic on Arabic screens. These labels come from the react-day-picker/locale package, so import the locale from there rather than from date-fns/locale, which has no DayPicker labels.

RTL

  • The calendar takes its direction from the Radix DirectionProvider, so the week starts on the right and runs right to left.
  • The previous-month button is on the right and the next-month button on the left; their chevrons rotate 180° so they point outwards.
  • Left and right arrow keys follow the visual order: Arrow left goes to the next day.
  • Range ends round on the logical side (rounded-s-md, rounded-e-md), so a range reads correctly in both directions.
  • With the Arabic locale, weeks start on Saturday, as in the Gulf. Digits stay Western with numerals="latn".

Tokens used

Read from components/ui/calendar.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--accentbg-accentbrand-50orange-50
--accent-foregroundtext-accent-foregroundbrand-700orange-700
--backgroundbg-backgroundwhitewhite
--inputborder-inputneutral-200neutral-200
--muted-foregroundtext-muted-foregroundneutral-600neutral-600
--popoverbg-popoverwhitewhite
--primarybg-primarybrand-600orange-500
--primary-foregroundtext-primary-foregroundwhitewhite
--ringborder-ring ring-ring/50brand-600orange-500
  • Layerz-(--z-raised)
  • Opacityopacity-(--opacity-disabled)
  • Radiusrounded-md rounded-e-md rounded-s-md
  • Radiusrounded-none
  • Shadowshadow-xs
  • Typefont-medium
  • Typeleading-none
  • Typefont-regular
  • Typetext-sm
  • Typetext-xs

Props

The table lists the props the wrapper adds; the calendar also takes every DayPicker prop, such as mode, selected, onSelect, disabled, locale, numerals and captionLayout.

<Calendar>

Also takes every prop of <DayPicker>

Calendar props
PropTypeDefault
buttonVariant?React.ComponentProps<typeof Button>["variant"]"ghost"

<CalendarDayButton>

Also takes every prop of <DayButton>

No props of its own.

Replaces in coach-admin

From the read-only audit of coach-admin: 16 style values, 19 uses.

coach-admin's calendar view is built on react-big-calendar (rbc- classes) with task cards on each day. Its month grid and toolbar styles map to this component; the task cards and the scheduling view around them are a separate pattern.

Classes and selectors

  • .rbc-header4
  • .rbc-date-cell3
  • .rbc-month-view2
  • .rbc-off-range-bg1
  • .calendar-toolbar1
  • .rbc-month-row1
  • .rw-calendar1
  • .rbc-month-header1

Files

  • src/reusableComponents/calendar/Calendar.tsx5

The inventory lists the first 12 locations of each value, so file counts are a lower bound.

Date picker, Popover, Form, Content, RTL.