From 23218431bffea8daf329677f9302df13a95da189 Mon Sep 17 00:00:00 2001 From: Andreas Reinhold / reini Date: Sun, 13 Sep 2026 09:30:26 +0200 Subject: [PATCH] Add a clear button to the date picker `clearable` empties a date, or both ends of a range, closes an open picker and hands focus back to the field, as the time picker's does. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy --- .../livewire-material-development/SKILL.md | 3 ++- resources/js/datepicker.js | 12 ++++++++++++ .../views/components/datepicker.blade.php | 17 ++++++++++++++++- .../views/showcase/sections/pickers.blade.php | 2 +- tests/Browser/DatepickerTest.php | 19 +++++++++++++++++-- tests/Feature/Components/DatepickerTest.php | 9 +++++++++ 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/resources/boost/skills/livewire-material-development/SKILL.md b/resources/boost/skills/livewire-material-development/SKILL.md index ad91e0de..60682208 100644 --- a/resources/boost/skills/livewire-material-development/SKILL.md +++ b/resources/boost/skills/livewire-material-development/SKILL.md @@ -523,7 +523,7 @@ M3 date pickers on a text field. `wire:model` stores `Y-m-d` strings (`x-model` ```blade - + ``` | Prop | Default | | @@ -534,6 +534,7 @@ M3 date pickers on a text field. `wire:model` stores `Y-m-d` strings (`x-model` | `label`, `hint`, `icon`, `variant`, `size` | | the field's | | `value` | `null` | the initial value without `wire:model` | | `name` | | adds hidden inputs with `Y-m-d` for a plain form post (`name[start]`, `name[end]` for a range) | +| `clearable` | `false` | a button that empties the field (both ends of a range) once it holds a date | Picking in the calendar is a draft; OK or Enter on a day keeps it, Cancel or Escape does not. A typed date is the value once it is whole and allowed; otherwise the field says why. Month and weekday names, the week's first day and the typed format follow `app()->getLocale()`. Keyboard: arrows, Home/End (week), PageUp/PageDown (month; with Shift, year), Space, Enter, Escape. `min` and `max` are read when the picker starts: when they change on the server, give the component a `wire:key` that changes with them. `required`, `disabled` and `readonly` reach the text field. diff --git a/resources/js/datepicker.js b/resources/js/datepicker.js index e5dc673e..992067e6 100644 --- a/resources/js/datepicker.js +++ b/resources/js/datepicker.js @@ -366,6 +366,18 @@ document.addEventListener('alpine:init', () => { } }, + /** The clear button: no date (no start and no end), closed, and focus back in the field. */ + clear() { + if (this.open) { + this.cancel(false) + } + + this.fieldError = '' + this.text = '' + this.write(null) + this.$refs.input.focus() + }, + fieldProblem(value) { if (!config.range) { return this.problem(value) diff --git a/resources/views/components/datepicker.blade.php b/resources/views/components/datepicker.blade.php index 73528da2..d13a5e39 100644 --- a/resources/views/components/datepicker.blade.php +++ b/resources/views/components/datepicker.blade.php @@ -21,7 +21,8 @@ with, and the errors for `period`, `period.start` and `period.end` all belong to this field. `min` and `max` (`Y-m-d` or a date object) disable the days outside them and keep the keyboard inside them. `label`, `hint`, `icon`, `variant` (`outlined`, `filled`) and `size` - are the field's; `name` adds hidden inputs carrying `Y-m-d` for a plain form post, and every + are the field's; `clearable` adds a button that empties it (a date, or both ends of a range) + once it holds one; `name` adds hidden inputs carrying `Y-m-d` for a plain form post, and every other attribute (`required`, `disabled`, `readonly`) reaches the text field. Errors under the `wire:model` name replace the hint, and so does a typed date that cannot be read. @@ -48,6 +49,7 @@ 'min' => null, 'max' => null, 'value' => null, + 'clearable' => false, ]) @php @@ -179,6 +181,19 @@ /> + @if ($clearable) + + @endif +