---
title: Datetime Picker
description: A field that picks a date and a time together, from a calendar and a list of times in a dialog, for a form or a Livewire property.
visibility: guest
draft: false
---

# Datetime Picker

The `<x-wirekit::datetime-picker>` component picks a moment: a date and a time of day. Its trigger looks like a field and shows the moment it holds, "Oct 27, 2026 at 10:30 AM". It opens a dialog with a [calendar](/components/calendar) and a list of times beside it. The value is written `YYYY-MM-DDTHH:MM`, in the shape a `datetime-local` field submits, and a form receives it under the field's `name`.

## Usage

:::preview{title="Datetime picker"}
<x-wirekit::datetime-picker name="meeting" label="Meeting" />
:::

A value takes both halves. A day picked first shows on the trigger, and the focus moves to the list of times, but the field stays empty until a time is picked too: half a moment cannot be written as one, and a quiet midnight would be wrong. Once there is a value, another day changes it at once and the dialog stays open; a time completes it and closes the dialog.

:::preview{title="With a value"}
<x-wirekit::datetime-picker name="call" label="Call" value="2026-10-27T10:30" />
:::

A date object works as the value too, such as a model attribute with a `datetime` cast. It is read as the wall-clock time it names in your application's time zone.

## Confirmation

With `with-confirmation` the dialog keeps the day and the time it is given until Select is pressed. Cancel, Escape or a press outside leave the value as it was, and the trigger shows the old value until then.

:::preview{title="Picked, then confirmed"}
<x-wirekit::datetime-picker name="launch" label="Launch" with-confirmation />
:::

## Default time

`default-time` gives a day picked without a time that time at once, so a single pick in the calendar makes a value.

:::preview{title="Nine o'clock unless changed"}
<x-wirekit::datetime-picker name="visit" label="Visit" default-time="09:00" />
:::

## Times

`interval` sets the minutes between two times in the list, 30 by default. `min-time` and `max-time` set the first and the last time of every day, and a time outside them is not in the list.

:::preview{title="Every 15 minutes within office hours"}
<x-wirekit::datetime-picker name="slot" label="Slot" interval="15" min-time="09:00" max-time="17:00" />
:::

`time-format` shows the times on a 12-hour or a 24-hour clock. `auto`, the default, follows your application's locale.

:::preview{title="On a 24-hour clock"}
<x-wirekit::datetime-picker name="departure" label="Departure" value="2026-10-27T18:30" time-format="24-hour" />
:::

The time list is a list of times on the wall clock. A day on which the clocks change offers the same times as any other day, and the value is the time it shows.

## Limits

`min` and `max` take a moment, a day, a date object, `today` or `now`. The calendar closes the days before `min` and after `max`, and on those two days the list closes the times outside them. `max` written as a day leaves the whole of that day open.

:::preview{title="From now until noon on 20 December"}
<x-wirekit::datetime-picker name="delivery" label="Delivery" min="now" max="2026-12-20T12:00" />
:::

`unavailable` closes days, times and spans: a day (`2026-10-24`), a time or a span on every day (`12:00`, `12:00-13:00`), and a moment or a span on one day (`2026-10-23T10:00`, `2026-10-23T15:00-16:00`), both ends of a span included. A date object closes the moment it names, as an existing booking does. Write a list, or the entries separated by commas.

:::preview{title="Lunch and two bookings closed"}
<x-wirekit::datetime-picker name="appointment" label="Appointment" value="2026-10-27T09:00" unavailable="12:00-13:00, 2026-10-27T10:00, 2026-10-27T15:00-16:00, 2026-10-31" />
:::

A closed day or time stays in reach of the keyboard and is named as unavailable, and nothing picks it. The limits steer what a reader can pick and nothing more: validate the value on the server as well.

## Typing the time

`time="input"` puts a field under the calendar where the time is typed, instead of the list beside it. The field holds the hour, the minute and, on a 12-hour clock, AM or PM, each a segment of its own, in the order and with the separators of your application's locale. The button at the end of the field opens the list of times as suggestions, with the same limits, and a time picked there fills the segments.

:::preview{title="A typed time"}
<x-wirekit::datetime-picker name="pickup" label="Pickup" value="2026-10-27T14:45" time="input" min-time="08:00" max-time="18:00" />
:::

