94 lines
3.3 KiB
TypeScript
94 lines
3.3 KiB
TypeScript
'use client'
|
|
|
|
type ComboItem = { id: string; label: string }
|
|
|
|
type ComboBoxProps = {
|
|
value: string // ausgewählte ID
|
|
items: ComboItem[] // { id, label }
|
|
onSelect: (id: string) => void
|
|
}
|
|
|
|
export default function ComboBox({ value, items, onSelect }: ComboBoxProps) {
|
|
const selected = items.find(i => i.id === value)
|
|
|
|
return (
|
|
<div id="hs-combobox-basic-usage" className="relative" data-hs-combo-box="">
|
|
<div className="relative">
|
|
<input
|
|
className="py-2.5 sm:py-3 ps-4 pe-9 block w-full border-gray-200 rounded-lg sm:text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600"
|
|
type="text"
|
|
role="combobox"
|
|
aria-expanded="false"
|
|
value={selected?.label ?? ''}
|
|
data-hs-combo-box-input=""
|
|
readOnly
|
|
/>
|
|
<div
|
|
className="absolute top-1/2 end-3 -translate-y-1/2"
|
|
aria-expanded="false"
|
|
role="button"
|
|
data-hs-combo-box-toggle=""
|
|
>
|
|
<svg
|
|
className="shrink-0 size-3.5 text-gray-500 dark:text-neutral-500"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
>
|
|
<path d="m7 15 5 5 5-5" />
|
|
<path d="m7 9 5-5 5 5" />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
className="absolute z-50 w-full max-h-72 p-1 mt-1 bg-white border border-gray-200 rounded-lg overflow-y-auto dark:bg-neutral-900 dark:border-neutral-700"
|
|
style={{ display: 'none' }}
|
|
role="listbox"
|
|
data-hs-combo-box-output=""
|
|
>
|
|
{items.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className="cursor-pointer py-2 px-4 w-full text-sm text-gray-800 hover:bg-gray-100 rounded-lg focus:outline-hidden focus:bg-gray-100 dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:text-neutral-200 dark:focus:bg-neutral-800"
|
|
role="option"
|
|
tabIndex={0}
|
|
data-hs-combo-box-output-item=""
|
|
data-hs-combo-box-item-stored-data={JSON.stringify({ id: item.id, name: item.label })}
|
|
onClick={() => onSelect(item.id)}
|
|
>
|
|
<div className="flex justify-between items-center w-full">
|
|
<span
|
|
data-hs-combo-box-search-text={item.label}
|
|
data-hs-combo-box-value=""
|
|
>
|
|
{item.label}
|
|
</span>
|
|
{item.id === value && (
|
|
<span className="hidden hs-combo-box-selected:block">
|
|
<svg
|
|
className="shrink-0 size-3.5 text-blue-600 dark:text-blue-500"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M20 6 9 17l-5-5" />
|
|
</svg>
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|