Date

Date picker with calendar and keyboard navigation.

import { Date } from 'ui-lab-components/date';
import { Date as DatePicker } from 'ui-lab-components/date';
 
export default function Example() {
  return <DatePicker defaultMonth={new Date(2026, 0)} />;
}
 

date/01-basic-date

A simple date component for date selection with today indicator and week numbers. Click a date to select it.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
 
export default function Example() {
  const [date, setDate] = React.useState<globalThis.Date | null>(null)
  return <DatePicker value={date} onChange={setDate} />
}
 

date/02-with-disabled-dates

Date component with certain dates disabled (weekends). Disabled dates cannot be selected.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
 
export default function Example() {
  const [date, setDate] = React.useState<globalThis.Date | null>(null)
 
  const disabled = React.useCallback(
    (dateToCompare: globalThis.Date) => {
      const day = dateToCompare.getDay()
      return day === 0 || day === 6 // Disable weekends only
    },
    []
  )
 
  return <DatePicker value={date} onChange={setDate} disabled={disabled} />
}
 

date/03-controlled-mode

Date picker with controlled value and external state management. Includes a "Today" button to programmatically set the current date.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
import { Button } from 'ui-lab-components/button'
import { Flex } from 'ui-lab-components/flex'
 
export default function Example() {
  const [date, setDate] = React.useState<globalThis.Date | null>(null)
 
  const handleSetToday = () => {
    setDate(new Date())
  }
 
  const handleClear = () => {
    setDate(null)
  }
 
  const formatDate = (d: globalThis.Date | null) => {
    if (!d) return 'No date selected'
    return d.toLocaleDateString('en-US', {
      weekday: 'long',
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    })
  }
 
  return (
    <Flex direction="column" gap="md">
      <Flex gap="sm">
        <Button variant="primary" onClick={handleSetToday}>
          Today
        </Button>
        <Button variant="secondary" onClick={handleClear}>
          Clear
        </Button>
      </Flex>
      <div className="text-sm text-foreground-400">
        Selected: {formatDate(date)}
      </div>
      <DatePicker value={date} onChange={setDate} />
    </Flex>
  )
}
 

date/04-range

A single date picker in range mode: click once to set the start date, then click an end date to complete the range. Hovering after the start previews the range before it's committed. Useful for booking, event scheduling, or filtering data by date range.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
import type { DateRangeValue } from 'ui-lab-components/date'
import { Flex } from 'ui-lab-components/flex'
 
export default function Example() {
  const [range, setRange] = React.useState<DateRangeValue>({ start: null, end: null })
 
  const formatDate = (date: globalThis.Date | null) => {
    if (!date) return 'Select date'
    return date.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric'
    })
  }
 
  const daysDifference = range.start && range.end
    ? Math.floor((range.end.getTime() - range.start.getTime()) / (1000 * 60 * 60 * 24)) + 1
    : null
 
  return (
    <Flex direction="column" w={60} gap="lg">
      <DatePicker mode="range" value={range} onChange={setRange} />
 
      <div className="p-3 bg-background-300 rounded-md">
        <div className="text-sm text-foreground-400 mb-1">
          Selected Range
        </div>
        <div className="text-foreground-400 font-medium">
          {formatDate(range.start)} → {formatDate(range.end)}
        </div>
        {daysDifference !== null && (
          <div className="text-sm text-foreground-400 mt-2">
            Duration: {daysDifference} {daysDifference === 1 ? 'day' : 'days'}
          </div>
        )}
      </div>
    </Flex>
  )
}
 

date/05-date-input

Date.Input, the recommended way to compose a full date field: type into the month/day/year segments, or open the calendar from the trailing action and pick a day. Typing complete segments and picking from the calendar stay in sync, and selecting a day closes the popover.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
import { Flex } from 'ui-lab-components/flex'
 
export default function Example() {
  const [date, setDate] = React.useState<globalThis.Date | null>(null)
 
  const formatDate = (value: globalThis.Date | null) => {
    if (!value) return 'No date yet'
    return value.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric'
    })
  }
 
  return (
    <Flex direction="column" gap="lg">
      <DatePicker.Input value={date} onChange={setDate} label="Due date" />
 
      <div className="p-3 bg-background-300 rounded-md">
        <div className="text-sm text-foreground-400 mb-1">
          Selected Date
        </div>
        <div className="text-foreground-400 font-medium">
          {formatDate(date)}
        </div>
      </div>
    </Flex>
  )
}
 

date/06-date-input-range

Date.Input in range mode: one field holding start and end segments, driving a single range calendar. The popover stays open across the start and end picks and closes once the range is complete.

Loading interactive preview
import React from 'react'
import type { ReactNode } from 'react'
import { Date as DatePicker } from 'ui-lab-components/date'
import type { DateRangeValue } from 'ui-lab-components/date'
import { Flex } from 'ui-lab-components/flex'
 
export default function Example() {
  const [range, setRange] = React.useState<DateRangeValue>({ start: null, end: null })
 
  const formatDate = (value: globalThis.Date | null) => {
    if (!value) return 'Select date'
    return value.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric'
    })
  }
 
  const nights = range.start && range.end
    ? Math.floor((range.end.getTime() - range.start.getTime()) / (1000 * 60 * 60 * 24))
    : null
 
  return (
    <Flex direction="column" gap="lg">
      <DatePicker.Input mode="range" value={range} onChange={setRange} label="Stay" />
 
      <div className="p-3 bg-background-300 rounded-md">
        <div className="text-sm text-foreground-400 mb-1">
          Selected Range
        </div>
        <div className="text-foreground-400 font-medium">
          {formatDate(range.start)} → {formatDate(range.end)}
        </div>
        {nights !== null && (
          <div className="text-sm text-foreground-400 mt-2">
            Duration: {nights} {nights === 1 ? 'night' : 'nights'}
          </div>
        )}
      </div>
    </Flex>
  )
}