Added
-
SearchableSelectacceptsclearable(plusclear-labelfor the ✕'s
accessible name, default "Clear selection"). While something is selected, an
✕ appears between the label and the chevron; pressing it emits
update:modelValuewith''and hands focus back to the trigger.Without it the control is a trap for OPTIONAL values: it picks from a closed
set and only ever emitsoption.value, so once anything is picked there is
no gesture that returns to "nothing chosen". The consuming app hit this on
its data-source form — the store-dialog field is nullable all the way down
('nullable'in the FormRequest,?? nullon submit), but a user who
selected a dialog could never unselect it short of reloading the page. Its
sibling controls both already had an exit: the nativeSelectrenders a
selectable placeholder<option value="">, andComboboxis free text that
can be erased. This closes the gap for the third sibling;requiredfields
simply don't pass the prop.Two deliberate choices, so call sites don't pay for what they don't use:
- Clearing emits
'', notnull— the same "nothing chosen" payload
the nativeSelectproduces when its placeholder is picked. Emitting
nullwould widen the payload type toT | nullfor every consumer,
forcing null-handling onto the majority of call sites whose select is not
clearable and can never receive it. (For aT = stringsite,T | ''
collapses tostring: existing handlers type-check unchanged.) - The ✕ is a sibling of the trigger, not a child — the trigger is
itself a<button>, and a button inside a button is invalid HTML that
browsers "repair" by splitting the elements apart. It is absolutely
positioned into the trigger's right end at the control's full height, and
only rendered while a selected option's label is actually on screen (a
modelValuewhose options have not arrived yet shows the placeholder, and
there is nothing visible to clear).
The
Clearablestory pins the loop: clear → model'', placeholder back,
menu closed, focus on the trigger, ✕ gone; re-pick → ✕ back. - Clearing emits