Combobox WIP
A searchable dropdown built from a text input and the native Popover API. CSS handles all visual presentation; a small inline script filters the list and wires up selection.
Each anchor-name must be unique per combobox on the page.
Set it via an inline style and reference the same value as
position-anchor on the popover.
Default
<div class="combobox">
<input
type="search"
placeholder="Search fruits..."
style="anchor-name: --my-combobox"
onfocus="
setTimeout(
() =>
!this.nextElementSibling.matches(':popover-open') &&
this.nextElementSibling.showPopover(),
)
"
oninput="
this.nextElementSibling
.querySelectorAll('li')
.forEach(
(li) =>
(li.hidden = !li.textContent
.toLowerCase()
.includes(this.value.toLowerCase())),
)
"
/>
<div
popover
style="position-anchor: --my-combobox"
onpointerdown="const b=event.target.closest('button');if(b){event.preventDefault();this.previousElementSibling.value=b.textContent.trim();setTimeout(()=>this.hidePopover())}"
>
<menu>
<li><button class="ghost">Apple</button></li>
<li><button class="ghost">Banana</button></li>
<li><button class="ghost">Cherry</button></li>
<li><button class="ghost">Mango</button></li>
<li><button class="ghost">Pineapple</button></li>
</menu>
</div>
</div>
In a field
Wrap with a <label> to attach a visible label.
<label>
Favourite fruit
<div class="combobox">
<input
type="search"
placeholder="Search..."
style="anchor-name: --my-combobox"
onfocus="
setTimeout(
() =>
!this.nextElementSibling.matches(':popover-open') &&
this.nextElementSibling.showPopover(),
)
"
oninput="
this.nextElementSibling
.querySelectorAll('li')
.forEach(
(li) =>
(li.hidden = !li.textContent
.toLowerCase()
.includes(this.value.toLowerCase())),
)
"
/>
<div
popover
style="position-anchor: --my-combobox"
onpointerdown="const b=event.target.closest('button');if(b){event.preventDefault();this.previousElementSibling.value=b.textContent.trim();setTimeout(()=>this.hidePopover())}"
>
<menu>
<li><button class="ghost">Apple</button></li>
<li><button class="ghost">Banana</button></li>
<li><button class="ghost">Cherry</button></li>
</menu>
</div>
</div>
</label>