Kumo Svelte
  • Home
  • Installation
  • Colors
  • Accessibility
  • Changelog
  • Autocomplete
  • Badge
  • Banner
  • Breadcrumbs
  • Button
  • Checkbox
  • Clipboard Text
  • Cloudflare Logo
  • CodeHighlighted
  • Collapsible
  • Combobox
  • Command Palette
  • Date Picker
  • Dialog
  • Dropdown
  • Empty
  • Flow
  • Grid
  • Input
  • InputArea
  • InputGroup
  • Label
  • Layer Card
  • Link
  • Loader
  • MenuBar
  • Meter
  • Pagination
  • Popover
  • Radio
  • Select
  • Sensitive Input
  • Sidebar
  • Skeleton Line
  • Switch
  • Table
  • Table of Contents
  • Tabs
  • Text
  • Toast
  • Toolbar
  • Tooltip
  • Charts
  • Colors
  • Timeseries
  • Maps
  • Sankey
  • Custom Chart
  • Page Header
  • Resource List
  • Delete Resource
DatePicker
kumo-svelte

DatePicker

A date selection calendar supporting single, multiple, and range selection modes.

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1

Selected: None

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  let date = $state<DateValue | undefined>();

  function formatDate(value: DateValue | undefined) {
    return value ? value.toDate(getLocalTimeZone()).toLocaleDateString() : "None";
  }
</script>

<div class="flex flex-col gap-4">
  <DatePicker mode="single" bind:value={date} />
  <p class="text-sm text-kumo-subtle">Selected: {formatDate(date)}</p>
</div>

Import

import { DatePicker, type DatePickerValue } from "kumo-svelte/components/date-picker";

Usage

DatePicker supports three selection modes: single, multiple, and range. The Svelte component uses DateValue from @internationalized/date; range values use Bits UI’s { start, end } shape.

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  let date = $state<DateValue | undefined>();
</script>

<DatePicker mode="single" bind:value={date} />

Examples

Single Date Selection

Select a single date. The most common use case for date pickers.

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1

Selected: None

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  let date = $state<DateValue | undefined>();

  function formatDate(value: DateValue | undefined) {
    return value ? value.toDate(getLocalTimeZone()).toLocaleDateString() : "None";
  }
</script>

<div class="flex flex-col gap-4">
  <DatePicker mode="single" bind:value={date} />
  <p class="text-sm text-kumo-subtle">Selected: {formatDate(date)}</p>
</div>

Multiple Date Selection

Select multiple individual dates. Use maxDays to limit the number of selections.

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1

Selected: 0 date(s)

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  let dates = $state<DateValue[] | undefined>();
</script>

<div class="flex flex-col gap-4">
  <DatePicker mode="multiple" bind:value={dates} maxDays={5} />
  <p class="text-sm text-kumo-subtle">Selected: {dates?.length ?? 0} date(s)</p>
</div>

Date Range Selection

Select a continuous range of dates. Use numberOfMonths={2} for a side-by-side view.

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
August 2026
SuMoTuWeThFrSa
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5

Range: None

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  type DateRangeValue = { start: DateValue | undefined; end: DateValue | undefined };

  let range = $state<DateRangeValue | undefined>();

  function formatRange(value: DateRangeValue | undefined) {
    if (!value?.start) return "None";
    const start = value.start.toDate(getLocalTimeZone()).toLocaleDateString();
    const end = value.end?.toDate(getLocalTimeZone()).toLocaleDateString() ?? "…";
    return `${start} – ${end}`;
  }
</script>

<div class="flex flex-col gap-4">
  <DatePicker mode="range" bind:value={range} numberOfMonths={2} />
  <p class="text-sm text-kumo-subtle">Range: {formatRange(range)}</p>
</div>

Range with Min/Max Constraints

Constrain the range length using minDays and maxDays props (in days/nights).

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
Select 3-7 nights
<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  type DateRangeValue = { start: DateValue | undefined; end: DateValue | undefined };

  let range = $state<DateRangeValue | undefined>();
</script>

