Components
Date picker

Date Picker

A component that allows users to select a date from a calendar.

Usage

import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Button } from '~/components/ui/button'
import * as DatePicker from '~/components/ui/date-picker'
import { IconButton } from '~/components/ui/icon-button'
import { Input } from '~/components/ui/input'

export const Demo = (props: DatePicker.RootProps) => {
  return (
    <DatePicker.Root
      positioning={{ sameWidth: true }}
      startOfWeek={1}
      selectionMode="range"
      {...props}
    >
      <DatePicker.Label>Date Picker</DatePicker.Label>
      <DatePicker.Control>
        <DatePicker.Input index={0} asChild>
          <Input />
        </DatePicker.Input>
        <DatePicker.Input index={1} asChild>
          <Input />
        </DatePicker.Input>
        <DatePicker.Trigger asChild>
          <IconButton variant="outline" aria-label="Open date picker">
            <CalendarIcon />
          </IconButton>
        </DatePicker.Trigger>
      </DatePicker.Control>
      <DatePicker.Positioner>
        <DatePicker.Content>
          <DatePicker.View view="day">
            {(api) => (
              <>
                <DatePicker.ViewControl>
                  <DatePicker.PrevTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronLeftIcon />
                    </IconButton>
                  </DatePicker.PrevTrigger>
                  <DatePicker.ViewTrigger asChild>
                    <Button variant="ghost" size="sm">
                      <DatePicker.RangeText />
                    </Button>
                  </DatePicker.ViewTrigger>
                  <DatePicker.NextTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronRightIcon />
                    </IconButton>
                  </DatePicker.NextTrigger>
                </DatePicker.ViewControl>
                <DatePicker.Table>
                  <DatePicker.TableHead>
                    <DatePicker.TableRow>
                      {api.weekDays.map((weekDay, id) => (
                        <DatePicker.TableHeader key={id}>{weekDay.narrow}</DatePicker.TableHeader>
                      ))}
                    </DatePicker.TableRow>
                  </DatePicker.TableHead>
                  <DatePicker.TableBody>
                    {api.weeks.map((week, id) => (
                      <DatePicker.TableRow key={id}>
                        {week.map((day, id) => (
                          <DatePicker.TableCell key={id} value={day}>
                            <DatePicker.TableCellTrigger asChild>
                              <IconButton variant="ghost">{day.day}</IconButton>
                            </DatePicker.TableCellTrigger>
                          </DatePicker.TableCell>
                        ))}
                      </DatePicker.TableRow>
                    ))}
                  </DatePicker.TableBody>
                </DatePicker.Table>
              </>
            )}
          </DatePicker.View>
          <DatePicker.View view="month">
            {(api) => (
              <>
                <DatePicker.ViewControl>
                  <DatePicker.PrevTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronLeftIcon />
                    </IconButton>
                  </DatePicker.PrevTrigger>
                  <DatePicker.ViewTrigger asChild>
                    <Button variant="ghost" size="sm">
                      <DatePicker.RangeText />
                    </Button>
                  </DatePicker.ViewTrigger>
                  <DatePicker.NextTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronRightIcon />
                    </IconButton>
                  </DatePicker.NextTrigger>
                </DatePicker.ViewControl>
                <DatePicker.Table>
                  <DatePicker.TableBody>
                    {api.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => (
                      <DatePicker.TableRow key={id}>
                        {months.map((month, id) => (
                          <DatePicker.TableCell key={id} value={month.value}>
                            <DatePicker.TableCellTrigger asChild>
                              <Button variant="ghost">{month.label}</Button>
                            </DatePicker.TableCellTrigger>
                          </DatePicker.TableCell>
                        ))}
                      </DatePicker.TableRow>
                    ))}
                  </DatePicker.TableBody>
                </DatePicker.Table>
              </>
            )}
          </DatePicker.View>
          <DatePicker.View view="year">
            {(api) => (
              <>
                <DatePicker.ViewControl>
                  <DatePicker.PrevTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronLeftIcon />
                    </IconButton>
                  </DatePicker.PrevTrigger>
                  <DatePicker.ViewTrigger asChild>
                    <Button variant="ghost" size="sm">
                      <DatePicker.RangeText />
                    </Button>
                  </DatePicker.ViewTrigger>
                  <DatePicker.NextTrigger asChild>
                    <IconButton variant="ghost" size="sm">
                      <ChevronRightIcon />
                    </IconButton>
                  </DatePicker.NextTrigger>
                </DatePicker.ViewControl>
                <DatePicker.Table>
                  <DatePicker.TableBody>
                    {api.getYearsGrid({ columns: 4 }).map((years, id) => (
                      <DatePicker.TableRow key={id}>
                        {years.map((year, id) => (
                          <DatePicker.TableCell key={id} value={year.value}>
                            <DatePicker.TableCellTrigger asChild>
                              <Button variant="ghost">{year.label}</Button>
                            </DatePicker.TableCellTrigger>
                          </DatePicker.TableCell>
                        ))}
                      </DatePicker.TableRow>
                    ))}
                  </DatePicker.TableBody>
                </DatePicker.Table>
              </>
            )}
          </DatePicker.View>
        </DatePicker.Content>
      </DatePicker.Positioner>
    </DatePicker.Root>
  )
}

Installation

1

Add Component

Insert code snippet into your project. Update import paths as needed.

import { DatePicker } from '@ark-ui/react/date-picker'
import type { ComponentProps } from 'react'
import { styled } from 'styled-system/jsx'
import { datePicker } from 'styled-system/recipes'
import { createStyleContext } from '~/lib/create-style-context'

const { withProvider, withContext } = createStyleContext(datePicker)

