DatePicker
Dates without doubt.
About
Calendar picker for a single date, a start and end range, or a flat inline calendar, with an optional time of day. Type a date or pick one from the grid; the field shows it in the locale's spelling and the value stays ISO. Reach for it for invoice dates, due dates, send times and report periods.
Usage
Basic
The field is a text box with aria-haspopup="dialog", the chevron beside it is a labeled button, and the calendar is a role="grid" with Today and Clear links in its footer. Today carries aria-current="date" under the orange dot.
Range and report presets
Two clicks set a start and an end, and the preset column renders only in range mode, with aria-pressed on the active preset. Presets and the range value are properties, so setup writes them. The flat copy is the same picker with inline, so the column stays on the page.
Date and time
show-time adds a column of times beside the calendar, on the locale's clock unless hour-format names one. Picking a day keeps the time; picking a time closes the calendar. time-step spaces the rows and min-time and max-time bound the day. The value posts as a local YYYY-MM-DDTHH:mm with no time zone.
Format and locale
date-format is one of the four Intl dateStyle names, and locale supplies the order, the separators, the words, the first day of the week and the clock; the value stays ISO whatever the field shows. Unset, locale follows the page. first-day-of-week overrides the first day.
Typed entry
Type a date and press Enter or leave the field: the entry is read in the field format, as a month name, or as ISO, and rewritten in the field format once it commits. An entry that does not parse keeps its text, posts an empty value and holds the form on badInput with a message that shows the expected form.
Inline calendar
inline renders the calendar flat with no trigger and no shadow. It never opens, so it follows an external value write to the new month instead of leaving the date off screen.
As a property
variant="quiet" draws the date as text in the surrounding font, the calendar glyph before it, with no shell at rest: the fill comes on hover, and the shell while the field has focus or the calendar is open, since a focused text field is being typed into. The label is not drawn but still names the field.
Bounds and barred days
min-date and max-date stop the month arrows at the bounds, disabledDays bars weekdays by number and disabledDates bars single days; the last two are properties. A barred day stays in the grid with aria-disabled and stays reachable by the roving cursor, it just refuses the pick.
Sizes
size is the same sm, md, lg vocabulary and the same 28, 34, 42 heights as the rest of the control family, so a date field lines up in a row with a Select or an InputText. The calendar keeps its own metrics, and an inline picker has no field to size.
States
A trigger the user cannot open cannot be filled in, so a disabled picker never holds the form on valueMissing. An author-set error still applies and paints the trigger in the danger tone.
Read-only
readonly keeps the date readable but not typed over, opens no calendar, and the value still posts. A flat inline calendar shows its days and picks none.
In a form
A single date posts the ISO string whatever the field format, and a range posts "start,end". A cleared picker posts an empty string, and a disabled one is barred from submission and posts nothing at all.
Events
suiOpen fires after the element opens itself, suiMonthChange reports the month on show, and the cancelable suiClose fires before it closes and says why: escape, outside, trigger or pick. Here the listener refuses the first stray outside click with preventDefault and lets the next one through.
Keyboard
| Key | Action |
|---|---|
| ArrowDown ArrowUp | In the field, opens the calendar and focuses the selected day, or today. In the grid, moves a week. In the time column, moves a row. |
| ArrowLeft ArrowRight | In the grid, moves a day. Under dir="rtl" the pair swaps, so the arrow that points along the reading direction is always the forward one. |
| Home End | In the grid, moves to the first or the last day of the month. In the time column, moves to the first or the last time. |
| PageUp PageDown | Moves a month. |
| Shift+PageUp Shift+PageDown | Moves a year. |
| Enter | In the field, commits the typed date and closes an open calendar; with it closed, the form submits as after any text field. In a range field or on the chevron, opens or closes the calendar. In the grid, picks the focused day; a single pick closes the calendar, unless show-time keeps it open for the time. In the time column, picks the focused time and closes the calendar. |
| Space | In the grid, picks the focused day, and in the time column the focused time. On the chevron, opens or closes the calendar. |
| Escape | Closes the calendar and returns focus to the field. |
| Tab | From the field, moves to the chevron; Tab from the chevron, or Shift+Tab from the field, closes the calendar. Inside the open calendar, moves through the month arrows, the day grid, the time column with show-time, then Today (Now with show-time) and Clear. Tab past the last of them closes the calendar and moves on to the control after the picker; Shift+Tab from the first closes it and lands on the chevron. |
API
<sui-date-picker>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
dateFormat | date-format | SuiDateFormat"full" | "long" | "medium" | "short" | 'medium' | How the field spells the date, as one of the Intl dateStyle names: short (8/8/26), medium (Aug 8, 2026), long (August 8, 2026) or full (Saturday, August 8, 2026), each in the locale's own order and words. Typed entry is read against the same style, and ISO 2026-08-08 always parses. With showTime the locale adds the time in its own way (Aug 8, 2026, 2:30 PM), on the hourFormat clock. |
disabled | disabled | boolean | false | Disables the trigger. A disabled control posts nothing and never holds the form. |
disabledDates | property only | SuiDateInput[]SuiDateInput[] | undefined | Individual days that cannot be picked (holidays, days already booked). Property, not attribute. | |
disabledDays | property only | number[]number[] | undefined | Weekdays that cannot be picked, 0 Sunday to 6 Saturday ([0, 6] bars weekends). Property, not attribute. | |
error | error | stringstring | undefined | Error message; paints the field in the danger tone. | |
firstDayOfWeek | first-day-of-week | numbernumber | undefined | First column of the calendar, 0 Sunday to 6 Saturday; 1 starts the week on Monday. Unset, it comes from the locale: Sunday in en-US, Monday in de-DE. | |
help | help | stringstring | undefined | Help text under the field. Replaced by error when set. | |
hourFormat | hour-format | SuiTimeFormat"12" | "24" | undefined | Clock for the time with showTime: "12" (2:30 PM) or "24" (14:30), the same prop sui-time-picker takes. Unset, the locale's own clock: 12-hour in en-US, 24-hour in de-DE. The value stays HH:mm on either clock. | |
inline | inline | boolean | false | Renders the calendar flat with no field (always visible, no shadow). |
invalid | invalid | boolean | false | Danger border without a message. |
label | label | stringstring | undefined | Label above the field; also names the calendar dialog. | |
locale | locale | stringstring | undefined | BCP 47 tag ("en-US", "de-DE", "ja-JP") for the field text, the month heading, the weekday heads, the words a typed date may use, and the default clock and first day. Unset, the page's locale (setLocale() or <html lang>), else en-US; never the browser's, so a screen reads the same on every machine. A tag the runtime does not know falls back to en-US. | |
maxDate | max-date | SuiDateInputDate | string | undefined | Latest selectable day; later days are barred and the forward arrow stops there. With showTime, a bound with a time of day also bars the later times of that day. | |
maxTime | max-time | stringstring | undefined | Latest time of day with showTime, e.g. "6:00 PM" or "18:00". Unset, the day runs to 11:59 PM. | |
minDate | min-date | SuiDateInputDate | string | undefined | Earliest selectable day; earlier days are barred and the back arrow stops there. With showTime, a bound with a time of day ("2026-08-08T09:00", or a Date) also bars the earlier times of that day; a bare date bounds the whole day. | |
minTime | min-time | stringstring | undefined | Earliest time of day with showTime, e.g. "8:00 AM" or "08:00"; earlier times are not listed and a typed one is refused. Unset, the day starts at midnight. | |
name | name | stringstring | undefined | Form control name. Posts the ISO date, YYYY-MM-DDTHH:mm with showTime, or start,end in range mode; an empty picker posts an empty string and a disabled one posts nothing. Reflected: entry construction reads the content attribute, and the three framework bindings set props, so an unreflected name would post nothing. | |
open | open | boolean | false | Opens the panel. Mutable; the element closes itself on pick, outside pointer, Escape and Tab out of the calendar. |
placeholder | placeholder | stringstring | undefined | Field text while nothing is picked. | |
presets | property only | SuiDatePreset[]SuiDatePreset[] | undefined | Report ranges shown in a column left of the calendar (range mode). Property, not attribute. | |
range | range | boolean | false | Two clicks pick a start and an end date. The field is read-only in range mode; typing is for single dates. A range is whole days: showTime does nothing here. |
readOnly | readonly | boolean | false | Display only: the date can be read and copied but not typed over, the calendar opens nothing (a flat inline calendar shows its days and picks none), and the value still posts. Neither a read-only nor a disabled picker holds the form on valueMissing. |
required | required | boolean | false | A date must be picked for the surrounding form to be valid. A disabled picker never holds the form, since the user could not open it. |
showTime | show-time | boolean | false | Adds a time of day: a column of times beside the calendar, the time in the field, and a value of YYYY-MM-DDTHH:mm. Picking a day keeps the time and leaves the calendar open; picking a time keeps the day and closes it. A day picked before any time starts at the window's first minute. The footer's Today becomes Now. Single dates only; a range stays whole days. |
size | size | "lg" | "md" | "sm" | 'md' | Field height: sm 28, md 34 (default), lg 42, from the --control-* tokens, the same three the rest of the control family takes. The calendar keeps its own metrics, and an inline picker has no field to size. In the quiet variant it is the height of the box that paints on hover and while the field is in use; the text keeps the surrounding font. |
timeStep | time-step | number | 30 | Minutes between the rows of the time column with showTime, counted from minTime. A time off the step is typed into the field. |
todayDate | today-date | SuiDateInputDate | string | undefined | Pins "today" (the orange dot, the Today link and the two-digit year pivot) for demos and tests, e.g. "2026-08-22". With showTime, a time on it ("2026-08-22T10:05") pins the Now link too; without one, Now takes the clock's time on the pinned day. | |
tone | tone | "inverse" | undefined | Ink for the quiet variant on the brand chrome. inverse takes the inverse inks, the inverse hover wash and the inverse focus colour, as sui-button's tone of the same name does, so the value reads on a tone="brand" toolbar. Opening the field shows its shell in the card's own inks. The default variant ignores it. | |
value | value | SuiDateValueDate | SuiDateInput[] | string | undefined | Selected date, or [start, end] when range. Accepts ISO strings ("2026-08-08"), Dates, or an array of either. Mutable; the element writes ISO strings back before suiChange fires. The field shows the date in the dateFormat and locale spelling, and a range joins its two dates with an en dash. With showTime the value is a local date and time, "2026-08-08T14:30" as <input type="datetime-local"> has it: wall-clock time with no zone, so the host converts to and from UTC. A bare date reads as midnight, and a Z or offset on the string is not applied. | |
variant | variant | "default" | "quiet" | 'default' | default draws the field shell. quiet draws the date as text in the surrounding font, with the calendar glyph before it and no border or fill at rest, for a record's properties column: the fill comes on hover, and the shell while the field has focus or the calendar is open, since a focused text field is one being typed into. The label is not drawn but still names the field, so the host prints the property name. Typing, the keyboard, events, validation and the form post are the same in both. The inline attribute is the flat calendar, which has no field, so variant does nothing there. Anything else falls back to default. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiChange | string | string[] | onSuiChange | @sui-change | Fires when a date commits, by pick or by typed entry on Enter or blur; detail is the ISO string (YYYY-MM-DDTHH:mm with showTime; "" after clear or an entry that does not parse), or [start, end] ISO strings in range mode ([] after clear). |
suiClose | SuiCloseReason"cancel" | "close-button" | "escape" | "outside" | "pick" | "scrim" | "trigger" | onSuiClose | @sui-close | Fires before the element closes the panel itself; detail is 'escape' | 'outside' | 'trigger' | 'pick'. Tab out of the calendar reports 'outside', because focus left the control. Cancelable: preventDefault() keeps it open. Does not bubble: a preventDefault() in a dialog's own suiClose listener cannot veto this one. |
suiMonthChange | SuiDateViewDetail | onSuiMonthChange | @sui-month-change | Fires when the calendar shows a different month, so a host can fetch that month's availability. Does not bubble: it reports the calendar's view, not the value. |
suiOpen | void | onSuiOpen | @sui-open | Fires after the element opens the panel itself. Does not bubble, so a dialog around the picker never takes it for its own. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves keyboard focus to the field (or the focused day when inline). |
Types
SuiCloseReason typeWhy a dismissible surface is closing. Detail of the cancelable suiClose. A consumer expresses "a stray backdrop click must not close this" by calling preventDefault() on the reason it does not accept, which is why none of these needs a prop of its own. | |||
|---|---|---|---|
| No members. |
SuiDateFormat typeThe four Intl dateStyle names the field text can take. | |||
|---|---|---|---|
| No members. |
SuiDateInput typeA date as an ISO YYYY-MM-DD string (any string new Date accepts also works) or a Date. With showTime, a local YYYY-MM-DDTHH:mm. | |||
|---|---|---|---|
| No members. |
SuiDatePreset interfaceReport preset: a labeled [start, end] range (This month, Last quarter, Year to date). | |||
|---|---|---|---|
label | string | ||
range | [SuiDateInput, SuiDateInput] | ||
SuiDateStyle typeThe four Intl dateStyle names: short 8/8/26, medium Aug 8, 2026, long August 8, 2026, full Saturday, August 8, 2026 (en-US). | |||
|---|---|---|---|
| No members. |
SuiDateValue typeSingle date, or [start, end] in range mode. The element writes ISO strings back. | |||
|---|---|---|---|
| No members. |
SuiDateViewDetail interfaceDetail of suiMonthChange: the month on show. month is 0-based, as Date.getMonth() is. | |||
|---|---|---|---|
year | number | ||
month | number | ||
SuiTimeFormat typeClock display: 2:30 PM or 14:30. | |||
|---|---|---|---|
| No members. |
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color27
Typography1
Spacing and size5
Radius4
Elevation2
Motion3
Every name above is listed with its value and its role in Foundations.