Skip to content
Drivn logoDrivn
4 min read

Drivn vs shadcn/ui — Calendar Component Compared

Side-by-side comparison of Drivn and shadcn/ui React Calendar components — built-in variants, range mode API, react-day-picker base, and locale setup.

Drivn and shadcn/ui both build their Calendar on top of react-day-picker, which means the runtime dependency story is identical — DayPicker does the heavy lifting for keyboard navigation, locale switching, and accessibility on both sides. Where the two diverge is how much surface each library exposes to you. shadcn ships a minimal classNames-only wrapper and leaves variant selection as configuration you assemble in every file. Drivn collapses the three most common configurations — plain, week numbers, caption dropdowns — into a single variant prop and exposes range mode via dot notation as Calendar.Range.

That trade-off shows up the first time you need a month and year dropdown. In shadcn you pass captionLayout="dropdown" plus startMonth, endMonth, and classNames overrides to style the caption row. In Drivn you write <Calendar variant="dropdown" /> and the fromYear and toYear defaults already cover a forty-year window centered on today. Both calendars render the same DOM and share the same keyboard model, because react-day-picker owns the accessibility work underneath.

This page compares every surface that differs: API shape, variant ergonomics, range mode, chevron customization, and locale wiring. Every snippet below is runnable against the current CLI release. If you already use react-day-picker directly or via shadcn, the Drivn Calendar will feel familiar — what changes is the import count and how much caption plumbing you write per screen.

Side-by-side comparison

FeatureDrivnshadcn/ui
Underlying libraryreact-day-pickerreact-day-picker
API styleDot notation (Calendar.Range)Named exports + mode prop
Built-in variantsdefault | weekNumbers | dropdownConfigure props each call
Year range shortcutsfromYear / toYear propsManual startMonth / endMonth
Range mode<Calendar.Range /><Calendar mode="range" />
Chevron iconslucide-react (editable)lucide-react (editable)
Locale supportreact-day-picker/localereact-day-picker/locale
Accessibilityreact-day-picker baselinereact-day-picker baseline
LicenseMITMIT
Copy-paste install

API side-by-side

shadcn/ui exports a single Calendar component and changes behavior via a mode prop — mode="single", mode="multiple", or mode="range". Drivn exports Calendar for single-date selection and mounts range mode on the same object as Calendar.Range. One dot access, no mode string, no cast. The Calendar docs cover every prop passed through to react-day-picker.

The usage divergence is small per component but compounds across a form with several pickers. A single import line covers both the single and range variants in Drivn, and TypeScript narrows each to the right selected and onSelect pair — a Date | undefined on the root and a DateRange | undefined on Calendar.Range — without you choosing between union types at the call site.

1// shadcn/ui — named exports + mode prop
2import { Calendar } from '@/components/ui/calendar'
3
4<Calendar
5 mode="single"
6 selected={date}
7 onSelect={setDate}
8/>
9
10<Calendar
11 mode="range"
12 selected={range}
13 onSelect={setRange}
14/>
15
16// Drivn — dot notation, root stays single-mode
17import { Calendar } from '@/components/ui/calendar'
18
19<Calendar selected={date} onSelect={setDate} />
20
21<Calendar.Range selected={range} onSelect={setRange} />

Built-in variants

Drivn exposes three variants through a variant prop: default, weekNumbers, and dropdown. Each maps to a preset object of react-day-picker config, so variant="weekNumbers" flips showWeekNumber to true and variant="dropdown" flips captionLayout to dropdown plus applies the dropdownOverrides classNames for the select-style caption row. shadcn/ui leaves all three as loose props you wire at every call site.

The dropdown variant also reads fromYear and toYear props and converts them into startMonth and endMonth Date objects for react-day-picker. The default window is today plus or minus twenty years. shadcn does not provide the fromYear / toYear shortcut — you build the Date objects yourself and pass them through. For a booking form with a tight three-year window, Drivn saves two lines per picker.

1// Drivn
2<Calendar variant="weekNumbers" selected={date} onSelect={setDate} />
3
4<Calendar variant="dropdown" fromYear={2000} toYear={2030} />
5
6// shadcn/ui equivalent
7<Calendar showWeekNumber mode="single" selected={date} onSelect={setDate} />
8
9<Calendar
10 mode="single"
11 captionLayout="dropdown"
12 startMonth={new Date(2000, 0)}
13 endMonth={new Date(2030, 11)}
14/>

Range mode with Calendar.Range

Date range selection is one of the most common calendar patterns — think booking flows, reporting periods, leave requests. Both libraries wrap react-day-picker's mode="range", but they surface it differently. shadcn reuses the same Calendar with a different mode string; Drivn mounts it as Calendar.Range, which is a pure TypeScript win because the selected prop narrows to DateRange | undefined automatically.

Drivn's range component also applies a rangeActive class set only once the range spans more than one day — the range_start, range_middle, and range_end cells get bg-primary with rounded-left and rounded-right corners. If you only need single-day selection wrapped in a popover with a formatted input, use the Date Picker component, which composes Calendar with Popover and Input.

1'use client'
2import { useState } from 'react'
3import { Calendar, type DateRange } from '@/components/ui/calendar'
4
5export function DateRangeField() {
6 const [range, setRange] = useState<DateRange | undefined>()
7 return <Calendar.Range selected={range} onSelect={setRange} />
8}

Locale and internationalization

Both libraries accept a locale prop from react-day-picker/locale and pass it through to the underlying locale object. Drivn imports it like import { cs } from 'react-day-picker/locale' and passes it to <Calendar locale={cs} />. That applies month names, weekday labels, and first-day-of-week conventions in one line. No extra i18n dependency, no provider, no context — the locale is plain data that travels with the prop.

If you already use a heavier i18n library such as lingui or next-intl in your Next.js app, the Calendar does not read from it. You pass the matching react-day-picker locale for whatever active locale your app has resolved. The installation guide has the full setup — after npx drivn add calendar the component imports are identical between Drivn and shadcn on this axis.

1import { Calendar } from '@/components/ui/calendar'
2import { cs } from 'react-day-picker/locale'
3
4<Calendar locale={cs} selected={date} onSelect={setDate} />
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

Yes — react-day-picker and lucide-react. This is one of the few Drivn components that ships with a runtime UI dependency, because building an accessible date grid from scratch would duplicate work react-day-picker already does well. The styling, variant preset logic, and chevron icons are Drivn's; the keyboard handling, focus trap, and ARIA attributes come from react-day-picker.

Yes. Range selection lives on the same import as single-date selection. You write Calendar.Range instead of Calendar, pass a DateRange object to selected, and get back a typed range on onSelect. No second component to install, no wrapper div, and no mode string — dot notation carries the variation at the call site.

Set fromYear and toYear on the Calendar component. The defaults are today's year minus twenty and plus twenty, which suits birthday pickers and near-future scheduling. Pass explicit numbers for anything tighter or wider — Drivn converts them into the startMonth and endMonth Date objects that react-day-picker expects, so the dropdown caption lists exactly the years you asked for.

Yes, because react-day-picker drives the keyboard model and ARIA attributes on both Drivn and shadcn. Arrow keys navigate days, Page Up and Page Down navigate months, Home and End jump to the start and end of a week, and screen readers announce the currently selected date. Drivn does not override this behavior — the only additions are visual styling and the variant preset shortcuts.