| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
</script>
<template>
<DatePicker.Root v-model="value" name="target-date">
<DatePicker.Label>Target completion date</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Pick a date" />
<DatePicker.ClearTrigger aria-label="Clear date" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>Installation
Barrel
import {
DatePicker,
DatePickerRoot,
DatePickerRootProvider,
DatePickerLabel,
DatePickerControl,
DatePickerInput,
DatePickerTrigger,
DatePickerClearTrigger,
DatePickerContent,
DatePickerCalendar,
} from "@dicehub/kappa";Granular
import {
DatePicker,
DatePickerRoot,
DatePickerRootProvider,
DatePickerLabel,
DatePickerControl,
DatePickerInput,
DatePickerTrigger,
DatePickerClearTrigger,
DatePickerContent,
DatePickerCalendar,
} from "@dicehub/kappa/components/date-picker";Usage
A popover date picker needs a Control with an Input, aTrigger, and a Content holding the calendar. Values areDateValue objects from @internationalized/date; create them with CalendarDate, today(), or the exportedparseDate helper.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
</script>
<template>
<DatePicker.Root v-model="value" name="report-date">
<DatePicker.Label>Report date</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="YYYY-MM-DD" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>Composition
DatePicker.Root
├── DatePicker.Label
├── DatePicker.Control
│ ├── DatePicker.Input
│ ├── DatePicker.ClearTrigger
│ └── DatePicker.Trigger
└── DatePicker.Content
└── DatePicker.CalendarArk UI owns the calendar state machine, keyboard grid navigation, input parsing, visible-range logic, and the popover layer. Kappa owns the compound API, the composedCalendar part, default icons, dense geometry, states, and semantic tokens.
Rootowns selection, view, open state, locale, and constraints.Contentteleports the popover to the body; pass:teleport="false"to render in place.Calendarrenders the full day view: prev/next navigation, month titles, weekday header, and day cells. Multi-month and week numbers come fromRoot.- Table parts stay public for fully custom grids;
MonthSelectandYearSelecthandle long jumps.
See the Ark UI Date Pickerguide for the primitive behavior contract. Month and year grid views are available through the View, ViewControl, and table parts; the composedCalendar intentionally ships the day view only.
<script setup>
import {
DatePickerRoot,
DatePickerControl,
DatePickerInput,
DatePickerTrigger,
DatePickerContent,
DatePickerCalendar,
} from "@dicehub/kappa/components/date-picker";
</script>
<template>
<DatePickerRoot>
<DatePickerControl>
<DatePickerInput placeholder="Pick a date" />
<DatePickerTrigger aria-label="Open calendar" />
</DatePickerControl>
<DatePickerContent>
<DatePickerCalendar />
</DatePickerContent>
</DatePickerRoot>
</template>Examples
Inline
With inline, the calendar renders in place without a popover.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
</script>
<template>
<DatePicker.Root v-model="value" inline>
<DatePicker.Calendar />
</DatePicker.Root>
</template>Date Range
selectionMode="range" selects a start and an end. Two months keep the whole window visible while picking.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
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 | 1 | 2 | 3 | 4 | 5 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const samplingWindow = ref([]);
</script>
<template>
<DatePicker.Root v-model="samplingWindow" selection-mode="range" :num-of-months="2">
<DatePicker.Label>Sampling window</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Start date" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>Range Constraints
Limit the range length with isDateUnavailable. While a range start is pending — the controlled value holds one date — mark days too close or too far as unavailable. The pattern needs no wrapper state and keeps the Ark machine authoritative.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
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 | 1 | 2 | 3 | 4 | 5 |
<script setup>
import { today, getLocalTimeZone } from "@internationalized/date";
import { computed, ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const RANGE_MIN_DAYS = 2;
const RANGE_MAX_DAYS = 6;
const value = ref([today(getLocalTimeZone()).add({ days: 2 }), today(getLocalTimeZone()).add({ days: 5 })]);
// A pending range start: the controlled value holds exactly one date.
const pendingStart = computed(() => (value.value.length === 1 ? value.value[0] : undefined));
const outsideRangeLimits = (date) => {
if (!pendingStart.value) return false;
const days = Math.abs(
Math.round((date.toDate("UTC") - pendingStart.value.toDate("UTC")) / 86_400_000),
);
return days < RANGE_MIN_DAYS || days > RANGE_MAX_DAYS;
};
</script>
<template>
<DatePicker.Root
v-model="value"
selection-mode="range"
inline
:num-of-months="2"
:is-date-unavailable="outsideRangeLimits"
>
<DatePicker.Calendar />
</DatePicker.Root>
</template>Presets
PresetTrigger applies a prepared value in one click.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { CalendarDate, today, getLocalTimeZone } from "@internationalized/date";
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([today(getLocalTimeZone())]);
const inDays = (days) => today(getLocalTimeZone()).add({ days });
</script>
<template>
<DatePicker.Root v-model="value">
<DatePicker.Control>
<DatePicker.Input placeholder="Pick a date" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
<div class="presets">
<DatePicker.PresetTrigger :value="[inDays(0)]">Today</DatePicker.PresetTrigger>
<DatePicker.PresetTrigger :value="[inDays(7)]">In a week</DatePicker.PresetTrigger>
</div>
</DatePicker.Content>
</DatePicker.Root>
</template>Month and Year Selects
Native dropdowns for long jumps sit above the composed calendar.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
</script>
<template>
<DatePicker.Root v-model="value">
<DatePicker.Control>
<DatePicker.Input placeholder="Pick a date" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<div class="selects">
<DatePicker.MonthSelect aria-label="Month" />
<DatePicker.YearSelect aria-label="Year" />
</div>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>Min, Max, and Unavailable
min and max bound the selectable range;isDateUnavailable blocks specific days such as weekends.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 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 |
<script setup>
import { today, getLocalTimeZone } from "@internationalized/date";
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
const now = today(getLocalTimeZone());
const weekendUnavailable = (date) => {
const day = new Date(date.year, date.month - 1, date.day).getDay();
return day === 0 || day === 6;
};
</script>
<template>
<DatePicker.Root
v-model="value"
:min="now"
:max="now.add({ days: 30 })"
:is-date-unavailable="weekendUnavailable"
>
<DatePicker.Label>Submission date</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Next 30 days, weekdays" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>Week Numbers
showWeekNumbers adds the ISO week column to the day view.
| wk | S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|---|
| 39 | 27 | 28 | 29 | 30 | 1 | 2 | 3 |
| 40 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 41 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 42 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 43 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
<script setup>
import { DatePicker } from "@dicehub/kappa/components/date-picker";
</script>
<template>
<DatePicker.Root inline show-week-numbers>
<DatePicker.Calendar />
</DatePicker.Root>
</template>Locale
locale localizes month names, weekday order, and input formatting.
| M | D | M | D | F | S | S |
|---|---|---|---|---|---|---|
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 |
<script setup>
import { ref } from "vue";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
const value = ref([]);
</script>
<template>
<DatePicker.Root v-model="value" locale="de-DE" name="abgabetermin">
<DatePicker.Label>Abgabetermin</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Datum wählen" />
<DatePicker.Trigger aria-label="Kalender öffnen" />
</DatePicker.Control>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
</template>States
Disabled blocks the field; invalid marks the control and needs a text description.
Select a date before the review closes.
<script setup>
import { CalendarDate } from "@internationalized/date";
import { DatePicker } from "@dicehub/kappa/components/date-picker";
</script>
<template>
<DatePicker.Root disabled :default-value="[new CalendarDate(2026, 8, 1)]">
<DatePicker.Label>Disabled start date</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Unavailable" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
</DatePicker.Root>
<DatePicker.Root invalid>
<DatePicker.Label>Invalid milestone date</DatePicker.Label>
<DatePicker.Control>
<DatePicker.Input placeholder="Required" aria-describedby="milestone-error" />
<DatePicker.Trigger aria-label="Open calendar" />
</DatePicker.Control>
</DatePicker.Root>
<p id="milestone-error">Select a date before the review closes.</p>
</template>Accessibility
- The input is the primary control: type a date, or open the calendar with the trigger button.
- Arrow keys move the focused date; PageUp and PageDown move between months; Home and End move within a week.
- Every icon-only trigger needs an accessible name; the defaults document the pattern.
- The month title announces changes through a polite live region.
- Connect error text with
aria-describedbyon the input. - Unavailable dates stay focusable with an unavailable announcement, matching the primitive contract.
- Keyboard focus remains visible on every interactive element.
API Reference
DatePicker.Root
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | DateValue[] | - | Controlled selected dates; supports v-model. |
defaultValue | DateValue[] | [] | Initially selected dates for uncontrolled use. |
selectionMode | "single" | "multiple" | "range" | "single" | Selects one date, many dates, or a contiguous range. |
inline | boolean | false | Renders the calendar inline instead of inside a popover. |
numOfMonths | number | 1 | Renders this many adjacent month grids. |
startOfWeek | number | 0 | First weekday column; 0 is Sunday, 1 is Monday. |
showWeekNumbers | boolean | false | Adds the ISO week-number column to the day view. |
fixedWeeks | boolean | false | Always renders six weeks to keep the grid height stable. |
min | DateValue | - | Earliest selectable date. |
max | DateValue | - | Latest selectable date. |
isDateUnavailable | (date, locale) => boolean | - | Marks specific dates unavailable, such as weekends or booked days. |
locale | string | "en-US" | BCP 47 tag driving month, weekday, and input formatting. |
timeZone | string | "UTC" | Time zone used for date math and the today marker. |
format | (date, details) => string | localized | Overrides how the input renders the selected date. |
parse | (value, details) => DateValue | localized | Overrides how typed text parses back into a date. |
open / defaultOpen | boolean | false | Controlled or initial popover open state; pair open with update:open. |
openOnClick | boolean | false | Opens the calendar when the input is clicked. |
closeOnSelect | boolean | true | Closes the popover after a completed selection. |
positioning | PositioningOptions | bottom-start | Floating placement, gutter, and viewport handling for the popover. |
view / defaultView | "day" | "month" | "year" | "day" | Controlled or initial calendar view. |
disabled / readOnly / required / invalid | boolean | false | Standard form states, exposed as data attributes. |
name | string | - | Form field name for the hidden value. |
maxSelectedDates | number | - | Caps selections in multiple mode. |
createCalendar | (identifier) => Calendar | Gregorian | Enables non-Gregorian calendars such as Persian or Buddhist. |
Parts
| Part | Element | Description |
|---|---|---|
DatePicker.Label | label | Names the field and focuses the input on click. |
DatePicker.Control | div | Visual box grouping the input and icon triggers. |
DatePicker.Input | input | Editable date text; parses on commit. |
DatePicker.Trigger | button | Opens the popover; renders a calendar icon by default. |
DatePicker.ClearTrigger | button | Clears the selection; renders an × icon by default. |
DatePicker.Content | div | Teleported positioner and popover surface. |
DatePicker.Calendar | div | Composed day-view calendar: navigation, month titles, weekday header, and day grid. |
DatePicker.View / ViewControl / ViewTrigger | div | View switching primitives for day, month, and year grids. |
DatePicker.PrevTrigger / NextTrigger | button | Step the visible range; render chevron icons by default. |
DatePicker.Table … TableCellTrigger | table | Full grid anatomy for custom calendar layouts. |
DatePicker.WeekNumberCell / WeekNumberHeaderCell | td | ISO week-number column cells. |
DatePicker.ValueText | div | Formatted selected value outside the input. |
DatePicker.RangeText | div | Formatted visible range text. |
DatePicker.PresetTrigger | button | Applies a prepared value such as Today or Next week. |
DatePicker.MonthSelect / YearSelect | select | Native month and year jump dropdowns. |
DatePicker.Context | renderless | Exposes the date picker API to its slot. |
DatePicker.RootProvider | div | Root driven by an external useDatePicker machine. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | DateValue[] | Emitted on selection changes; drives v-model. |
valueChange | DatePickerValueChangeDetails | Ark UI detail with value and valueAsString. |
update:open | boolean | Emitted when the popover opens or closes; drives v-model:open. |
openChange | { open: boolean } | Ark UI detail for popover visibility. |
focusChange | DatePickerFocusChangeDetails | Emitted when the focused date moves. |
viewChange | DatePickerViewChangeDetails | Emitted when the calendar view changes. |
visibleRangeChange | DatePickerVisibleRangeChangeDetails | Emitted when the visible month range changes. |
Exports
| Export | Description |
|---|---|
DatePicker | Compound API exposing every named part. |
DatePickerRoot | Unaugmented root state machine host. |
DatePickerCalendar | Composed day-view calendar with navigation. |
DatePickerContent | Teleported popover surface. |
DatePickerProps | Public root props and Ark UI state contract. |
DatePickerEmits | Root event contract. |
DateValue | @internationalized/date value type used across the API. |
DatePickerValueChangeDetails | Payload for valueChange. |
parseDate | Ark UI helper parsing ISO strings into DateValue objects. |
useDatePicker | Ark UI machine hook for external state control. |
datePickerAnatomy | Ark UI part anatomy metadata. |