Skip to main content
Urbicon UI

DatePicker

Date picker with calendar popup. Supports single date and date range selection, validation constraints, clearable input, and multiple visual variants.

Playground

Input Variant
Calendar Variant
<script lang="ts">
  import { DatePicker } from '@urbicon-ui/blocks';

  const label = 'Date';
  const placeholder = 'Select a date';
</script>

<DatePicker
  {label}
  {placeholder}
/>

01 Examples

Basic DatePicker

A labelled date field with a calendar popover. Clicking the input opens the calendar; the chosen date is written back formatted.
<script lang="ts">
  import { DatePicker } from '@urbicon-ui/blocks';

  let selectedDate = $state<Date | undefined>(undefined);
</script>

<div class="max-w-xs">
  <DatePicker
    bind:value={selectedDate}
    label="Geburtsdatum"
    placeholder="Datum auswaehlen"
    locale="de-DE"
    defaultMonth={2}
    defaultYear={2026}
  />

  {#if selectedDate}
    <div class="bg-surface-elevated border-border-subtle mt-3 rounded-lg border p-3">
      <p class="text-text-secondary text-sm">
        <span class="text-text-primary font-medium">Gewaehlt:</span>
        {selectedDate.toLocaleDateString('de-DE', {
          weekday: 'long',
          day: 'numeric',
          month: 'long',
          year: 'numeric'
        })}
      </p>
    </div>
  {/if}
</div>

DateRangePicker

Two clicks pick a start and an end date; the popover closes on its own once both are set. The shape bookings and report filters usually want.
<script lang="ts">
  import { DateRangePicker } from '@urbicon-ui/blocks';

  let value = $state<{ start: Date; end: Date } | undefined>(undefined);
</script>

<div class="max-w-xs">
  <DateRangePicker
    bind:value
    label="Reisezeitraum"
    placeholder="Zeitraum auswaehlen"
    locale="de-DE"
    defaultMonth={2}
    defaultYear={2026}
  />

  {#if value}
    <div class="bg-surface-elevated border-border-subtle mt-3 rounded-lg border p-3">
      <p class="text-text-secondary text-sm">
        <span class="text-text-primary font-medium">Von:</span>
        {value.start.toLocaleDateString('de-DE', {
          day: 'numeric',
          month: 'long',
          year: 'numeric'
        })}
      </p>
      <p class="text-text-secondary text-sm">
        <span class="text-text-primary font-medium">Bis:</span>
        {value.end.toLocaleDateString('de-DE', {
          day: 'numeric',
          month: 'long',
          year: 'numeric'
        })}
      </p>
      <p class="text-text-secondary mt-1 text-xs">
        {Math.ceil((value.end.getTime() - value.start.getTime()) / (1000 * 60 * 60 * 24)) + 1} Tage
      </p>
    </div>
  {/if}
</div>

With Constraints

minDate, maxDate, disabledDates and isDateDisabled together — only weekdays in March 2026 are selectable, weekends and holidays are locked out.
Nur Werktage im Maerz 2026, keine Feiertage.
<script lang="ts">
  import { DatePicker } from '@urbicon-ui/blocks';

  let selectedDate = $state<Date | undefined>(undefined);

  const minDate = new Date(2026, 2, 1);
  const maxDate = new Date(2026, 2, 31);

  /** Disable weekends */
  function isWeekend(date: Date): boolean {
    const day = date.getDay();
    return day === 0 || day === 6;
  }

  /** Specific holidays / blocked dates */
  const holidays = [new Date(2026, 2, 6), new Date(2026, 2, 20)];
</script>

<div class="max-w-xs">
  <DatePicker
    bind:value={selectedDate}
    label="Terminbuchung"
    placeholder="Werktag waehlen"
    helper="Nur Werktage im Maerz 2026, keine Feiertage."
    locale="de-DE"
    {minDate}
    {maxDate}
    isDateDisabled={isWeekend}
    disabledDates={holidays}
    defaultMonth={2}
    defaultYear={2026}
  />

  {#if selectedDate}
    <div class="bg-surface-elevated border-border-subtle mt-3 rounded-lg border p-3">
      <p class="text-text-secondary text-sm">
        <span class="text-text-primary font-medium">Termin:</span>
        {selectedDate.toLocaleDateString('de-DE', {
          weekday: 'long',
          day: 'numeric',
          month: 'long',
          year: 'numeric'
        })}
      </p>
    </div>
  {/if}
</div>

02 Accessibility

ARIA Roles

The trigger input carries aria-haspopup="dialog" and aria-expanded, so the popover's state is announced. The embedded calendar is a role="grid" with the full ARIA that implies.

Keyboard Navigation

Enter, Space or ArrowDown open the calendar, Escape closes it. Inside, the arrow keys move between days and weeks and PageUp/PageDown between months. Focus rings use focus-visible:, so they appear for the keyboard only.

Screen Reader Labels

The label reaches the screen reader through the input. Every day cell carries an aria-label with the full date ("Thursday, 12 March 2026"), and error and helper text are linked through aria-describedby.

Internationalisation

Formatting goes through the native Intl.DateTimeFormat with the configured locale, so weekday names, month names and the input format follow the language without further configuration.

03 API Reference

35 props
35 props
Prop
Type
Default
Description

04 Types

Local type definitions used by this component.

12 types
Name
Kind
Category
Used by
Description

05 Installation

Import

import { DatePicker, DateRangePicker } from '@urbicon-ui/blocks';
import type { DatePickerProps, DateRangePickerProps } from '@urbicon-ui/blocks';