{#snippet footer()}
  <span class="text-xs text-kumo-subtle">Select 3-7 nights</span>
{/snippet}

<DatePicker mode="range" bind:value={range} minDays={3} maxDays={7} {footer} />

With Popover

Compose with the Popover component to create a dropdown date picker.

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { Button } from "kumo-svelte/components/button";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  import * as Popover from "kumo-svelte/components/popover";
  import CalendarDotsIcon from "phosphor-svelte/lib/CalendarDotsIcon";

  let date = $state<DateValue | undefined>();
  function formatDate(value: DateValue | undefined) {
    return value ? value.toDate(getLocalTimeZone()).toLocaleDateString() : "Pick a date";
  }
</script>

<Popover.Root>
  <Popover.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="outline" icon={CalendarDotsIcon}>{formatDate(date)}</Button>
    {/snippet}
  </Popover.Trigger>
  <Popover.Content class="p-3">
    <DatePicker mode="single" bind:value={date} />
  </Popover.Content>
</Popover.Root>

Date Range with Popover

A date range picker in a popover with two months displayed.

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { Button } from "kumo-svelte/components/button";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  import * as Popover from "kumo-svelte/components/popover";
  import CalendarDotsIcon from "phosphor-svelte/lib/CalendarDotsIcon";

  type DateRangeValue = { start: DateValue | undefined; end: DateValue | undefined };

  let range = $state<DateRangeValue | undefined>();

  function formatRange(value: DateRangeValue | undefined) {
    if (!value?.start) return "Select dates";
    const start = value.start.toDate(getLocalTimeZone()).toLocaleDateString();
    const end = value.end?.toDate(getLocalTimeZone()).toLocaleDateString();
    return end ? `${start} – ${end}` : start;
  }
</script>

<Popover.Root>
  <Popover.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="outline" icon={CalendarDotsIcon}>{formatRange(range)}</Button>
    {/snippet}
  </Popover.Trigger>
  <Popover.Content class="p-3">
    <DatePicker mode="range" bind:value={range} numberOfMonths={2} />
  </Popover.Content>
</Popover.Root>

Date Range with Presets

Combine the date picker with preset options for quick selection.

<script lang="ts">
  import type { CalendarDate, DateValue } from "@internationalized/date";
  import { getLocalTimeZone, today } from "@internationalized/date";
  import { Button } from "kumo-svelte/components/button";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  import * as Popover from "kumo-svelte/components/popover";
  import CalendarDotsIcon from "phosphor-svelte/lib/CalendarDotsIcon";

  type DateRangeValue = { start: DateValue | undefined; end: DateValue | undefined };
  type PresetRange = { start: CalendarDate; end: CalendarDate };

  const timeZone = getLocalTimeZone();
  const now = today(timeZone);
  const presets: Array<{ label: string; range: PresetRange }> = [
    { label: "Today", range: { start: now, end: now } },
    { label: "Last 7 days", range: { start: now.subtract({ days: 6 }), end: now } },
    { label: "Last 30 days", range: { start: now.subtract({ days: 29 }), end: now } },
    { label: "Last 90 days", range: { start: now.subtract({ days: 89 }), end: now } },
    { label: "This month", range: { start: now.set({ day: 1 }), end: now } },
    {
      label: "Last month",
      range: {
        start: now.subtract({ months: 1 }).set({ day: 1 }),
        end: now.set({ day: 1 }).subtract({ days: 1 }),
      },
    },
  ];

  let range = $state<DateRangeValue | undefined>();
  let placeholder = $state(now);

  function formatRange(value: DateRangeValue | undefined) {
    if (!value?.start) return "Select dates";
    const start = value.start.toDate(timeZone).toLocaleDateString();
    const end = value.end?.toDate(timeZone).toLocaleDateString();
    return end ? `${start} – ${end}` : start;
  }

  function selectPreset(preset: { range: PresetRange }) {
    range = preset.range;
    placeholder = preset.range.start;
  }

  function isPresetActive(preset: { range: PresetRange }) {
    return range?.start?.compare(preset.range.start!) === 0 && range?.end?.compare(preset.range.end!) === 0;
  }
</script>

<Popover.Root>
  <Popover.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="outline" icon={CalendarDotsIcon}>{formatRange(range)}</Button>
    {/snippet}
  </Popover.Trigger>
  <Popover.Content class="p-0">
    <div class="flex">
      <div class="flex flex-col gap-1 border-r border-kumo-hairline p-2 text-sm">
        {#each presets as preset}
          <button
            type="button"
            onclick={() => selectPreset(preset)}
            class={[
              "whitespace-nowrap rounded-md px-3 py-1.5 text-left",
              isPresetActive(preset)
                ? "bg-kumo-bg-inverse text-kumo-text-inverse"
                : "text-kumo-subtle hover:bg-kumo-control",
            ]}
          >
            {preset.label}
          </button>
        {/each}
      </div>
      <div class="p-3">
        <DatePicker mode="range" bind:value={range} bind:placeholder numberOfMonths={2} />
      </div>
    </div>
  </Popover.Content>
</Popover.Root>

Disabled Dates with Usage Limits

Use isDateDisabled or isDateUnavailable to make certain dates unselectable, and footer to display usage information.

July 2026
SuMoTuWeThFrSa
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8

0/5 days selected. Grayed dates are unavailable.

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone, today } from "@internationalized/date";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  const timeZone = getLocalTimeZone();
  const now = today(timeZone);
  const maxDays = 5;
  const unavailableDates = [
    now.set({ day: 5 }),
    now.set({ day: 12 }),
    now.set({ day: 18 }),
    now.set({ day: 25 }),
  ];

  let dates = $state<DateValue[] | undefined>();
  let selectedCount = $derived(dates?.length ?? 0);

  function isUnavailable(value: DateValue) {
    return unavailableDates.some((date) => date.compare(value) === 0);
  }
</script>

{#snippet footer()}
  <p class="w-full pt-2 text-xs text-kumo-subtle">
    {selectedCount}/{maxDays} days selected. Grayed dates are unavailable.
  </p>
{/snippet}

<DatePicker
  mode="multiple"
  bind:value={dates}
  maxDays={maxDays}
  isDateDisabled={isUnavailable}
  fixedWeeks
  {footer}
/>

Full Popover Example

Here’s a complete example showing how to compose DatePicker with Popover:

<script lang="ts">
  import type { DateValue } from "@internationalized/date";
  import { getLocalTimeZone } from "@internationalized/date";
  import { Button } from "kumo-svelte/components/button";
  import { DatePicker } from "kumo-svelte/components/date-picker";
  import * as Popover from "kumo-svelte/components/popover";
  import CalendarDotsIcon from "phosphor-svelte/lib/CalendarDotsIcon";

  let date = $state<DateValue | undefined>();
  function label(value: DateValue | undefined) {
    return value ? value.toDate(getLocalTimeZone()).toLocaleDateString() : "Pick a date";
  }
</script>

<Popover.Root>
  <Popover.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="outline" icon={CalendarDotsIcon}>{label(date)}</Button>
    {/snippet}
  </Popover.Trigger>
  <Popover.Content class="p-3">
    <DatePicker mode="single" bind:value={date} />
  </Popover.Content>
</Popover.Root>

API Reference

DatePicker

PropTypeDefault
calendarLabelstring—
childrenSnippet<[DatePickerSnippetProps]>—
classstring—
disableDaysOutsideMonthbooleanfalse
disabledbooleanfalse
excludeDisabledbooleanfalse
fixedWeeksbooleanfalse
footerSnippet—
initialFocusboolean—
isDateDisabledDateMatcher—
isDateUnavailableDateMatcher—
localestring—
maxDaysnumber—
maxValueDateValue—
minDaysnumber—
minValueDateValue—
modeDatePickerMode"single"
monthFormatIntl.DateTimeFormatOptions["month"] | ((month: number) => string)—
numberOfMonthsnumber1
onEndValueChange(value: DateValue | undefined) => void—
onPlaceholderChange(value: DateValue) => void—
onStartValueChange(value: DateValue | undefined) => void—
onValueChange(value: DatePickerValue) => void—
pagedNavigationboolean—
placeholderDateValuebindable
preventDeselectboolean—
readonlybooleanfalse
refHTMLDivElement | nullnull
valueDatePickerValuebindable
weekStartsOnWeekStartsOn—
weekdayFormatIntl.DateTimeFormatOptions["weekday"]"short"
yearFormatIntl.DateTimeFormatOptions["year"] | ((year: number) => string)—

On this page

  • Import
  • Usage
  • Examples
    • Single Date Selection
    • Multiple Date Selection
    • Date Range Selection
    • Range with Min/Max Constraints
    • With Popover
    • Date Range with Popover
    • Date Range with Presets
    • Disabled Dates with Usage Limits
  • Full Popover Example
  • API Reference
    • DatePicker