A digit sets a segment and moves on once no other digit fits: on a 12-hour clock `1` waits for `10`, `11` or `12`, and `3` moves to the minutes at once. The arrow keys step a segment round its range, from 59 back to 00 without changing the hour, Home and End go to its first and its last value, `a` and `p` set AM or PM, and Backspace empties it. On a touch screen the keyboard opens with digits.

A typed time outside `min-time` and `max-time`, or closed by `unavailable`, `min` or `max` on the day picked, is not taken, and a sentence under the field says why: type 7:00 AM above, and it names the times from 8:00 AM to 6:00 PM. A typed time waits for Select, as with [`with-confirmation`](#confirmation), so the field never receives a time that is half typed.

## Typing the whole moment

`type="input"` makes the trigger a field where the whole moment is typed: the day, the month, the year, the hour, the minute and, on a 12-hour clock, AM or PM, each a segment of its own, in the order and with the separators of the locale. A German page asks `27.10.2026, 14:45`, an American one `10/27/2026, 2:45 PM`. The button at the end of the field opens the dialog, and the field and the dialog show each other's moment.

:::preview{title="A typed moment"}
<x-wirekit::datetime-picker name="departure" label="Departure" type="input" value="2026-10-27T14:45" clearable />
:::

A segment takes digits as a [typed time](#typing-the-time) does, and the year takes four. A moment typed whole and open is taken at once, as a native field takes it, so `wire:model.live` hears each one. A day its month does not have, a day closed by `min`, `max` or `unavailable`, and a closed time are not taken: the field holds no moment, and a sentence under it says why. A moment pasted into any segment fills the field, written as a timestamp (`2026-10-27T14:45`, an offset dropped) or as the locale writes it.

With `range` the start and the end are typed in two fields, named Start and End, with one button beside them that opens the dialog for both. The two stand side by side, and on a narrow screen one above the other. A range typed whole is taken at once when the end comes after the start and the range covers as many days as `min-range` and `max-range` allow, both ends counted; until then the field of the end says why. The dialog opens on what the two fields hold, a start typed without its end among it.

:::preview{title="A typed stay of up to two weeks"}
<x-wirekit::datetime-picker name="stay" label="Stay" type="input" range value="2026-10-27T15:00/2026-10-30T11:00" max-range="14" />
:::

With a [custom trigger](#custom-trigger) the trigger stays the caller's button.

## Range

`range` picks two moments, a start and an end. The calendar shows two months and picks the two days, and below it a row for each end takes its time: a field that opens the list of times, or with `time="input"` the time typed in segments. A range always waits for Select range, which stays closed until both ends have a day and a time and the end comes after the start. On one day the times decide, and the sentence under the times says why.

:::preview{title="A trip"}
<x-wirekit::datetime-picker name="trip" label="Trip" range value="2026-10-27T09:00/2026-11-01T17:00" />
:::

The trigger writes the range from its start to its end, "Oct 27, 2026 at 9:00 AM – Nov 1, 2026 at 5:00 PM", and the end's time alone when both ends fall on one day. `default-time` gives days picked by hand their times, one for both ends or `09:00/17:00` for each, and `min-range` and `max-range` limit the days a range covers, as on the [calendar](/components/calendar#range-limits).

:::preview{title="A shift on one day, typed, nine to five unless changed"}
<x-wirekit::datetime-picker name="shift-hours" label="Shift" range time="input" default-time="09:00/17:00" max-range="1" />
:::

With `presets` the calendar lists ranges such as "Last 7 days" beside it, as on the [calendar](/components/calendar#presets). A preset takes its whole days, from the first time of a day to the last, unless `default-time` names the two.

:::preview{title="A report period with presets"}
<x-wirekit::datetime-picker name="report-period" label="Report period" range presets="today last7Days thisMonth custom" />
:::

### Binding a range

The form receives `name[start]` and `name[end]`, each `YYYY-MM-DDTHH:MM`, and `name[preset]` with `presets`. `wire:model` binds the two ends as `{property}.start` and `{property}.end`, so the property is an array with the two keys or a `Pushery\WireKit\Values\DateTimeRange`, which keeps the time of each end and the preset:

```php
use Pushery\WireKit\Values\DateTimeRange;

public DateTimeRange $trip;

public function mount(): void
{
    $this->trip = DateTimeRange::from('2026-10-27T09:00/2026-11-01T17:00');
}
```

```blade
<x-wirekit::datetime-picker name="trip" label="Trip" range :value="$trip" wire:model.live="trip" />
```

Validation reads the ends as `trip.start` and `trip.end`. `:value` takes `start/end` as text, an array with `start` and `end`, the two as a list, or a range object.

## Opening month and time

Without a value the calendar opens on the current month and the list of times on the current time. `open-to` names another moment, or a day, for both.

:::preview{title="Opens on 2 November at 14:00"}
<x-wirekit::datetime-picker name="review" label="Review" open-to="2026-11-02T14:00" />
:::

## Clearing

`clearable` adds a button to the trigger that empties the field, while it holds a value.

:::preview{title="With a clear button"}
<x-wirekit::datetime-picker name="reminder" label="Reminder" value="2026-10-27T08:00" clearable />
:::

## Hint and error

A `hint` stands under the field and describes the trigger. An `error` takes its place, marks the trigger invalid and is announced. After a failed validation the error is read from the error bag by `name`, so a form needs no `:error` of its own.

:::preview{title="With a hint"}
<x-wirekit::datetime-picker name="boarding" label="Boarding" hint="Local time at the airport." />
:::

:::preview{title="Error state"}
<x-wirekit::datetime-picker name="arrival" label="Arrival" value="2026-10-27T10:30" error="The arrival must come after the departure." />
:::

## Calendar options

The calendar in the dialog takes the options of the calendar component: `months`, `with-today`, `selectable-header`, `week-numbers`, `week-starts-on` and `fixed-weeks`. See the [calendar](/components/calendar) for each.

:::preview{title="Today button, week numbers and six weeks"}
<x-wirekit::datetime-picker name="shift" label="Shift" with-today week-numbers fixed-weeks />
:::

## Sizes

`size` sets the height of the trigger: `sm`, `md`, the default, or `lg`, as on the other fields.

:::preview{title="Small and large triggers"}
<x-wirekit::stack gap="md">
    <x-wirekit::datetime-picker name="small" label="Small" size="sm" value="2026-10-27T10:30" />
    <x-wirekit::datetime-picker name="large" label="Large" size="lg" value="2026-10-27T10:30" />
</x-wirekit::stack>
:::

## Custom trigger

The `trigger` slot replaces the field with a trigger of your own, a button that says what it does. The picker wires it to the dialog, and its content names it.

:::preview{title="A Schedule button"}
<x-wirekit::datetime-picker name="post">
    <x-slot:trigger>
        <x-wirekit::button>Schedule</x-wirekit::button>
    </x-slot:trigger>
</x-wirekit::datetime-picker>
:::

## On a phone

Below the kit's `sm` width, 640 pixels, and on a screen less than 480 pixels tall, as a phone held sideways, the dialog opens as a modal over the page rather than below the trigger: centered over a backdrop, inside the safe area of a phone with a notch, with the page behind it held still. The days grow to the size of a touch target as far as the width allows, a range shows one month with its presets as a select above it, and the list of times gives way to a select, which the phone opens as its own wheel; a typed time keeps its segments. A pick always waits for Select there, with or without `with-confirmation`, and a tap on the backdrop closes the dialog as Escape does. A dialog taller than the screen scrolls in itself with Cancel and Select in sight. The screen is read when the dialog opens, and a tablet keeps the panel below the trigger whichever way it is held.

:::preview{title="A meeting picked on a phone"}
<x-wirekit::datetime-picker name="phone-meeting" label="Meeting" value="2026-10-27T10:30" />
:::

Set the preview to 390 pixels and open the picker to see the modal.

## Inside a form

The picker renders a hidden field with the given `name`, which a form submits as `YYYY-MM-DDTHH:MM`. `required` stops an empty submit as a native field does, with the browser's own message under the field. A form reset returns the picker to the value it started with. `disabled` takes the field out of the form, and `readonly` shows the value and opens nothing.

```blade
<form method="POST" action="/meetings">
    @csrf

    <x-wirekit::datetime-picker name="starts_at" label="Starts at" required />

    <x-wirekit::button type="submit">Save</x-wirekit::button>
</form>
```

## With Livewire

`wire:model` binds the moment, written `YYYY-MM-DDTHH:MM`. Pass the bound property as `:value` as well: the picker shows the moment it is given, and a moment the server sets reaches it.

```blade
<x-wirekit::datetime-picker name="starts_at" label="Starts at" :value="$startsAt" wire:model.live="startsAt" />
```

The answer to a pick of the reader's own changes nothing on the screen, so an open dialog stays open while the server answers.

## Localization

The picker writes its moment in your application's locale, the one `config('app.locale')` carries: the day, the time and the word between them on the trigger, and the months and weekdays of the calendar. The server writes the trigger the way the script does, so its text does not change when the page starts, and the language of the reader's browser plays no part.

`locale` writes the moment in another locale, a BCP 47 tag such as `fr` or `en-US`: for a schedule that belongs to another region than the page, or for a reader whose language your application keeps in the session.

:::preview{title="A moment written in French"}
<x-wirekit::datetime-picker name="departure" label="Departure" value="2026-10-27T14:00" locale="fr" />
:::

```blade
<x-wirekit::datetime-picker name="departure" label="Departure" :locale="session('locale')" />
```

The other texts of the picker, such as Cancel, Select and the placeholder, stay in your application's language and come from WireKit's translations. `time-format` sets a 12-hour or a 24-hour clock where the locale's own does not suit, and `week-starts-on="locale"` starts the calendar's week on the locale's first day.

## Timezones

The picker works with wall-clock time, as a `datetime-local` field does: the moment the reader picks is the moment the field submits, `2026-10-27T14:00`, and nothing is converted in the browser. A date object, or a moment written with its offset as `toIso8601String()` writes one, is read in your application's time zone, `config('app.timezone')`, and Livewire reads the moment that comes back in that zone too.

When your readers live in other time zones, keep the bound property as text in the reader's zone and convert it when you load and store it:

```php
use App\Models\Meeting;
use Carbon\CarbonImmutable;
use Livewire\Component;

class EditMeeting extends Component
{
    public Meeting $meeting;

    // The reader's time zone, from their profile.
    public string $zone = 'America/New_York';

    public string $startsAt = '';

    public function mount(): void
    {
        $this->startsAt = $this->meeting->starts_at->setTimezone($this->zone)->format('Y-m-d\TH:i');
    }

    public function save(): void
    {
        $this->meeting->update([
            'starts_at' => CarbonImmutable::createFromFormat('Y-m-d\TH:i', $this->startsAt, $this->zone)->utc(),
        ]);
    }
}
```

```blade
<x-wirekit::datetime-picker name="starts_at" label="Starts" :value="$startsAt" wire:model="startsAt" />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string\|null` | `null` | Name of the hidden form field. Ids derive from it |
| `id` | `string\|null` | `null` | Id of the trigger |
| `label` | `string\|null` | `null` | The field's label |
| `value` | `string\|DateTimeInterface\|array\|null` | `null` | The moment, `YYYY-MM-DDTHH:MM`, or a date object, read in the application's time zone. With `range`: `start/end`, an array with `start` and `end`, or a `DateTimeRange`. See [Binding a range](#binding-a-range) |
| `range` | `bool` | `false` | Two moments, a start and an end, taken together with Select range. See [Range](#range) |
| `type` | `string` | `'button'` | `button`, a trigger that opens the dialog, or `input`, a field where the whole moment is typed, two with `range`, with a button that opens the dialog. Not with a custom trigger. See [Typing the whole moment](#typing-the-whole-moment) |
| `placeholder` | `string\|null` | `null` | What the trigger shows without a value; "Select a date and time" by default, "Select a date and time range" with `range` |
| `hint` | `string\|null` | `null` | A hint below the field |
| `help` | `string\|null` | `null` | An explanation in a tooltip beside the label |
| `error` | `string\|null` | `null` | An error message; read from the error bag by `name` as well |
| `announceError` | `bool\|null` | `null` | Whether an error is announced when it appears |
| `size` | `string` | `'md'` | The height of the trigger: `sm`, `md` or `lg` |
| `disabled` | `bool` | `false` | Disables the picker and leaves it out of the form |
| `readonly` | `bool` | `false` | Shows the value and opens nothing |
| `required` | `bool` | `false` | Stops an empty submit with the browser's message |
| `clearable` | `bool` | `false` | A button that empties the field |
| `withConfirmation` | `bool` | `false` | The day and the time wait for Select, as a range always does. See [Confirmation](#confirmation) |
| `defaultTime` | `string\|null` | `null` | The time a day picked without one takes, `HH:MM`; with `range` one for both ends or `HH:MM/HH:MM` |
| `time` | `string` | `'list'` | `list`, a list of times beside the calendar, or `input`, a time typed in segments with the list as suggestions. See [Typing the time](#typing-the-time) |
| `interval` | `int` | `30` | Minutes between two times in the list |
| `timeFormat` | `string` | `'auto'` | `auto`, `12-hour` or `24-hour` |
| `minTime` | `string\|null` | `null` | The first time of every day, `HH:MM` |
| `maxTime` | `string\|null` | `null` | The last time of every day, `HH:MM` |
| `min` | `string\|DateTimeInterface\|null` | `null` | The first moment a reader can pick. See [Limits](#limits) |
| `max` | `string\|DateTimeInterface\|null` | `null` | The last moment a reader can pick |
| `unavailable` | `array\|string\|null` | `null` | Days, times and spans a reader cannot pick |
| `openTo` | `string\|DateTimeInterface\|null` | `null` | Where the dialog opens without a value |
| `months` | `int\|null` | `null` | Months the calendar shows: 1, or 2 with `range` |
| `minRange` | `int\|null` | `null` | With `range`: the fewest days a range may cover, both ends counted |
| `maxRange` | `int\|null` | `null` | With `range`: the most days a range may cover, both ends counted |
| `presets` | `bool\|string\|array\|null` | `null` | With `range`: ranges such as "Last 7 days" beside the calendar, as the calendar's `presets` takes them |
| `withToday` | `bool` | `false` | The calendar's today button |
| `selectableHeader` | `bool` | `false` | The calendar's month and year selects |
| `weekNumbers` | `bool` | `false` | The calendar's week numbers |
| `weekStartsOn` | `int\|string` | `1` | The first day of the calendar's week, from `0` to `6`, or `locale` |
| `fixedWeeks` | `bool` | `false` | Six rows in every month |
| `locale` | `string\|null` | `null` | BCP 47 locale for the moment on the trigger, the calendar and the times. `null` uses your application's locale. See [Localization](#localization) |
| `scope` | `string\|null` | `null` | Scoped personalization key |

## Events

The picker dispatches these on its root, and they bubble:

| Event | When |
| --- | --- |
| `wirekit:datetime-picker-open` | The dialog opens |
| `wirekit:datetime-picker-close` | The dialog closes, however it closes |
| `wirekit:datetime-picker-clear` | The reader empties the field with the clear button |

The root carries `data-open` while the dialog is open. The hidden field fires `input` and `change` for each moment picked, as a native field does, so `wire:model.change` and `wire:model.blur` work as on any field.

## Accessibility

- The trigger is a button with `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`. Its name is the field's label and the moment it shows, "Meeting Oct 27, 2026 at 10:30 AM", and "(required)" for a required field.
- The dialog is a `role="dialog"` with `aria-modal="true"`, named by the field's label and what it is for, "Meeting, Select a date and time". Enter, Space and Down Arrow on the trigger open it and move the focus to the day of the value, or without one to today or the next day that can be picked, on every opening; Tab stays inside it, and Escape closes it and returns the focus to the trigger.
- The calendar is the [calendar](/components/calendar) component, with its grid, its keyboard and its names.
- On a phone the dialog is a modal: the page behind it is inert and does not scroll, the focus stays in the dialog, and a tap on the backdrop or Escape closes it and returns the focus to the trigger. The select that stands in for the list of times is named "Time", or by the row of a range's end, and offers the same times, a closed one disabled.
- The list of times is a `listbox` named "Time". The arrow keys move between open times, Home and End go to the first and the last, Page Up and Page Down an hour, and typing goes to the time typed: `9` to nine o'clock, `14` to two in the afternoon, `9:3` to half past nine. Enter or Space picks. A closed time is passed over and named as unavailable.
- A day picked without a time moves the focus to the list of times.
- With `range` the calendar picks the two days as the calendar does with `range`. The time of each end stands in a row named "Start" or "End": a button named by the row and the time it shows, which opens the list of times as a `listbox` named by the row, or with `time="input"` the typed time named by the row. Select range is described by the sentence that says the end must come after the start, which stands in a live region (`aria-live="polite"`) and is announced as it appears, as a field's error is, unless `announce-error` is off.
- With `time="input"` the segments are spin buttons named "Hour", "Minute" and "AM/PM", in a group named "Time", each with its range and its value. Up and Down change a segment, Left and Right move between them, and Tab goes on to the button at the end of the field, then to Cancel and Select. The button is named "Suggested times" and opens the list of times; Escape closes the list first, and the dialog with the next press. A day picked without a time it can take moves the focus to the first segment. The sentence that says why a typed time is not taken is announced, and describes each segment.
- With `type="input"` the field is a `role="group"` named by the label. Its segments are spin buttons named "Day", "Month", "Year", "Hour", "Minute" and "AM/PM", each with its range and its value, and the label points at the first one. The hint and the error describe each segment and the button at the end of the field, which is named "Select a date and time" and opens the dialog; Alt+Down Arrow opens it from a segment, as on a native field. The clear button empties the field and moves the focus to its first segment. The sentence that says why a typed moment is not taken describes each segment and stands in a live region (`aria-live="polite"`), announced as it appears unless `announce-error` is off. With `range` the two fields are groups named by the label and their word, "Stay Start" and "Stay End", in a group named by the label, each with a sentence of its own; the sentence of the end also says when the end does not come after the start or the range covers too few or too many days. The button beside them is named "Select a date and time range".

## Keyboard Interaction

| Key | Where | Action |
| --- | --- | --- |
| Enter, Space, Down Arrow | Trigger | Opens the dialog, with the focus on the day of the value, or on today or the next day that can be picked |
| Escape | Dialog | Closes the dialog and returns the focus to the trigger; with the suggestions of a typed time or the list of a range's time open, it closes them first |
| Tab, Shift+Tab | Dialog | Move between the calendar, the times and the buttons; the focus stays in the dialog |
| Arrow keys, Home, End, Page Up, Page Down | Calendar | As on the [calendar](/components/calendar#keyboard); with Shift, Page Up and Page Down move a year |
| Up, Down | List of times | Move between the open times |
| Home, End | List of times | The first and the last open time |
| Page Up, Page Down | List of times | An hour back or ahead |
| A digit | List of times | Goes to the time typed: `9` to nine o'clock, `14` to two in the afternoon, `9:3` to half past nine |
| Enter, Space | List of times | Picks the time |
| Enter, Space | Time of a range's end | Opens its list of times, with the focus on the time it shows or the nearest open one |
| Up, Down | Typed time | Steps the segment round its range |
| Left, Right | Typed time | Moves between the segments |
| Home, End | Typed time | The first and the last value of the segment |
| `a`, `p` | Typed time | Sets AM or PM |
| Backspace | Typed time | Empties the segment |
| A digit | Typed moment | Sets the segment and moves on once no other digit fits, the year at its fourth digit |
| Up, Down | Typed moment | Steps the segment round its range; an empty year starts at the current one |
| Left, Right | Typed moment | Moves between the segments |
| Home, End | Typed moment | The first and the last value of the segment |
| `a`, `p` | Typed moment | Sets AM or PM |
| Backspace | Typed moment | Empties the segment, or moves back from an empty one |
| Alt+Down Arrow | Typed moment | Opens the dialog |

## Design Tokens

| Token | Used for |
| --- | --- |
| `--size-wk-time-list` | Width of the list of times beside the calendar |
| `--size-wk-sm` / `--size-wk-md` / `--size-wk-lg` | Height of the trigger at each size, and of a time in the list |
| `--size-wk-xl` | The least height of the list of times |
| `--color-wk-bg-input` / `--color-wk-border-strong` | The trigger's surface and border |
| `--color-wk-bg-elevated` / `--color-wk-border` / `--shadow-wk-lg` | The dialog's surface, border and shadow |
| `--color-wk-bg-hover` / `--color-wk-bg-active` | A time under the pointer, and the time picked |
| `--color-wk-text-muted` / `--color-wk-text-placeholder` | The word "at" and the icons, and the placeholder |
| `--radius-wk-md` / `--radius-wk-lg` / `--radius-wk-sm` | The trigger, the dialog and a time |
| `--color-wk-accent` / `--color-wk-accent-fg` | The segment of a typed time that has the focus |
| `--color-wk-border-error` / `--color-wk-danger-text` | The field of a typed time that is not taken, and the sentence that says why |
| `--color-wk-overlay` / `--z-wk-modal` | The backdrop behind the dialog on a phone, and the layer the two stand on |
| `--size-wk-modal-sm` | The width of the dialog on a phone, less the edges of a narrower screen |
| `--size-wk-touch-target` | The size the days of the calendar grow to on a phone |

## Personalization

Override classes globally via `WireKit::personalize()`:

```php
use Pushery\WireKit\WireKit;

WireKit::personalize('datetime-picker', [
    'trigger' => 'rounded-[var(--radius-wk-lg)]',
    'panel' => 'shadow-[var(--shadow-wk-xl)]',
]);
```

## Further Reading

- [WAI-ARIA Date Picker Dialog Example](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/)
- [WAI-ARIA Listbox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)
- [Calendar](/components/calendar) and [Date Picker](/components/date-picker)