export const Root = withProvider(styled(DatePicker.Root), 'root')
export const ClearTrigger = withContext(styled(DatePicker.ClearTrigger), 'clearTrigger')
export const Content = withContext(styled(DatePicker.Content), 'content')
export const Control = withContext(styled(DatePicker.Control), 'control')
export const Input = withContext(styled(DatePicker.Input), 'input')
export const Label = withContext(styled(DatePicker.Label), 'label')
export const MonthSelect = withContext(styled(DatePicker.MonthSelect), 'monthSelect')
export const NextTrigger = withContext(styled(DatePicker.NextTrigger), 'nextTrigger')
export const Positioner = withContext(styled(DatePicker.Positioner), 'positioner')
export const PresetTrigger = withContext(styled(DatePicker.PresetTrigger), 'presetTrigger')
export const PrevTrigger = withContext(styled(DatePicker.PrevTrigger), 'prevTrigger')
export const RangeText = withContext(styled(DatePicker.RangeText), 'rangeText')
export const Table = withContext(styled(DatePicker.Table), 'table')
export const TableBody = withContext(styled(DatePicker.TableBody), 'tableBody')
export const TableCell = withContext(styled(DatePicker.TableCell), 'tableCell')
export const TableCellTrigger = withContext(styled(DatePicker.TableCellTrigger), 'tableCellTrigger')
export const TableHead = withContext(styled(DatePicker.TableHead), 'tableHead')
export const TableHeader = withContext(styled(DatePicker.TableHeader), 'tableHeader')
export const TableRow = withContext(styled(DatePicker.TableRow), 'tableRow')
export const Trigger = withContext(styled(DatePicker.Trigger), 'trigger')
export const View = withContext(styled(DatePicker.View), 'view')
export const ViewControl = withContext(styled(DatePicker.ViewControl), 'viewControl')
export const ViewTrigger = withContext(styled(DatePicker.ViewTrigger), 'viewTrigger')
export const YearSelect = withContext(styled(DatePicker.YearSelect), 'yearSelect')

export interface RootProps extends ComponentProps<typeof Root> {}
export interface ClearTriggerProps extends ComponentProps<typeof ClearTrigger> {}
export interface ContentProps extends ComponentProps<typeof Content> {}
export interface ControlProps extends ComponentProps<typeof Control> {}
export interface InputProps extends ComponentProps<typeof Input> {}
export interface LabelProps extends ComponentProps<typeof Label> {}
export interface MonthSelectProps extends ComponentProps<typeof MonthSelect> {}
export interface NextTriggerProps extends ComponentProps<typeof NextTrigger> {}
export interface PositionerProps extends ComponentProps<typeof Positioner> {}
export interface PresetTriggerProps extends ComponentProps<typeof PresetTrigger> {}
export interface PrevTriggerProps extends ComponentProps<typeof PrevTrigger> {}
export interface RangeTextProps extends ComponentProps<typeof RangeText> {}
export interface TableProps extends ComponentProps<typeof Table> {}
export interface TableBodyProps extends ComponentProps<typeof TableBody> {}
export interface TableCellProps extends ComponentProps<typeof TableCell> {}
export interface TableCellTriggerProps extends ComponentProps<typeof TableCellTrigger> {}
export interface TableHeadProps extends ComponentProps<typeof TableHead> {}
export interface TableHeaderProps extends ComponentProps<typeof TableHeader> {}
export interface TableRowProps extends ComponentProps<typeof TableRow> {}
export interface TriggerProps extends ComponentProps<typeof Trigger> {}
export interface ViewProps extends ComponentProps<typeof View> {}
export interface ViewControlProps extends ComponentProps<typeof ViewControl> {}
export interface ViewTriggerProps extends ComponentProps<typeof ViewTrigger> {}
export interface YearSelectProps extends ComponentProps<typeof YearSelect> {}
2

Add Recipe

This step is necessary only if you do not use any of the Park UI plugins.

import { datePickerAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'

export const datePicker = defineSlotRecipe({
  className: 'datePicker',
  slots: [...datePickerAnatomy.keys()],
  base: {
    root: {
      colorPalette: 'accent',
      display: 'flex',
      flexDirection: 'column',
      gap: '1.5',
    },
    content: {
      background: 'bg.default',
      borderRadius: 'l3',
      boxShadow: 'lg',
      display: 'flex',
      flexDirection: 'column',
      gap: '3',
      p: '4',
      width: '344px',
      zIndex: 'dropdown',
      _open: {
        animation: 'fadeIn 0.25s ease-out',
      },
      _closed: {
        animation: 'fadeOut 0.2s ease-out',
      },
      _hidden: {
        display: 'none',
      },
    },
    control: {
      display: 'flex',
      flexDirection: 'row',
      gap: '2',
    },
    label: {
      color: 'fg.default',
      fontWeight: 'medium',
      textStyle: 'sm',
    },
    tableHeader: {
      color: 'fg.muted',
      fontWeight: 'semibold',
      height: '10',
      textStyle: 'sm',
    },
    viewControl: {
      display: 'flex',
      gap: '2',
      justifyContent: 'space-between',
    },
    table: {
      width: 'full',
      borderCollapse: 'separate',
      borderSpacing: '1',
      m: '-1',
    },
    tableCell: {
      textAlign: 'center',
    },
    tableCellTrigger: {
      width: '100%',
      _today: {
        _before: {
          content: "'−'",
          color: 'colorPalette.default',
          position: 'absolute',
          marginTop: '6',
        },
      },
      '&[data-in-range]': {
        background: 'bg.muted',
      },
      _selected: {
        _before: {
          color: 'colorPalette.fg',
        },
      },
    },
    view: {
      display: 'flex',
      flexDirection: 'column',
      gap: '3',
      _hidden: {
        display: 'none',
      },
    },
  },
})

Previous

Combobox

On this page