# TallStackUI: Date
> TallStackUI is a TALL Stack (Tailwind CSS, Alpine.js, Laravel, Livewire)
> component library providing 80+ Blade components for building modern web interfaces.
A date picker component with a floating calendar panel, month/year pickers, range selection, multiple date selection, configurable date format, min/max date and year constraints, disabled dates, day-of-week filtering, helper buttons (yesterday/today/tomorrow), month-year-only mode, and direct keyboard input through `typeable`.
## Basic Usage
```blade
```
```blade
```
```blade
```
```blade
```
```blade
```
```blade
```
Outside Livewire, give it a `name` and it backs a plain form through a hidden input.
The hidden input belongs to the component that renders it, so the same `name` can
repeat on the page, in another form or as an array name such as `dates[]`.
A single date is submitted as `Y-m-d`; `range` and `multiple` are submitted JSON
encoded. `value` takes the same back: a date string, and for `range` or `multiple` an
array, that JSON string or a comma separated string:
```blade
```
## Attributes
| Attribute | Type | Default | Description |
|-----------------|-----------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------|
| label | string\|ComponentSlot\|null | null | Label text displayed above the input |
| hint | string\|ComponentSlot\|null | null | Hint text displayed below the input |
| invalidate | bool\|null | null | Prevents displaying validation error messages |
| range | bool\|null | false | Enables date range selection (start and end dates) |
| multiple | bool\|null | false | Enables multiple individual date selection |
| format | string\|null | 'YYYY-MM-DD' | Display format for the selected date (see Format Tokens) |
| min-date | string\|Carbon\|null | null | Minimum selectable date |
| max-date | string\|Carbon\|null | null | Maximum selectable date |
| min-year | int\|null | null | Minimum selectable year in the year picker |
| max-year | int\|null | null | Maximum selectable year in the year picker |
| helpers | bool\|null | null | Shows yesterday, today, and tomorrow quick-select buttons |
| month-year-only | bool\|null | false | Restricts the picker to month and year selection only |
| disable | array\|Collection | [] | Array of date strings or date instances to disable: `Carbon`, `CarbonImmutable`, the dates of a `CarbonPeriod` or a native `DateTime` |
| start | int\|string\|null | null | First day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday). Falls back to the global `start` configuration, `0` by default |
| only | int\|string\|null | null | Restricts selection to a specific day of the week (0-6) |
| weekdays | bool\|null | false | Restricts selection to weekdays only (Monday-Friday) |
| weekends | bool\|null | false | Restricts selection to weekends only (Saturday-Sunday) |
| typeable | bool\|null | false | Allows typing the date directly into the input (see Typeable) |
| disabled | bool | false | Locks the input, the calendar and the clear button. The value is not submitted. |
| readonly | bool | false | Locks the input, the calendar and the clear button. The value is still submitted. |
## Global Configuration
```php
// config/tallstackui.php
'date' => [
\TallStackUi\Components\Form\Date\Component::class,
[
'start' => 0,
],
],
```
`start` sets the first day of the week for every date picker, so an application whose
week starts on Monday sets `'start' => 1` once instead of repeating the attribute. The
inline attribute always wins over the global default, so `start="0"` keeps Sunday on a
single picker while the configuration moves the others. The configured value goes through
the same validation as the attribute: anything outside `0`–`6` raises the exception below.
## Typeable
`typeable` turns the input into a regular text field with an auto-formatting mask
derived from the `format` tokens (`DD/MM/YYYY` becomes `##/##/####`), inserting the
separators as the user types. On blur, or when Enter is pressed, the typed value is
parsed against the format and validated by the same rules as the picker — min/max,
disabled dates, weekdays, weekends and only — so an invalid, impossible (`31/02/2020`)
or out-of-range date restores the previous value, while clearing the field and leaving
empties the model. Clicking the input no longer opens the picker; the calendar icon
still does, and the keyboard focus keeps working.
With `wire:change`, the method is called once, with the new date as its argument, and
only when the typed date differs from the current one. Leaving the field without
changing it, or with an invalid date, calls nothing. The attribute stays on the
component and is not forwarded to the inner input, so the browser `change` event of
the text field never calls the method on its own.
Without `typeable` the input takes no typing, but `Tab` and `Shift+Tab` still move the
focus through it.
The `format` must contain the `YYYY`, `MM` and `DD` tokens, and `typeable` cannot be
combined with `range`, `multiple` or `month-year-only` — combining them throws the
exception below.
## Alpine.js Events
| Event | Description |
|-------------|--------------------------------------------|
| x-on:select | Triggered when a date is selected |
| x-on:clear | Triggered when the clear button is clicked |
## Validation Constraints
- The `min-date` must be a valid date string or Carbon instance.
- The `max-date` must be a valid date string or Carbon instance.
- The `min-date` must be less than or equal to `max-date` when both are set.
- The `min-year` must be less than or equal to `max-year` when both are set.
- The `start` attribute, inline or configured, must be between 0 and 6.
- The `only` attribute must not be greater than 6.
- The `typeable` cannot be used with `range`, `multiple` or `month-year-only`.
## Event Payload Details
```blade
```
### Backend Format Note
The component uses `Y-m-d` format internally. If your date is in a different format, convert it server-side:
```php
$date = '20/02/2024';
$date = now()->createFromFormat('d/m/Y', $date)->format('Y-m-d');
// Result: '2024-02-20'
```
## Format Tokens
The `format` attribute is visual only and accepts the tokens below. They are the Day.js core tokens, but the formatter is the package's own (`js/helpers/date.js`), so tokens that Day.js only exposes through plugins — `Do`, `Q`, `X`, `x`, `k`, `w`, `gggg` — are not available and never were.
| Token | Output |
|----------|----------------------------------------------------------|
| `YY` | `26` |
| `YYYY` | `2026` |
| `M` | `1`-`12` |
| `MM` | `01`-`12` |
| `MMM` | `Jan` (first three characters of the translated month) |
| `MMMM` | `January` (translated) |
| `D` | `1`-`31` |
| `DD` | `01`-`31` |
| `d` | `0`-`6` |
| `dd` | `Su` (first two characters of the translated weekday) |
| `ddd` | `Sun` (first three characters of the translated weekday) |
| `dddd` | `Sunday` (translated) |
| `H` | `0`-`23` |
| `HH` | `00`-`23` |
| `h` | `1`-`12` |
| `hh` | `01`-`12` |
| `m` | `0`-`59` |
| `mm` | `00`-`59` |
| `s` | `0`-`59` |
| `ss` | `00`-`59` |
| `SSS` | `000`-`999` |
| `a` | `am` / `pm` |
| `A` | `AM` / `PM` |
| `Z` | `+03:00` |
| `ZZ` | `+0300` |
| `[text]` | `text`, escaped from parsing |
```blade
```
Month and weekday names come from the `calendar` translations in `lang/{locale}/messages.php`, so `MMMM` and `dddd` follow the application locale. The picker only ever holds a date, so the time tokens always render zeros.
## Soft Customization
Soft customization allows you to override default Tailwind CSS classes used by this component at runtime, either through a service provider or scoped per-instance.
### Customization
```php
TallStackUi::customize()
->form('date')
->block('button.day', 'your-tailwind-classes');
```
### Available Blocks
| Block Name | Purpose |
|---------------------------|-----------------------------------------------------------------------------------------------------|
| wrapper.helpers | Helper buttons scrollable container |
| floating.default | Base floating panel positioning |
| floating.class | Floating panel width and padding |
| box.picker.expanded | Minimum panel height while a picker is open (`min-h-[17rem]`), keeping room under `month-year-only` |
| box.picker.button | Month/year picker button styles |
| box.picker.wrapper.first | Picker overlay background and positioning |
| box.picker.wrapper.second | Picker content flex wrapper |
| box.picker.wrapper.third | Picker header row layout |
| box.picker.label | Picker label button styles |
| box.picker.range | Month/year range item styles |
| box.picker.separator | Year range separator dash |
| label.days | Day-of-week header text styles |
| label.month | Month label font styles |
| label.year | Year label font styles |
| button.blank | Empty calendar cell padding |
| button.day | Day button size, rounding, and transitions |
| button.select | Unselected day hover styles |
| button.today | Today highlight text styles |
| button.selected | Selected day background and text styles |
| button.helpers | Helper button (yesterday/today/tomorrow) styles |
| button.navigate | Navigation arrow button styles |
| icon.wrapper | Suffix icon flex container |
| icon.size | Calendar and clear icon dimensions |
| icon.clear | Clear icon hover color |
| icon.navigate | Navigation arrow icon color and size |
| range | Range selection between-date background |