DatePicker
A date picker is two inputs in one: a segmented field that can be typed into, and a calendar for picking. Neither is a fallback for the other — typing is faster for a date you know, and the calendar is faster for one you are choosing.
import { DatePicker, DatePickerGroup, DatePickerInput } from "ropav";The field and the calendar
DatePickerInput renders one DatePickerSegment per part of the date, in the order the reader's locale writes them. DatePickerPopover holds a Calendar, which is a component in its own right.
date-picker-basic.vue
<script setup lang="ts">
import {
Calendar,
CalendarCell,
CalendarGrid,
CalendarGridBody,
CalendarGridHeader,
CalendarHeader,
CalendarHeaderCell,
CalendarNavButton,
DatePicker,
DatePickerGroup,
DatePickerInput,
DatePickerPopover,
DatePickerSegment,
DatePickerSuffix,
DatePickerTrigger,
DatePickerTriggerIndicator,
Label,
} from "ropav";
</script>
<template>
<div class="field">
<DatePicker name="date">
<Label>Date</Label>
<DatePickerGroup full-width>
<DatePickerInput>
<template #default="{ segment }">
<DatePickerSegment :segment />
</template>
</DatePickerInput>
<DatePickerSuffix>
<DatePickerTrigger>
<DatePickerTriggerIndicator />
</DatePickerTrigger>
</DatePickerSuffix>
</DatePickerGroup>
<DatePickerPopover>
<Calendar aria-label="Selected date">
<CalendarHeader>
<CalendarNavButton slot="previous" />
<CalendarNavButton slot="next" />
</CalendarHeader>
<CalendarGrid>
<CalendarGridHeader>
<template #default="{ day }">
<CalendarHeaderCell>{{ day }}</CalendarHeaderCell>
</template>
</CalendarGridHeader>
<CalendarGridBody>
<template #default="{ date }">
<CalendarCell :date />
</template>
</CalendarGridBody>
</CalendarGrid>
</Calendar>
</DatePickerPopover>
</DatePicker>
</div>
</template>
<style scoped>
/* The control renders two roots, so a scoped rule has nothing in it to attach to. The demo
owns this box instead, and a column stretches the control across it. */
.field {
display: flex;
flex-direction: column;
width: calc(var(--rp-spacing) * 72);
}
</style>There is a lot of markup here, and that is the trade: every part is yours to place, so a picker with a year jump, a two-month calendar or a footer is composition rather than a prop.
Calendars other than Gregorian
A date picker builds a Gregorian calendar until it is told otherwise, which keeps the other systems out of the bundle for the projects that never need them. Passing a calendar system is what pulls it in — see Calendar systems.
Accessibility
- The segments are one control: arrow keys change the segment under the cursor, left and right move between them, and typing digits fills them in.
- The value is announced as a whole date, not as three numbers.
- The popover traps focus while it is open and returns it to the field on close.
API
DatePicker
| Prop | Type | Default | Description |
|---|---|---|---|
ariaDescribedby | string | — | |
ariaLabel | string | — | |
ariaLabelledby | string | — | |
autoComplete | string | — | What the browser may offer to autofill. |
autoFocus | boolean | — | Whether the first segment takes focus as the picker appears. |
createCalendar | ((identifier: CalendarIdentifier) => Calendar) | — | Builds the calendar system for an identifier. Injectable so a build can ship fewer of them. |
defaultOpen | boolean | — | |
defaultValue | DateValue | null | — | The date the picker starts with while it owns its own value. |
firstDayOfWeek | "fri" | "mon" | "sat" | "sun" | "thu" | "tue" | "wed" | — | The day a week starts on in the calendar, when it should not follow the locale. |
form | string | — | Id of the form the value belongs to, when it is not an ancestor. |
granularity | "day" | "hour" | "minute" | "second" | — | The smallest part of a date the picker shows. Taken from the value when unset. |
hideTimeZone | boolean | — | Whether the time zone abbreviation is hidden. |
hourCycle | 12 | 24 | — | Whether to show a 12 or 24 hour clock. Taken from the locale when unset. |
id | string | — | Id for the group around the segments and the trigger, which is what a label points at. |
isDateUnavailable | ((date: DateValue) => boolean) | — | Rules a date out even though it is inside the range. A prop rather than an emit: the picker calls it while validating and while drawing the calendar, and an emit has no answer to give back. |
isDisabled | boolean | — | |
isInvalid | boolean | — | Whether the picker reads as invalid regardless of what it holds. |
isOpen | boolean | — | Whether the popover is open. Set this and the caller owns it. |
isReadOnly | boolean | — | |
isRequired | boolean | — | |
locale | string | — | Overrides the locale in force, for a picker that must not follow its surroundings. |
maxValue | DateValue | null | — | |
minValue | DateValue | null | — | |
name | string | — | Name the value is submitted under. |
pageBehavior | "single" | "visible" | "visible" | How much the calendar moves by when it pages. |
placeholderValue | DateValue | null | — | A date whose shape the empty segments follow, which is also where the calendar opens. Defaults to today. |
shouldCloseOnSelect | boolean | (() => boolean) | true | Whether picking a date closes the popover. |
shouldForceLeadingZeros | boolean | — | Whether numbers are always padded to two digits. Taken from the locale when unset. |
validate | ((value: DateValue | null) => string | true | string[] | null | undefined) | — | Extra rule the value has to satisfy, beyond the range. |
validationBehavior | "aria" | "native" | "native" | Whether errors go through the browser or through ARIA alone. |
value | DateValue | null | — | The date the picker shows. Set this and the caller owns the value. |
The default slot receives:
| Slot prop | Type |
|---|---|
isDisabled | boolean |
isInvalid | boolean |
isOpen | boolean |
isReadOnly | boolean |
isRequired | boolean |
| Event | Payload |
|---|---|
change | DateValue | null |
focusChange | boolean |
openChange | boolean |
update:isOpen | boolean |
update:value | DateValue | null |
DatePickerPopover
| Prop | Type | Default | Description |
|---|---|---|---|
containerPadding | number | — | Distance kept between the popover and the edge of the viewport. |
crossOffset | number | — | Distance along the cross axis. |
isKeyboardDismissDisabled | boolean | false | |
offset | number | — | Distance along the main axis, between the popover and the group. |
placement | "bottom" | "bottom end" | "bottom left" | "bottom right" | "bottom start" | "end" | "end bottom" | "end top" | "left" | "left bottom" | "left top" | "right" | "right bottom" | "right top" | "start" | "start bottom" | "start top" | "top" | "top end" | "top left" | "top right" | "top start" | "bottom" | Where the popover sits relative to the group. |
shouldFlip | boolean | — | Whether the popover may flip to the other side when it does not fit. |
Slots: default.
DatePickerTrigger
Slots: default.
DatePickerTriggerIndicator
Slots: default.