remix/ui/combobox · DemoView Source
Combobox Overview
A searchable combobox with keyboard navigation. Try typing airport names or codes like ord, lax, or jfk.
Hartsfield-Jackson Atlanta International
Austin-Bergstrom International
Boston Logan International
Baltimore/Washington International
Ronald Reagan Washington National
Denver International
Dallas/Fort Worth International
Newark Liberty International
Daniel K. Inouye International
Washington Dulles International
John F. Kennedy International
Harry Reid International
Los Angeles International
Orlando International
Miami International
Chicago O'Hare International
Portland International
San Diego International
San Francisco International
San Jose Mineta International
Try typing `san`, `wash`, or airport codes like `ord`, `lax`, or `jfk`, then use ArrowDown and Enter.
value=null
import { css, type Handle } from 'remix/ui'
import { Combobox, ComboboxOption, onComboboxChange } from 'remix/ui/combobox'
import { theme } from 'remix/ui/theme'
export default function Example(handle: Handle) {
let value: string | null = null
return () => (
<div mix={stackCss}>
<div mix={fieldCss}>
<label for="airport-combobox" mix={labelCss}>
Airport
</label>
<Combobox
inputId="airport-combobox"
mix={[
comboboxCss,
onComboboxChange((event) => {
value = event.value
void handle.update()
}),
]}
name="airport"
placeholder="Search airports or codes"
>
{airportOptions.map((airport) => (
<ComboboxOption
key={airport.value}
disabled={airport.disabled}
label={airport.label}
searchValue={airport.searchValue}
value={airport.value}
/>
))}
</Combobox>
<div mix={helpCss}>
Try typing `san`, `wash`, or airport codes like `ord`, `lax`, or
`jfk`, then use ArrowDown and Enter.
</div>
</div>
<p mix={valueCss}>{`value=${value ?? 'null'}`}</p>
</div>
)
}
type AirportOption = {
disabled?: boolean
label: string
searchValue: string[]
value: string
}
const airportOptions: AirportOption[] = [
{
label: 'Hartsfield-Jackson Atlanta International',
searchValue: ['atl', 'atlanta', 'hartsfield-jackson atlanta international'],
value: 'ATL',
},
{
label: 'Austin-Bergstrom International',
searchValue: ['aus', 'austin', 'austin-bergstrom international'],
value: 'AUS',
},
{
label: 'Boston Logan International',
searchValue: ['bos', 'boston', 'boston logan international'],
value: 'BOS',
},
{
label: 'Baltimore/Washington International',
searchValue: [
'bwi',
'baltimore',
'washington',
'baltimore/washington international',
],
value: 'BWI',
},
{
label: 'Ronald Reagan Washington National',
searchValue: [
'dca',
'reagan',
'washington',
'ronald reagan washington national',
],
value: 'DCA',
},
{
label: 'Denver International',
searchValue: ['den', 'denver', 'denver international'],
value: 'DEN',
},
{
label: 'Dallas/Fort Worth International',
searchValue: [
'dfw',
'dallas',
'fort worth',
'dallas/fort worth international',
],
value: 'DFW',
},
{
label: 'Newark Liberty International',
searchValue: ['ewr', 'newark', 'newark liberty international'],
value: 'EWR',
},
{
label: 'Daniel K. Inouye International',
searchValue: ['hnl', 'honolulu', 'daniel k. inouye international'],
value: 'HNL',
},
{
label: 'Washington Dulles International',
searchValue: [
'iad',
'dulles',
'washington',
'washington dulles international',
],
value: 'IAD',
},
{
label: 'John F. Kennedy International',
searchValue: [
'jfk',
'kennedy',
'new york',
'john f. kennedy international',
],
value: 'JFK',
},
{
label: 'Harry Reid International',
searchValue: ['las', 'las vegas', 'harry reid international'],
value: 'LAS',
},
{
label: 'Los Angeles International',
searchValue: ['lax', 'los angeles', 'los angeles international'],
value: 'LAX',
},
{
label: 'Orlando International',
searchValue: ['mco', 'orlando', 'orlando international'],
value: 'MCO',
},
{
label: 'Miami International',
searchValue: ['mia', 'miami', 'miami international'],
value: 'MIA',
},
{
label: "Chicago O'Hare International",
searchValue: ['ord', 'ohare', 'chicago', "chicago o'hare international"],
value: 'ORD',
},
{
label: 'Portland International',
searchValue: ['pdx', 'portland', 'portland international'],
value: 'PDX',
},
{
label: 'San Diego International',
searchValue: ['san', 'san diego', 'san diego international'],
value: 'SAN',
},
{
label: 'San Francisco International',
searchValue: ['sfo', 'san francisco', 'san francisco international'],
value: 'SFO',
},
{
disabled: true,
label: 'San Jose Mineta International',
searchValue: ['sjc', 'san jose', 'san jose mineta international'],
value: 'SJC',
},
]
const comboboxCss = css({
width: '16rem',
})
const stackCss = css({
display: 'flex',
flexDirection: 'column',
gap: theme.space.sm,
width: '100%',
})
const fieldCss = css({
display: 'flex',
flexDirection: 'column',
gap: theme.space.xs,
})
const labelCss = css({
margin: 0,
fontSize: theme.fontSize.xs,
fontWeight: theme.fontWeight.semibold,
color: theme.colors.text.primary,
})
const helpCss = css({
fontSize: theme.fontSize.xs,
lineHeight: theme.lineHeight.relaxed,
color: theme.colors.text.secondary,
})
const valueCss = css({
margin: 0,
fontFamily: theme.fontFamily.mono,
fontSize: theme.fontSize.xs,
color: theme.colors.text.secondary,
})