Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Inputs

Date Picker

Inputs

Date Picker React component for Tailwind CSS v4

Currency InputDate Range Picker
Live props
Field
label
description
error
required
invalid
disabled
readOnly
Content
placeholder
locale
invalidDateText
outOfRangeText
sheetTitle
name
Behavior
editable
autoFormat
presets
clearable
withTime
timeStep
hourCycle
closeOnSelect
responsive
weekStartsOn-1
monthYearPicker
Appearance
fixedWeeks
size
variant
radius
tone
color
Layout
numberOfMonths1
side
align
State
defaultOpen
Code
import { DatePicker } from "@/components/ui/date-picker"

<DatePicker />
  1. Home
  2. Components
  3. Inputs
  4. Date Picker
Pro

Date Picker React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React date picker: type a date in your locale or pick it from a calendar, with presets, limits, optional time and a phone sheet.

Type a date the way your locale writes it: "09232026" becomes "09/23/2026" as you type (separators appear after each group), "9/23" means this year, a 2 digit year picks the nearest century, ISO "2026-09-23" always works, "+3" is three days from today, and keywords like "today", "tomorrow" or "yesterday" work (other languages through parseKeywords). Clicking the field opens the calendar under it without taking focus from the text; while you type, the calendar follows and highlights the typed day, and a complete, allowed date is committed at once. On blur the text is re-written in the display format; text that does not parse shows invalidDateText, and a day outside min / max or a disabled day shows outOfRangeText. Escape in the field brings back the last good date. Clicking a day (or a preset chip: Today, Tomorrow, Next week or your own) sets it and closes the panel; with withTime a time field sits under the calendar and Done closes. The calendar button toggles the panel; the clear button empties the field. Keyboard: ArrowDown (or Alt+ArrowDown) opens the panel and moves focus to the selected day (else today); arrows move a day or a week, Home / End the week's ends, PageUp / PageDown a month (Shift: a year), Enter or Space picks and returns focus to the field, Escape closes without changing anything. With editable off the field is a button: a click, Enter, Space or ArrowDown open the calendar and a second click closes it. The calendar button opened from the keyboard moves focus to the selected day too. On a phone the field never raises the keyboard: a tap opens a bottom sheet with the title, presets as a row of chips, the calendar with 44px days you can swipe between months, and the time field when withTime (it opens its own wheel sheet); a tap on a day commits and closes, and with withTime or closeOnSelect off the sheet has Done and Clear buttons and dragging it away keeps the old date. name submits the ISO date through a hidden input.

Date Picker is a Pro React component in the React input components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add date-picker, together with Button, Calendar, Drawer, Field, Time Picker and 7 more and the npm packages @radix-ui/react-popover, date-fns, motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add date-picker

Date Picker is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import DatePicker from @/components/ui/date-picker.

import { useState } from "react"
import { addDays } from "date-fns"
import { DatePicker } from "@/components/ui/date-picker"

export function DeliveryDate() {
  const [date, setDate] = useState<Date | null>(null)
  return (
    <DatePicker
      label="Delivery date"
      description="We deliver Monday to Friday."
      value={date}
      onValueChange={setDate}
      locale="en-US"
      min={addDays(new Date(), 1)}
      disabled={{ dayOfWeek: [0, 6] }}
      presets
      presetLabels={{ nextWeek: "In a week" }}
      invalidDateText="That date does not exist"
      outOfRangeText="We do not deliver on that day"
      sheetTitle="Delivery date"
      name="delivery_date"
    />
  )
}

