Fix combobox docs HTML and add screenshots pages

Replace the emails in the avatar example with roles so the rendered HTML has
no link inside a button, fix the related dropdown link, and add two
screenshots pages for the combobox.
This commit is contained in:
Bartek committed 2026-09-29 14:21:34 +02:00
1 parent 23b75168a3
commit 61593efe40
3 files changed
+140 -6

No files matched your search

+6 -6
View File
@@ -4,7 +4,7 @@ seoTitle: Combobox select
order: 14
summary: A select-like field built from a toggle button and a dropdown menu, with custom item content, live search and multiple selection.
description: Add a customizable combobox (select replacement) with search, multiple selection, rich items, form submission and full keyboard support.
related: [/ui/forms/elements, /ui/components/dropdowns, /ui/forms/validation]
related: [/ui/forms/elements, /ui/components/dropdown, /ui/forms/validation]
source: core/scss/ui/forms/_combobox.scss
css-vars: combobox
css-plugins: [flags, payments]
@@ -486,7 +486,7 @@ Show the person next to the name.
</div>
</Example>
Add a name and an email with `.dropdown-item-content` and `.dropdown-item-description`.
Add a name and a role with `.dropdown-item-content` and `.dropdown-item-description`.
<Example column overflow="visible">
<div class="w-100">
@@ -498,7 +498,7 @@ Add a name and an email with `.dropdown-item-content` and `.dropdown-item-descri
<span class="dropdown-item-indicator"><span class="avatar avatar-xs" style="background-image: url(/static/avatars/000m.jpg)"></span></span>
<span class="dropdown-item-content">
<span>Paweł Kuna</span>
<small class="dropdown-item-description">pawel@example.com</small>
<small class="dropdown-item-description">Product designer</small>
</span>
<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>
</button>
@@ -506,7 +506,7 @@ Add a name and an email with `.dropdown-item-content` and `.dropdown-item-descri
<span class="dropdown-item-indicator"><span class="avatar avatar-xs" style="background-image: url(/static/avatars/001f.jpg)"></span></span>
<span class="dropdown-item-content">
<span>Jeffie Lewzey</span>
<small class="dropdown-item-description">jeffie@example.com</small>
<small class="dropdown-item-description">Front-end developer</small>
</span>
<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>
</button>
@@ -514,7 +514,7 @@ Add a name and an email with `.dropdown-item-content` and `.dropdown-item-descri
<span class="dropdown-item-indicator"><span class="avatar avatar-xs" style="background-image: url(/static/avatars/002m.jpg)"></span></span>
<span class="dropdown-item-content">
<span>Mallory Hulme</span>
<small class="dropdown-item-description">mallory@example.com</small>
<small class="dropdown-item-description">Project manager</small>
</span>
<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>
</button>
@@ -522,7 +522,7 @@ Add a name and an email with `.dropdown-item-content` and `.dropdown-item-descri
<span class="dropdown-item-indicator"><span class="avatar avatar-xs" style="background-image: url(/static/avatars/003f.jpg)"></span></span>
<span class="dropdown-item-content">
<span>Dunn Slane</span>
<small class="dropdown-item-description">dunn@example.com</small>
<small class="dropdown-item-description">QA engineer</small>
</span>
<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>
</button>
+46
View File
@@ -0,0 +1,46 @@
---
// A single combobox field on its own, open: a country picker with a flag next
// to every name. The capture never clicks, so the open state is written into
// the markup (`show` on the toggle and the menu); the menu sits right under the
// field. Poland is already chosen; Spain is drawn in its hover state, with the fake cursor on it.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import FormGroup from '@ui/FormGroup.astro'
const countries: [string, string][] = [
['us', 'United States'],
['gb', 'United Kingdom'],
['de', 'Germany'],
['fr', 'France'],
['pl', 'Poland'],
['es', 'Spain'],
['jp', 'Japan'],
]
const check = '<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>'
---
<ScreenshotLayout title="Combobox field" columns={1.5} zoom={1.4} cssPlugins={['flags']}>
<FormGroup label="Country" for="shot-country" class="mb-0">
<div class="position-relative" style="padding-bottom: 290px">
<button class="form-select combobox-toggle show" type="button" id="shot-country" data-bs-toggle="combobox" data-bs-placeholder="Pick a country">
<span class="combobox-value"></span>
</button>
<div class="dropdown-menu show w-100">
<div class="combobox-search">
<input type="text" class="form-control combobox-search-input" placeholder="Search…" autocomplete="off" aria-label="Search countries" />
</div>
{
countries.map(([code, name]) => (
<button class:list={['dropdown-item', 'position-relative', code === 'pl' && 'selected']} type="button" data-bs-value={code} aria-selected={code === 'pl' ? 'true' : undefined} style={code === 'es' ? 'background-color: var(--tblr-dropdown-link-hover-bg)' : undefined}>
<span class="dropdown-item-indicator">
<span class={`flag flag-xs flag-country-${code}`} />
</span>
<span class="dropdown-item-label">{name}</span>
<Fragment set:html={check} />
{code === 'es' && <span class="cursor" style="top: 60%; left: 40%" />}
</button>
))
}
</div>
</div>
</FormGroup>
</ScreenshotLayout>
+88
View File
@@ -0,0 +1,88 @@
---
// Combobox in context: the "New task" form of an issue tracker, with the
// assignee field open. The capture never clicks, so the open state is written
// into the markup (`show` on the toggle and the menu); the menu sits right
// under the field and covers the next one, like the real thing. The menu holds
// avatars with a name and a role, a search field and a check on the person
// who is already chosen. The fake cursor points at the next person.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import Card from '@ui/Card.astro'
import CardBody from '@ui/CardBody.astro'
import CardTitle from '@ui/CardTitle.astro'
import CardSubtitle from '@ui/CardSubtitle.astro'
import FormGroup from '@ui/FormGroup.astro'
import Avatar from '@ui/Avatar.astro'
import { personById } from '@shared/lib/people'
const team = [1, 4, 2, 6].map((id) => personById(id))
const labels = ['Bug', 'Backend', 'Urgent', 'Design', 'Docs']
const check = '<svg xmlns="http://www.w3.org/2000/svg" class="dropdown-item-check icon icon-2" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5l10 -10" /></svg>'
---
<ScreenshotLayout title="Combobox" columns={2}>
<Card>
<CardBody class="p-4 pb-6">
<CardTitle>New task</CardTitle>
<CardSubtitle>Pick who works on it. Search by name, or use the arrow keys.</CardSubtitle>
<FormGroup label="Title" for="shot-task-title" class="mb-3">
<input type="text" id="shot-task-title" class="form-control" value="Fix the broken password reset link" readonly />
</FormGroup>
<div class="mb-3">
<label class="form-label" for="shot-task-labels">Labels</label>
<select class="form-select" id="shot-task-labels" multiple data-bs-toggle="combobox" data-placeholder="Add labels">
{
labels.map((label, index) => (
<option value={label.toLowerCase()} selected={index < 3}>
{label}
</option>
))
}
</select>
</div>
<div class="mb-3">
<label class="form-label" id="shot-assignee-label">Assignee</label>
<div class="position-relative">
<button class="form-select combobox-toggle show" type="button" data-bs-toggle="combobox" data-bs-placeholder="Assign to…" aria-labelledby="shot-assignee-label">
<span class="combobox-value"></span>
</button>
<div class="dropdown-menu show w-100">
<div class="combobox-search">
<input type="text" class="form-control combobox-search-input" placeholder="Search…" autocomplete="off" aria-label="Search people" />
</div>
{
team.map((person, index) => (
<button class:list={['dropdown-item', 'position-relative', index === 0 && 'selected']} type="button" data-bs-value={String(person?.id)} aria-selected={index === 0 ? 'true' : undefined}>
<span class="dropdown-item-indicator">
<Avatar size="xs" person={person} />
</span>
<span class="dropdown-item-content">
<span>{person?.full_name}</span>
<small class="dropdown-item-description">{person?.job_title}</small>
</span>
<Fragment set:html={check} />
{index === 2 && <span class="cursor" style="top: 60%; left: 50%" />}
</button>
))
}
</div>
</div>
</div>
<FormGroup label="Due date" for="shot-task-due" class="mb-3">
<input type="text" id="shot-task-due" class="form-control" value="Friday, October 2" readonly />
</FormGroup>
<FormGroup label="Estimate" for="shot-task-estimate" class="mb-5">
<input type="text" id="shot-task-estimate" class="form-control" value="3 days" readonly />
</FormGroup>
<div class="d-flex justify-content-end gap-2">
<button type="button" class="btn">Cancel</button>
<button type="button" class="btn btn-primary">Create task</button>
</div>
</CardBody>
</Card>
</ScreenshotLayout>