選單
選單是你的應用程式基礎的可協助自動完成和命令面板,完整支援鍵盤瀏覽。
首先,透過 npm 安裝 Headless UI
npm install @headlessui/react
組合方塊是使用 Combobox
、ComboboxInput
、ComboboxButton
、ComboboxOptions
和 ComboboxOption
元件建立的。
您完全控制您過濾結果的方式,可能是透過一個模糊搜尋函式庫在用戶端過濾,或透過建立伺服器端要求到 API 中過濾。為了示範目的,我們會讓這個範例的邏輯保持簡單。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
Headless UI 追蹤每個元件的很多狀態,例如目前選取哪個組合方塊選項、快顯視窗是否開啟或關閉、或目前使用鍵盤聚焦在選單中的哪個項目。
但由於元件是沒有頭的且完全沒有樣式,在您自己提供每個狀態您想要的樣式之前,您在使用者介面中看不到這些資訊。
要設定 Headless UI 元件不同狀態樣式的最簡單的方式,是使用每個元件公開的 data-*
屬性。
例如,ComboboxOption
元件公開 data-focus
屬性告訴您選項目前是否透過滑鼠或鍵盤聚焦,以及 data-selected
屬性告訴您該選項是否符合 Combobox
目前的 value
。
<!-- Rendered `ComboboxOptions` -->
<div data-open>
<div>Wade Cooper</div>
<div data-focus data-selected>Arlene Mccoy</div>
<div>Devon Webb</div>
</div>
使用 CSS 屬性選擇器 根據這些資料屬性的存在有條件地套用樣式。如果您使用 Tailwind CSS,資料屬性修改器 會讓這變得容易許多
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { CheckIcon } from '@heroicons/react/20/solid'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="group flex gap-2 bg-white data-[focus]:bg-blue-100"> <CheckIcon className="invisible size-5 group-data-[selected]:visible" /> {person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
請見 元件 API 來取得所有可用資料屬性的清單。
每個元件也透過 渲染道具 公開其目前狀態的資訊,您可以用它有條件地套用不同的樣式或渲染不同的內容。
例如,ComboboxOption
元件公開 focus
狀態,告訴您選項目前是否透過滑鼠或鍵盤聚焦,以及一個 selected
狀態,告訴您該選項是否符合 Combobox
目前的 value
。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { CheckIcon } from '@heroicons/react/20/solid'
import clsx from 'clsx'
import { Fragment, useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption as={Fragment} key={person.id} value={person} className="data-[focus]:bg-blue-100"> {({ focus, selected }) => ( <div className={clsx('group flex gap-2', focus && 'bg-blue-100')}> {selected && <CheckIcon className="size-5" />} {person.name} </div> )} </ComboboxOption> ))}
</ComboboxOptions>
</Combobox>
)
}
請見 元件 API 來取得所有可用渲染道具的清單。
以 Field
元件包裹 Label
和 Combobox
,使用自動產生的 ID 自動將它們關聯起來
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Field, Label } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Field> <Label>Assignee:</Label> <Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput displayValue={(person) => person?.name} onChange={(event) => setQuery(event.target.value)} />
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
</Field> )
}
在 Field
元件中使用 Description
元件,使用 aria-describedby
屬性將其自動與 Combobox
相關聯
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Description, Field, Label } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Field> <Label>Assignee:</Label>
<Description>This person will have full access to this project.</Description> <Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput displayValue={(person) => person?.name} onChange={(event) => setQuery(event.target.value)} />
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
</Field> )
}
將 disabled
屬性新增至 Field
元件,以停用 Combobox
及其關聯的 Label
和 Description
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Field, Label } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Field disabled> <Label>Assignee:</Label>
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput displayValue={(person) => person?.name} onChange={(event) => setQuery(event.target.value)} />
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
</Field>
)
}
您也可以在 Field
外部停用下拉式選單,方法是將 disabled 屬性直接新增至 Combobox
本身。
使用 disabled
屬性停用 ComboboxOption
,並防止選取它
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds', available: true },
{ id: 2, name: 'Kenton Towne', available: true },
{ id: 3, name: 'Therese Wunsch', available: true },
{ id: 4, name: 'Benedict Kessler', available: false }, { id: 5, name: 'Katelyn Rohan', available: true },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption
key={person.id}
value={person}
disabled={!person.available} className="data-[focus]:bg-blue-100 data-[disabled]:opacity-50" >
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
您可以根據 query
值包含動態 ComboboxOption
,允許使用者輸入清單中不存在的自訂值。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{query.length > 0 && ( <ComboboxOption value={{ id: null, name: query }} className="data-[focus]:bg-blue-100"> Create <span className="font-bold">"{query}"</span> </ComboboxOption> )} {filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
如果您新增 name
屬性至您的 Combobox
,將會產生隱藏的 input
元素,並與下拉式選單狀態保持同步。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<form action="/projects/1/assignee" method="post">
<Combobox name="assignee" value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
<button>Submit</button>
</form>
)
}
這使您可以在原生 HTML <form>
內使用下拉式選單,並進行傳統的表單提交,就像您的下拉式選單是原生 HTML 表單控制項一樣。
基本值(例如字串)將產生包含該值的單一隱藏式輸入,但複雜值(例如物件)會使用中括號表示法針對名稱編碼成多個輸入
<!-- Rendered hidden inputs -->
<input type="hidden" name="assignee[id]" value="1" />
<input type="hidden" name="assignee[name]" value="Durward Reynolds" />
如果你省略 value
道具,Headless UI 會內部追蹤其狀態,允許你使用它作為一個 非受控元件。
在非受控時,使用 defaultValue
道具以提供初始值給 Combobox
。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<form action="/projects/1/assignee" method="post">
<Combobox name="assignee" defaultValue={people[0]} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
<button>Submit</button>
</form>
)
}
這可以在使用結合框時簡化你的程式碼 使用 HTML 表單 或使用透過 FormData 收集其狀態的表單 API,而不是使用 React 狀態來追蹤它。
如果你需要執行任何副作用,你提供的任何 onChange
道具仍會在元件的值變動時被呼叫,但你不必使用它自己追蹤元件狀態。
加入 anchor
道具到 ComboboxOptions
以讓下拉式選單自動相對於 ComboboxInput
定位
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom start" className="border empty:invisible"> {filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
使用值 top
、right
、bottom
或 left
來讓下拉式選單沿著對應邊緣置中,或將它與 start
或 end
結合使用以將下拉式選單對齊到特定角落,例如 top start
或 bottom end
。
若要控制輸入與下拉式選單之間的間隙,請使用 --anchor-gap
CSS 變數
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom start"
className="border [--anchor-gap:4px] empty:invisible sm:[--anchor-gap:8px]"
>
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
此外,你可以使用 --anchor-offset
控制下拉式選單應該從其原始位置輕推的距離,以及 --anchor-padding
控制下拉式選單和視窗之間應該存在的最小空間。
anchor
道具也支援一個物件 API,允許你使用 JavaScript 控制 gap
、offset
和 padding
值
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor={{ to: 'bottom start', gap: '4px' }} className="border empty:invisible"> {filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
請參閱 ComboboxOptions API 以取得更多關於這些選項的資訊。
ComboboxOptions
下拉式選單預設沒有設定寬度,但你可以使用 CSS 新增一個
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="w-52 border empty:invisible"> {filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
如果你想要下拉式選單寬度與 ComboboxInput
或 ComboboxButton
寬度匹配,請使用 --input-width
和 --button-width
CSS 變數,它們在 ComboboxOptions
元素上公開
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="w-[var(--input-width)] border empty:invisible"> {filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
若要動畫化開合組合框面板,請加入 transition
道具到 ComboboxOptions
元件,然後使用 CSS 來設定轉場的不同階段
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions
anchor="bottom"
transition className="origin-top border transition duration-200 ease-out empty:invisible data-[closed]:scale-95 data-[closed]:opacity-0" >
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
在內部,transition
道具是以與 Transition
元件完全相同的方式實作。請參閱 轉場文件 以進一步了解。
Headless UI 搭配 React 生態系中的其他動畫函式庫,例如 Framer Motion 及 React Spring,效果也很好。您只需要向這些函式庫公開一些狀態。
例如,若要使用 Framer Motion 對組合方塊進行動畫處理,請將 static
屬性新增到 ComboboxOptions
元件,然後根據 open
渲染屬性來有條件地呈現。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { AnimatePresence, motion } from 'framer-motion'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson}>
{({ open }) => ( <>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<AnimatePresence>
{open && ( <ComboboxOptions
static as={motion.div}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
anchor="bottom"
className="origin-top border empty:invisible"
onAnimationComplete={() => setQuery('')}
>
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
)} </AnimatePresence>
</>
)} </Combobox>
)
}
與僅允許您提供字串作為值的原生 HTML 表單控制項不同,Headless UI 也支援繫結複雜物件。
繫結物件時,請務必在 ComboboxInput
上設定 displayValue
,以便可以在輸入中呈現已選取選項的字串表示。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [ { id: 1, name: 'Durward Reynolds' }, { id: 2, name: 'Kenton Towne' }, { id: 3, name: 'Therese Wunsch' }, { id: 4, name: 'Benedict Kessler' }, { id: 5, name: 'Katelyn Rohan' },]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name} onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name} </ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
將物件繫結為值時, важно 從 Combobox
的 value
及對應的 ComboboxOption
,務必使用同一個物件的 相同執行個體,否則這些執行個體將無法相等並導致組合方塊行為不正確。
若要簡化使用同一個物件的不同執行個體,您可以使用 by
屬性來根據特定欄位比較物件,而不是比較物件身分。
當您將物件傳遞給 value
屬性時,by
預設是 id
(存在時),但您可以設定為您想要的欄位
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const departments = [
{ name: 'Marketing', contact: 'Durward Reynolds' },
{ name: 'HR', contact: 'Kenton Towne' },
{ name: 'Sales', contact: 'Therese Wunsch' },
{ name: 'Finance', contact: 'Benedict Kessler' },
{ name: 'Customer service', contact: 'Katelyn Rohan' },
]
function DepartmentPicker({ selectedDepartment, onChange }) { const [query, setQuery] = useState('')
const filteredDepartments =
query === ''
? departments
: departments.filter((department) => {
return department.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedDepartment} by="name" onChange={onChange} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Department"
displayValue={(department) => department?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredDepartments.map((department) => (
<ComboboxOption key={department.id} value={department} className="data-[focus]:bg-blue-100">
{department.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
如果希望完全控制比較物件的方式,也可以將您自己的比較函式傳遞給 by
屬性
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const departments = [
{ id: 1, name: 'Marketing', contact: 'Durward Reynolds' },
{ id: 2, name: 'HR', contact: 'Kenton Towne' },
{ id: 3, name: 'Sales', contact: 'Therese Wunsch' },
{ id: 4, name: 'Finance', contact: 'Benedict Kessler' },
{ id: 5, name: 'Customer service', contact: 'Katelyn Rohan' },
]
function compareDepartments(a, b) { return a.name.toLowerCase() === b.name.toLowerCase()}
function DepartmentPicker({ selectedDepartment, onChange }) {
const [query, setQuery] = useState('')
const filteredDepartments =
query === ''
? departments
: departments.filter((department) => {
return department.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedDepartment} by={compareDepartments} onChange={onChange} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Department"
displayValue={(department) => department?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredDepartments.map((department) => (
<ComboboxOption key={department.id} value={department} className="data-[focus]:bg-blue-100">
{department.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
儘管 將物件繫結為值 很常見,但您也可以提供簡單的字串值。
這樣做時,您可以省略 ComboboxInput
的 displayValue
屬性。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = ['Durward Reynolds', 'Kenton Towne', 'Therese Wunsch', 'Benedict Kessler', 'Katelyn Rohan']
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput aria-label="Assignee" onChange={(event) => setQuery(event.target.value)} />
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person} value={person} className="data-[focus]:bg-blue-100"> {person} </ComboboxOption> ))}
</ComboboxOptions>
</Combobox>
)
}
若要允許在組合方塊中選取多個值,請使用 multiple
屬性,並將陣列傳遞給 value
,而不是單一選項。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPeople, setSelectedPeople] = useState([people[0], people[1]]) const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox multiple value={selectedPeople} onChange={setSelectedPeople} onClose={() => setQuery('')}> {selectedPeople.length > 0 && (
<ul>
{selectedPeople.map((person) => (
<li key={person.id}>{person.name}</li>
))}
</ul>
)}
<ComboboxInput aria-label="Assignees" onChange={(event) => setQuery(event.target.value)} />
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
每次新增或移除選項時,您的 onChange
處理常式會呼叫陣列,陣列中包含所有已選取的選項。
使用 立即
屬性以在組合方塊輸入獲得焦點時立即開啟組合方塊選項。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox immediate value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
預設情況下,組合方塊
及其子元件各呈現適合該元件的預設元素。
例如,組合方塊輸入
呈現 輸入
、組合方塊按鈕
呈現 按鈕
、組合方塊選項
呈現 div
,而 組合方塊選項
呈現 div
。相反,組合方塊
不呈現元素,而是直接呈現其子元素。
使用 作為
屬性以將元件呈現為不同元素或您自己的自訂元件,確保您的自訂元件 將參考傳送出去,以便 Headless UI 就能正確建立連結。
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { forwardRef, useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
let MyCustomButton = forwardRef(function (props, ref) { return <button className="..." ref={ref} {...props} />})
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}> <ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxButton as={MyCustomButton}>Open</ComboboxButton>
<ComboboxOptions as="ul" anchor="bottom" className="border empty:invisible"> {filteredPeople.map((person) => (
<ComboboxOption as="li" key={person.id} value={person} className="data-[focus]:bg-blue-100"> {person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
若要讓元素直接呈現其子元素而沒有包裝元素,請使用 片段
。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { Fragment, useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
as={Fragment} aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
>
<input />
</ComboboxInput>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
根據您所建立的內容,有時將 組合方塊選項
以外的額外資訊呈現為主動選項是有意義的。例如,在命令面板中預覽主動選項。在這些情況下,您可以讀取 主動選項
呈現屬性引數來存取此資訊。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
{({ activeOption }) => ( <>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
{activeOption && <div>The currently focused user is: {activeOption.name}</div>} </>
)}
</Combobox>
)
}
主動選項
將成為目前有焦點 組合方塊選項
的 值
。
預設情況下,組合方塊
會將其所有選項呈現到 DOM 中。雖然這是一個良好的預設設定,但在選項數量非常多時,這可能會導致效能問題。針對這些情況,我們提供了虛擬捲動 API。
若要啟用虛擬捲動,請透過 虛擬.選項
屬性提供選項清單給 組合方塊
,並提供 組合方塊選項
呈現屬性,作為每個選項的範本。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
// +1000 more people
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox
value={selectedPerson}
virtual={{ options: filteredPeople }} onChange={setSelectedPerson}
onClose={() => setQuery('')}
>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="w-[var(--input-width)] border empty:invisible">
{({ option: person }) => ( <ComboboxOption value={person} className="data-[focus]:bg-blue-100"> {person.name} </ComboboxOption> )} </ComboboxOptions>
</Combobox>
)
}
若要指定給定的選項是否已停用,請提供回呼至 虛擬.停用
屬性。
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds', available: true },
{ id: 2, name: 'Kenton Towne', available: true },
{ id: 3, name: 'Therese Wunsch', available: true },
{ id: 4, name: 'Benedict Kessler', available: false }, { id: 5, name: 'Katelyn Rohan', available: true },
// +1000 more people
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox
value={selectedPerson}
virtual={{
options: filteredPeople,
disabled: (person) => !person.available, }}
onChange={setSelectedPerson}
onClose={() => setQuery('')}
>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="w-[var(--input-width)] border empty:invisible">
{({ option: person }) => (
<ComboboxOption value={person} className="data-[focus]:bg-blue-100 data-[disabled]:opacity-50"> {person.name}
</ComboboxOption>
)}
</ComboboxOptions>
</Combobox>
)
}
鍵盤互動
指令 | 說明 |
向下箭頭、或向上箭頭當 | 開啟下拉式選單並將焦點移至選取的項目 |
Enter、空白鍵、向下箭頭、或向上箭頭當 | 開啟下拉式選單,將焦點移至輸入並選取選取的項目 |
Esc當下拉式選單開啟時 | 關閉下拉式選單並恢復在輸入欄位中的選取項目 |
向下箭頭或向上箭頭當下拉式選單開啟時 | 將焦點移至上一個/下一個已啟用的項目 |
首頁或PgUp當下拉式選單開啟時 | 將焦點移至第一個已啟用的項目 |
尾頁或PgDn當下拉式選單開啟時 | 將焦點移至最後一個已啟用的項目 |
Enter當下拉式選單開啟時 | 選取目前項目 |
Enter當下拉式選單關閉且在表單中時 | 提交表單 |
Tab當組合方塊開啟時 | 選取當前焦點的項目並關閉組合方塊 |
A–Z 或 a–z當組合方塊開啟時 | 呼叫 |
prop | 預設值 | 說明 |
as | 片段 | 字串 | 元件 組配方塊應該呈現地或元件。解組合方塊呈現在這個設定的 |
disabled | false | 布林 使用這個設定來停用整個組合方塊元件 & 相關的子元件。 |
value | — | T 選取的值。 |
defaultValue | — | T 當使用為非受控元件時的預設值。 |
by | — | keyof T | ((a: T, z: T) => 布林) 使用這個設定來比較特定欄位的物件,或是傳遞你自己的比較函式來完全控制比較物件的方式。 當你傳遞物件給 |
onChange | — | (value: T) => 無 當選取新的選項時呼叫的函式。 |
onClose | — | () => 無 當下拉式選單關閉時呼叫的函式。 |
multiple | false | 布林 是否可以選取多個選項 |
name | — | 字串 用於組合方塊在表單內使用 |
form | — | 字串 屬於組合方塊的表單 ID 如果提供 |
immediate | false | 布林 組合方塊輸入被設定焦點時,組合方塊是否應該立刻開啟選項。 |
virtual | null | 物件 設定虛擬捲動。 |
virtual.options | — | 陣列 在虛擬捲動模式時顯示的選項集合。 |
virtual.disabled | null | (value: T) => 布林 在虛擬捲動模式時用來決定給定選項是否已停用的回呼。 |
資料屬性 | 呈現 Prop | 說明 |
— | value |
選取的值。 |
data-open | open |
是否組合方塊已開啟. |
— | activeOption |
有焦點的選項,或 |
data-disabled | disabled |
是否組合方塊已停用。 |
— | activeIndex |
聚焦的選項索引,如果沒有焦點則為 |
prop | 預設值 | 說明 |
as | 輸入 | 字串 | 元件 組配方塊應該呈現地或元件。解combobox 輸入內容呈現在這個設定的 |
顯示值 | — | (項目: T) => 字串
|
onChange | — | (事件: Event) => void 在輸入值變更時要呼叫的函式。 |
自動對焦 | false | 布林 是否combobox 輸入內容首次呈現時應收到焦點。 |
資料屬性 | 呈現 Prop | 說明 |
data-open | open |
是否組合方塊已開啟. |
data-disabled | disabled |
是否組合方塊已停用。 |
data-焦點 | 焦點 |
是否combobox 輸入內容已聚焦。 |
data-懸停 | 懸停 |
是否combobox 輸入內容已懸停。 |
data-自動對焦 | 自動對焦 |
|
prop | 預設值 | 說明 |
as | 按鈕 | 字串 | 元件 組配方塊應該呈現地或元件。解combobox 按鈕呈現在這個設定的 |
自動對焦 | false | 布林 是否combobox 按鈕首次呈現時應收到焦點。 |
資料屬性 | 呈現 Prop | 說明 |
— | value |
選取的值。 |
data-open | open |
是否組合方塊已開啟. |
data-disabled | disabled |
是否combobox 按鈕已停用。 |
data-焦點 | 焦點 |
是否combobox 按鈕已聚焦。 |
data-懸停 | 懸停 |
是否combobox 按鈕已懸停。 |
data-活動 | 活動 |
是否combobox 按鈕處於活動或按下的狀態。 |
prop | 預設值 | 說明 |
as | div | 字串 | 元件 組配方塊應該呈現地或元件。解combobox 選項呈現在這個設定的 |
過渡 | false | 布林 元素是否應呈現過渡屬性,例如 |
定位點 | — | 物件 設定下拉選單固定在輸入內容的方式。 |
anchor.to | 底部 | 字串 放置combobox 選項相對於觸發器。 使用值 |
anchor.gap | 0 | 數字 | 字串 之間的間距combobox 輸入內容和combobox 選項. 也可以使用 |
anchor.offset | 0 | 數字 | 字串 距離combobox 選項應從其原始位置略微調整。 也可以使用 |
anchor.padding | 0 | 數字 | 字串 之間的最小空間combobox 選項和視窗。 也可以使用 |
靜態 | false | 布林 元素是否應略過內部管理的開啟/關閉狀態。 |
解除安裝 | true | 布林 元素是否應根據開啟/關閉狀態解除安裝或隱藏。 |
入口 | false | 布林 元素是否應在入口中呈現。 當設定 |
模式 | true | 布林 是否啟用輔助功能,例如捲動鎖定、焦點捕捉,以及使其他元素 |
資料屬性 | 呈現 Prop | 說明 |
data-open | open |
是否組合方塊已開啟. |
prop | 預設值 | 說明 |
as | div | 字串 | 元件 組配方塊應該呈現地或元件。解combobox 選項呈現在這個設定的 |
value | — | T 選項值。 |
disabled | false | 布林 是否combobox 選項已禁用用於鍵盤導覽和 ARIA 用途. |
順序 | — | 數字 選項在選項清單中的順序,用於效能改善。 使用虛擬捲動時無關緊要。 |
資料屬性 | 呈現 Prop | 說明 |
data-已選取 | 已選取 |
是否combobox 選項已被選取。 |
data-disabled | disabled |
是否combobox 選項已停用。 |
data-焦點 | 焦點 |
是否combobox 選項已聚焦。 |
如果您有興趣使用預先設計的 Tailwind CSS Combobox 組件範例使用 Headless UI,請查看 Tailwind UI — 由我們建立的精選美觀設計和精心製作的組件。
對於像這樣開源專案,這是支持我們工作的絕佳方式,並使我們能夠改善這些開源專案與持續維護。