Props

  • labeldefault ""
    ReactNode

    The field label, linked to the input. Plain text also titles the phone sheet.

  • descriptiondefault ""
    ReactNode

    Helper text under the field, linked with aria-describedby.

  • errordefault ""
    ReactNode

    Replaces the description with an animated error and marks the field invalid. It wins over invalidDateText and outOfRangeText.

  • requireddefault false
    boolean

    The red mark after the label and required on the input.

  • invaliddefault false
    boolean

    The invalid look and aria-invalid without a message. A controlled value outside min / max is flagged the same way.

  • disableddefault false
    boolean or DateMatcher or DateMatcher[] (DateMatcher: Date, Date[], { from, to }, { before }, { after }, { dayOfWeek } or (date) => boolean)

    true dims the field, blocks typing and never opens the calendar (the hidden input is not submitted). A DateMatcher instead disables those days: a date, a list, { from, to }, { before }, { after }, { dayOfWeek: [0, 6] } for weekends, or a test function.

  • readOnlydefault false
    boolean

    The date stays visible and selectable but can not change: no typing, no calendar, no clear button.

  • value
    Date | null

    The date, controlled (null is empty). With withTime the Date carries the time. A value outside min / max shows as given and is flagged invalid.

  • defaultValuedefault "null"
    Date | null

    The starting date while uncontrolled. A form reset returns to it.

  • onValueChange
    (date: Date | null) => void

    Called with the new local Date as soon as a complete typed date is allowed, and after a day, a preset, a time, Clear or the sheet's Done. null when cleared.

  • placeholderdefault ""
    string

    Empty uses the locale's pattern in lowercase ("dd.mm.yyyy", "mm/dd/yyyy"). Localized forms pass their own, like "zz.ll.aaaa" in Romanian. It also becomes the screen reader format hint.

  • localedefault ""
    string

    How dates are read and written, the month and weekday names and the first day of the week: ro-RO 23.09.2026 from Monday, en-US 09/23/2026 from Sunday. Empty uses the nearest LocaleProvider, else the page's language.

  • displayFormat
    Intl.DateTimeFormatOptions

    How the value shows while the field is not focused ({ dateStyle: "long" } gives "March 5, 1990"). Typing is always numeric. Default: 2 digit day and month, numeric year.

  • editabledefault true
    boolean

    Typing on desktop. Off, the field is a button that only opens the calendar (phones always work that way).

  • autoFormatdefault true
    boolean

    Separators appear as digits are typed: "2309" becomes "23.09.".

  • parseKeywords
    Partial<Record<"today" | "tomorrow" | "yesterday", string[]>>

    Words that mean a day, matched without case or diacritics. English by default; another language passes its own words, e.g. { today: ["hoy"], tomorrow: ["mañana"], yesterday: ["ayer"] }.

  • min
    Date

    The first day that can be picked. Earlier days are disabled, navigation stops at its month and a typed earlier date shows outOfRangeText.

  • max
    Date

    The last day that can be picked (18 years ago for a birthday).

  • presetsdefault false
    boolean | { label: ReactNode; value: Date | (() => Date); key?: string }[]

    Chips above the calendar. true gives Today, Tomorrow and Next week; or pass your own. A preset outside the limits is disabled.

  • presetLabels
    Partial<{ today: string; tomorrow: string; nextWeek: string }>

    Names of the built-in presets ("Today", "Tomorrow", "Next week").

  • clearabledefault true
    boolean

    A clear button in the field while it has a date (and Clear in the panel footer and the sheet).

  • withTimedefault false
    boolean

    A time field under the calendar; the value keeps both and the field reads "24.09.2026, 14:30". Picking a day keeps the panel open until Done. Clearing keeps the time for the next pick.

  • timeStepdefault "15"
    number

    Minute step of the time field.

  • hourCycledefault "auto"
    "auto" | "h12" | "h23"

    12 or 24 hours for the time; auto follows the locale.

  • timeProps
    Partial<TimePickerProps>

    Anything else for the time field: labels, min, max, disabledTimes, showNow.

  • closeOnSelectdefault true
    boolean

    Picking a day closes the panel. Never with withTime. Off, the panel (and the sheet) get a Done button.

  • responsivedefault true
    boolean

    Below 768px the field opens a bottom sheet instead of the popover. Off, phones get the popover and can type.

  • weekStartsOndefault -1
    0 | 1 | 2 | 3 | 4 | 5 | 6 | -1

    The first day of the week: 0 Sunday ... 6 Saturday; -1 follows the locale (Monday in ro-RO, Sunday in en-US).

  • fixedWeeksdefault true
    boolean

    Six weeks in every month, so the panel never changes height while you browse.

  • monthYearPickerdefault true
    boolean

    The calendar caption opens a months grid, then a years grid, for fast jumps (birthdays).

  • numberOfMonthsdefault 1
    number

    Months side by side in the popover (1 to 3). The phone sheet always shows one.

  • events
    { date: Date; tone?: Tone; color?: string; label?: string }[]

    Dots under days (deliveries, deadlines); labels join the day's aria-label.

  • calendarProps
    Partial<CalendarProps>

    Anything else for the calendar: size, radius, strikeDisabled, showWeekNumbers, todayButton, renderDay, labels.

  • invalidDateTextdefault "Enter a valid date"
    string

    The error after blur while the text does not parse ("31.02.2026").

  • outOfRangeTextdefault "This date is not available"
    string

    The error after blur for a typed day outside min / max or a disabled day.

  • defaultOpendefault false
    boolean

    Starts with the calendar (or the sheet) open. Pass open and onOpenChange to control it.

  • open
    boolean

    Whether the calendar is open, controlled. It never opens while disabled or readOnly.

  • onOpenChange
    (open: boolean) => void

    Called when the popover or sheet opens or closes.

  • sizedefault "md"
    "sm" | "md" | "lg"

    Field heights of 32, 40 and 48px (md is 44px on touch screens), with matching text.

  • variantdefault "soft"
    "soft" | "outline" | "underline" | "ghost"

    The field box: a tinted fill, a border, a bottom line that grows on focus, or nothing until hover.

  • radiusdefault "md"
    "none" | "sm" | "md" | "lg" | "full"

    Corner radius of the field, scaled per size like the button. Ignored by underline.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The selected day, the chosen preset and the Done button.

  • colordefault ""
    string

    Any CSS color for the selection; replaces the tone.

  • icon
    ReactNode

    The calendar button's icon.

  • sheetTitledefault "Select date"
    string

    The phone sheet's title when the label is not plain text (or missing).

  • labels
    Partial<{ clear; open; done; dialog; time; presets; format: string }>

    Every other string, merged over the English defaults ("Clear", "Open calendar", "Done", "Choose date", "Time", "Quick picks", "Format: {format}"). format is the screen reader hint after the field.

  • namedefault ""
    string

    A hidden input with this name and the local ISO date ("2026-09-23", "2026-09-23T14:30" with withTime), never shifted to UTC.

  • sidedefault "bottom"
    "top" | "right" | "bottom" | "left"

    Where the popover opens; it flips when there is no room.

  • aligndefault "start"
    "start" | "center" | "end"

    How the popover lines up with the field.

  • container
    HTMLElement | null

    Portal target of the popover and the sheet; defaults to document.body.

  • fieldProps
    Partial<FieldProps>

    Anything else for the Field wrapper: optional, labelAction, orientation, labelWidth, hideLabel.

  • id
    string

    The input's id; generated when left out.

  • classNames
    Partial<Record<"field" | "label" | "description" | "error" | "counter" | "box" | "input" | "trigger" | "clear" | "content" | "presets" | "preset" | "calendar" | "time" | "footer", string>>

    Extra classes for the inner parts. content is the popover (or the sheet).

  • className
    string

    Extra classes for the outermost element: the Field when there is a label or message, else the box.

  • ref
    Ref<HTMLInputElement> (a useRef object or an (el) => void callback)

    The text input. Other props (onBlur, autoFocus, aria-*, data-*) land on it too.

