Skip to content

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 ​

AttributeDescriptionTypeDefault
caption-layoutPanel 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—
clearableClearable: shows a clear button when a value exists; emits oas-clear + oas-change (empty value)boolean—
default-timeDefault start/end times for datetimerange (JSON array or single value); auto-filled when the value lacks a time partstring—
default-valuePanel anchor month when the value is empty (the value takes precedence when present)string—
disabledDisabledboolean—
first-day-of-weekWeek-start override (0=Sunday … 6=Saturday); defaults to the localestring—
formatDisplay format tokens (yyyy/MM/dd/HH/mm/ss; week/quarter use their fixed value format)string—
maxSelectable range (ISO date); navigation buttons gray out at the boundarystring—
minSelectable range (ISO date); navigation buttons gray out at the boundarystring—
multipleMultiple selection (only type=date), value is a JSON array; the typing channel is read-only in this modeboolean—
nameForm field name (key for native FormData submission; range mode derives name-start / name-end entries; the browser skips submission when name is absent)string—
openControlled 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——
placeholderPlaceholder text——
placementPopup 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 viewportstringbottom-start
readonlyReadonly: the panel can be opened and browsed (cells keyboard-navigable), but no interaction commitsboolean—
requiredRequired marker (drives the native valueMissing validation chain; not passed through to the inner control)boolean—
separatorCustom separator between start/end values in the trigger for range types (display only)string—
shortcuts-positionShortcut placement: bottom (default, horizontal on top) / left (vertical sidebar)stringbottom
show-week-numberShow an ISO week-number column (built-in for type=week)boolean—
sizeSize: small / medium / large (reads the nearest config-provider injection)stringmedium
statusValidation status: success / warning / error (error also sets aria-invalid)string—
timezoneTimezone 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 unchangedstring—
typeType: date / daterange / month / monthrange / year / yearrange / datetime / datetimerange / week / quarterstringdate
unlink-panelsRange months flip independently (linked by default)boolean—
valueCurrent value: yyyy-MM-dd / yyyy-MM / yyyy / yyyy-Wnn / yyyy-Qn / yyyy-MM-ddTHH:mm:ss / JSON range arraystring | string[] | null—

Property (JS property; see each row for attribute reflection) ​

PropertyDescriptionTypeDefault
disabledDateDisabled-date predicate (property function channel, (date) => boolean)((d: Date) => boolean) | null—
shortcutsShortcut presets (property channel, [{ label, value/getValue }])ShortcutItem[] | null—
valueCurrent value: a date string for single; a string array for range / multiplestring | string[] | null—

Events ​

EventDescription
oas-blurThe component as a whole loses focus (internal moves do not fire)
oas-calendar-changeEmitted on every range endpoint pick, detail: { value: [start, end|null] }
oas-cell-renderEmitted per day cell on rebuild, detail: { date, element } (listeners must be idempotent)
oas-changeValue change, detail: { value } (string array for ranges and multiple)
oas-clearClear, detail: { value } is the previous value
oas-confirmEmitted when datetime/datetimerange submits via the confirm button (alongside oas-change), detail: { value }
oas-focusThe component as a whole gains focus
oas-open-changeOpen state change, detail: { open } (both controlled and uncontrolled)

Slots ​

NameDescription
prefix-iconLeading icon inside the trigger (decorative; clicks pass through)
suffix-iconTrailing 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 VariableDefault
--oas-glass-blurnone
--oas-glass-ringtransparent

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.

Released under the MIT OR Apache-2.0 License.