Files
sign/packages/ui/primitives/combobox.tsx

82 lines
2.2 KiB
TypeScript
Raw Normal View History

2023-09-29 17:12:02 +01:00
import * as React from 'react';
2025-01-02 15:33:37 +11:00
import { msg } from '@lingui/core/macro';
2024-08-27 20:34:39 +09:00
import { useLingui } from '@lingui/react';
2025-01-02 15:33:37 +11:00
import { Trans } from '@lingui/react/macro';
import { Check, ChevronDown } from 'lucide-react';
import { cn } from '../lib/utils';
import { Button } from './button';
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from './command';
import { Popover, PopoverContent, PopoverTrigger } from './popover';
2023-09-29 17:12:02 +01:00
type ComboboxProps = {
className?: string;
options: string[];
value: string | null;
onChange: (_value: string | null) => void;
placeholder?: string;
disabled?: boolean;
2023-09-29 17:12:02 +01:00
};
const Combobox = ({
className,
options,
value,
onChange,
disabled = false,
placeholder,
}: ComboboxProps) => {
2024-08-27 20:34:39 +09:00
const { _ } = useLingui();
2023-09-29 17:12:02 +01:00
const [open, setOpen] = React.useState(false);
const onOptionSelected = (newValue: string) => {
onChange(newValue === value ? null : newValue);
2023-09-29 17:12:02 +01:00
setOpen(false);
};
2024-08-27 20:34:39 +09:00
const placeholderValue = placeholder ?? _(msg`Select an option`);
2023-09-29 17:12:02 +01:00
return (
2023-10-11 12:32:33 +03:00
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className={cn('my-2 w-full justify-between', className)}
disabled={disabled}
2023-10-11 12:32:33 +03:00
>
{value ? value : placeholderValue}
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
2023-10-11 12:32:33 +03:00
</Button>
</PopoverTrigger>
<PopoverContent className="p-0" side="bottom" align="start">
2023-10-11 12:32:33 +03:00
<Command>
<CommandInput placeholder={value || placeholderValue} />
2024-08-27 20:34:39 +09:00
<CommandEmpty>
<Trans>No value found.</Trans>
</CommandEmpty>
<CommandGroup className="max-h-[250px] overflow-y-auto">
{options.map((option, index) => (
<CommandItem key={index} onSelect={() => onOptionSelected(option)}>
2023-10-11 12:32:33 +03:00
<Check
className={cn('mr-2 h-4 w-4', option === value ? 'opacity-100' : 'opacity-0')}
2023-10-11 12:32:33 +03:00
/>
{option}
2023-10-11 12:32:33 +03:00
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
2023-09-29 17:12:02 +01:00
);
};
export { Combobox };