Parts

  • DatePreset

    type

    One preset button: { label, value: Date | (() => Date), key? }.

Examples

Birthday

max 18 years ago, the long display format ("March 5, 1990") and the month / year grid for jumping decades.

With time

withTime adds a time field under the calendar; the field reads the date and time ("mm/dd/yyyy, 2:30 PM") and the hidden input sends the ISO date-time ("yyyy-mm-ddT14:30").

Typed formats

One value in ro-RO (23.09.2026, Monday first) and en-US (09/23/2026, Sunday first). Try 0923, 9/23, ISO, tomorrow or +3.

Errors

A date that does not exist shows invalidDateText after blur, a weekend shows outOfRangeText; the second field has a consumer error.

Holidays

Public holidays disabled and struck through with calendarProps, rounded-square days and a short weekday display.

Button only

editable={false}: a large outline field that only opens the calendar, with a custom teal selection.

Custom presets

Your own quick picks, fixed or computed when the panel opens, in the success tone.

Sizes and variants

sm, md and lg in the four field boxes.

Dependencies

@radix-ui/react-popoverdate-fnsmotionlucide-reactbuttoncalendardrawerfieldtime-pickerdate-utilsuse-controllable-stateuse-localeuse-media-querymotiontonesui-config

Files

  • components/ui/date-picker.tsx

FAQ

Is the React Date Picker component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Date Picker?

Run npx wingo-ui@latest add date-picker. It also adds the Wingo UI items it builds on (Button, Calendar, Drawer, Field, Time Picker and 7 more) and the npm packages @radix-ui/react-popover, date-fns, motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/date-picker.

How does Date Picker behave on phones?

Below 768px the field opens a bottom sheet instead of the popover. Off, phones get the popover and can type. The responsive prop controls this and is on by default.

See also

CalendarDate Range PickerTime PickerFieldDrawer

Used in

Filter BuilderGanttEditable GridCRM Contact PageCRM Pipeline PageInvoice PageRestaurant Page

More React input components

Date Time PickerEmail InputEmoji PickerFile UploadInputInput Group
All 40 React input components

Articles using this component

  • Nextjs Restaurant Template: Open Now, Menu, Book a Table

    Build it: screens and apps · Nov 6, 2026 · 10 min read

  • Mantine vs shadcn in 2026: Which React UI Library to Pick

    Comparisons and alternatives · Oct 16, 2026 · 11 min read

  • MUI Alternatives for React and Tailwind in 2026

    Comparisons and alternatives · Oct 13, 2026 · 10 min read

  • React Date Range Picker With Presets and a Phone Sheet

    Component guides · Oct 13, 2026 · 9 min read

PreviousCurrency InputNext Date Range Picker

Schedule delivery

Order #48213 · 233 S Wacker Dr, Chicago

Courier
Format: mm/dd/yyyy

value: "2026-11-09" · time: 15 min, auto

Type 9/25, tomorrow or +3 · separators appear on their own · a day closes the panel · on a phone: a “Select date” sheet

02/31/2026 → “Enter a valid date” · a Saturday → “We deliver Monday to Friday, starting tomorrow.”

↓Down arrow calendar EnterEnter pick EscEscape close