DatePicker
A date picker supporting ten types — date, daterange, month, monthrange, year, yearrange, datetime, datetimerange, week, and quarter — with keyboard operation and Intl.DateTimeFormat formatting. The trigger is an input: you can type a date directly (committed on blur or Enter; invalid input reverts).
Basic Selection
Basic usage (type=date)
Click the input to open the panel and click a date to select; or type 2026-08-15 / 2026/8/15 and press Enter (or blur) to commit.
Date Range
Date range (type=daterange)
A double-month grid: pick the start first, then the end; submits a JSON array ["start","end"]. Hovering previews the range. Every endpoint pick emits oas-calendar-change (see Events). Range selection defaults to a double-month grid (left + right month linked); in the mobile form (narrow-screen drawer panel) the two month grids stack into a single column — desktop containers do not auto-collapse to single panel.
Month & Month Range
Month (type=month)
Month range (type=monthrange)
monthrange value is a JSON array ["yyyy-MM","yyyy-MM"]; two year panels for start/end month picking.
Year & Year Range
Year (type=year)
Year range (type=yearrange)
The year panel flips in 12-year pages; value is yyyy, yearrange a JSON array ["yyyy","yyyy"].
Week & Quarter
Week (type=week, ISO value yyyy-Wnn)
Quarter (type=quarter, value yyyy-Qn)
week selects the whole ISO week of the clicked day (full-row highlight with week numbers); quarter renders a four-cell quarter grid.
Datetime & Datetime Range
Datetime (type=datetime)
Datetime range (type=datetimerange)
datetime submits after picking date + time and clicking "OK"; datetimerange shows dual month grids plus start/end time columns and submits a JSON array ["yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mm:ss"].
Range Separator
separator: custom range separator
separator customizes the separator between the start/end values inside the trigger for range types (default ~); display only — the value contract is unchanged.
Range Default Time
default-time (datetimerange start/end default time)
default-time (["start time","end time"], or a single "HH:mm:ss" applied to both ends) provides default times for the datetimerange start/end time columns: when the value is empty or an endpoint lacks a time part it is filled in automatically — ["00:00:00","23:59:59"] is the common full-day convention, so picking both dates and clicking "OK" yields a whole-day range; shortcuts fill times the same way. Without the attribute the built-in convention is 00:00:00 / 23:59:59; endpoints that already carry a time are followed, not overridden.
Trigger Icon Slots
prefix-icon / suffix-icon slots
slot="prefix-icon" / slot="suffix-icon" distribute leading/trailing icons inside the trigger (decorative: clicks pass through to the trigger and open the panel). The trigger text makes room automatically; the clearable clear button shares the suffix zone — while it is visible the suffix icon yields (hidden) and restores after clearing.
Disabled Range & Navigation Bounds
min / max limits
Out-of-range dates are not selectable, and navigation buttons gray out at the min/max boundary.
Shortcuts
Shortcuts (property)
shortcuts (property, { label, value } or { label, getValue() }) applies on click, emits oas-change, and closes the panel. Built-in defaults exist for date / datetime / month / week / year and all range types (labels via locale).
Sidebar shortcuts (shortcuts-position=left)
With many presets, use shortcuts-position="left" to move the shortcut bar to a vertical column on the panel's left side.
Timezone (timezone)
timezone anchor: New York vs local
timezone accepts an IANA zone name (e.g. America/New_York) or UTC; an omitted/invalid value falls back to the host local zone. It only changes what counts as "today" and the defaults derived from it — the "today" highlight, the built-in Today shortcut, and default-time derivation for datetime / datetimerange all read the wall clock of the configured zone; the value contract (yyyy-MM-dd / ISO wall-clock strings) is unchanged. Open the left panel to see the Today ring on New York's day and the right one on the local day; the reference line below shows both zones' current date.
Disabled Dates
Disable past dates (disabled-date)
disabledDate (property, (date: Date) => boolean) grays out matching dates (clicks and keyboard skip them); stacks with min/max.
Multiple
Multiple selection
With multiple, clicks accumulate/deselect while the panel stays open; value is a JSON array.
Custom Format
Custom format
The format supports yyyy/MM/dd/HH/mm/ss tokens (week/quarter use their fixed value format).
Panel Features
Unlinked panels (unlink-panels)
Range panels navigate in lockstep by default; unlink-panels lets both months flip independently.
Empty-value initial month (default-value)
When the value is empty the panel opens on the current month; with default-value it anchors to the given date's month (recalling a birthday month, for example).
Month/year caption dropdowns (caption-layout=dropdown, date-of-birth quick jumps)
caption-layout="dropdown" replaces the day-panel caption with month / year dropdowns (date-of-birth style far-year navigation without paging month by month): the year dropdown covers "current year −100 … current year +10" by default (shrinks to the boundary years when min / max are set; whole months outside the range are disabled), and picking an option navigates the panel — navigation only, the value is untouched; dates are still committed by clicking a day, a shortcut preset, or typing. The month/year caption order follows the locale (year first for zh); it applies to type=date / datetime / week, while the other panel families (month/year/quarter/range grids are block pickers already) keep the caption button. Keyboard-accessible (native selects); focus stays on the dropdown after a jump for consecutive navigation.
Week numbers & first day of week
show-week-number adds an ISO week-number column (built-in for type=week); first-day-of-week (0-6, 0=Sunday) overrides the week start, which otherwise follows the locale.
Cell Rendering
Calendar marks (oas-cell-render / template[slot=cell])
Same dual channel as oas-calendar: template[slot="cell"] clones into each day cell ([data-cell-date] binds the day number), and every rebuild emits oas-cell-render with detail: { date, element } (listeners must be idempotent).
Form States
Sizes
Status & clearable
status=error also sets aria-invalid; clearable shows a clear button when a value exists (emits oas-clear + oas-change with an empty value).
Readonly
The panel can still be opened and browsed (keyboard navigation works), but no interaction commits.
Controlled & Events
Controlled + oas-change event
Controlled open (open + oas-open-change)
With the open attribute present the picker is controlled: gestures only emit oas-open-change; the host decides by adding/removing the attribute.
Range partial selection (oas-calendar-change)
Range types emit oas-calendar-change (detail.value is [start, end|null]) on every endpoint pick.
Disabled
Disabled
Floating Positioning (placement)
Right-edge trigger (default bottom-start, auto flip)
Right-edge wide panel (daterange, auto right-align flip)
Right-edge wide panel (range right-aligns)
Explicit placement (top-end)
placement supports 12 directions (top/bottom/left/right × -start/-end, default bottom-start) with auto right-align flipping near the viewport edge, upward flipping, and viewport clamping.
Picker vs Calendar
Use oas-date-picker (this component) for popover selection; use oas-calendar for always-visible inline panels (same family capabilities: mode=year, week numbers, cell rendering).
Mobile form (bottom sheet)
On touch screens (coarse pointer) or narrow viewports (<768px), the panel is automatically hosted by an oas-bottom-sheet bottom sheet: rises from the viewport bottom + backdrop + drag handle swipe-down to close (backdrop click / Esc also close), with bottom safe-area inset; the desktop form keeps the original floating dropdown. Dual-month range panels shrink on narrow screens to avoid horizontal overflow; inside the sheet, day cells are lifted to a 44px touch target (--oas-touch-target-min) so they are easy to hit on touch screens.
required
required (native validation chain)
required drives the native validation chain (form-associated): when unfilled, checkValidity() returns false (valueMissing) and native form submission is blocked; it recovers to :valid once filled.
Programmatic read/write of the current value goes through the public value property: el.value reads the current value with getFormValue() semantics (single mode: the raw value attribute; multiple/range modes: an array of strings, same shape as the oas-change detail); el.value = x writes the controlled value attribute and immediately syncs the trigger (arrays for range/multiple are JSON-serialized automatically, empty values remove the attribute), and the open panel's selection re-anchors accordingly. No events are dispatched.
API
oas-date-picker
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
caption-layout | Panel caption style: buttons (default, caption button toggles the month panel) / dropdown (month/year dropdowns for quick jumps, date-of-birth style far-year navigation; applies to day-grid single-value panels only — date/datetime/week; picking navigates without changing the value) | string | — |
clearable | Clearable: shows a clear button when a value exists; emits oas-clear + oas-change (empty value) | boolean | — |
default-time | Default start/end times for datetimerange (JSON array or single value); auto-filled when the value lacks a time part | string | — |
default-value | Panel anchor month when the value is empty (the value takes precedence when present) | string | — |
disabled | Disabled | boolean | — |
first-day-of-week | Week-start override (0=Sunday … 6=Saturday); defaults to the locale | string | — |
format | Display format tokens (yyyy/MM/dd/HH/mm/ss; week/quarter use their fixed value format) | string | — |
max | Selectable range (ISO date); navigation buttons gray out at the boundary | string | — |
min | Selectable range (ISO date); navigation buttons gray out at the boundary | string | — |
multiple | Multiple selection (only type=date), value is a JSON array; the typing channel is read-only in this mode | boolean | — |
name | Form field name (key for native FormData submission; range mode derives name-start / name-end entries; the browser skips submission when name is absent) | string | — |
open | Controlled open: present = open, removed = closed; gestures only emit oas-open-change for the host to write back; in the mobile form (touch / viewport <768px) the open panel is hosted by an oas-bottom-sheet bottom sheet (swipe-down/backdrop/Esc to close); desktop keeps the floating dropdown | — | — |
placeholder | Placeholder text | — | — |
placement | Popup placement, 12 directions: top/bottom/left/right × -start/-end (default bottom-start); auto right-aligns near the viewport right edge, flips upward when space below is insufficient, and clamps into the viewport | string | bottom-start |
readonly | Readonly: the panel can be opened and browsed (cells keyboard-navigable), but no interaction commits | boolean | — |
required | Required marker (drives the native valueMissing validation chain; not passed through to the inner control) | boolean | — |
separator | Custom separator between start/end values in the trigger for range types (display only) | string | — |
shortcuts-position | Shortcut placement: bottom (default, horizontal on top) / left (vertical sidebar) | string | bottom |
show-week-number | Show an ISO week-number column (built-in for type=week) | boolean | — |
size | Size: small / medium / large (reads the nearest config-provider injection) | string | medium |
status | Validation status: success / warning / error (error also sets aria-invalid) | string | — |
timezone | Timezone anchor: an IANA zone name (e.g. America/New_York) or UTC; omitted/invalid falls back to the host local zone. Today highlight, shortcuts and default-time derivation read this zone's wall clock; the value contract is unchanged | string | — |
type | Type: date / daterange / month / monthrange / year / yearrange / datetime / datetimerange / week / quarter | string | date |
unlink-panels | Range months flip independently (linked by default) | boolean | — |
value | Current value: yyyy-MM-dd / yyyy-MM / yyyy / yyyy-Wnn / yyyy-Qn / yyyy-MM-ddTHH:mm:ss / JSON range array | string | string[] | null | — |
Property (JS property; see each row for attribute reflection)
| Property | Description | Type | Default |
|---|---|---|---|
disabledDate | Disabled-date predicate (property function channel, (date) => boolean) | ((d: Date) => boolean) | null | — |
shortcuts | Shortcut presets (property channel, [{ label, value/getValue }]) | ShortcutItem[] | null | — |
value | Current value: a date string for single; a string array for range / multiple | string | string[] | null | — |
Events
| Event | Description |
|---|---|
oas-blur | The component as a whole loses focus (internal moves do not fire) |
oas-calendar-change | Emitted on every range endpoint pick, detail: { value: [start, end|null] } |
oas-cell-render | Emitted per day cell on rebuild, detail: { date, element } (listeners must be idempotent) |
oas-change | Value change, detail: { value } (string array for ranges and multiple) |
oas-clear | Clear, detail: { value } is the previous value |
oas-confirm | Emitted when datetime/datetimerange submits via the confirm button (alongside oas-change), detail: { value } |
oas-focus | The component as a whole gains focus |
oas-open-change | Open state change, detail: { open } (both controlled and uncontrolled) |
Slots
| Name | Description |
|---|---|
prefix-icon | Leading icon inside the trigger (decorative; clicks pass through) |
suffix-icon | Trailing icon inside the trigger (yields while the clear button is visible) |
template[slot="cell"] | template[slot="cell"] is cloned into each day cell; [data-cell-date] binds the day number (dual channel with oas-cell-render) |
CSS Variables
| CSS Variable | Default |
|---|---|
--oas-glass-blur | none |
--oas-glass-ring | transparent |
Property (shortcut presets)
shortcuts: shortcut presets
Keyboard: Enter / ↓ to open; arrows plus Home/End/PageUp/PageDown (Shift for years) to move; Enter to select; Esc to close.