Filtro funcionando primera versión
This commit is contained in:
@@ -2,28 +2,38 @@ import { SearchIcon } from 'lucide-react'
|
||||
import { useId } from 'react'
|
||||
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
|
||||
const InputSearchIconDemo = () => {
|
||||
type Props = {
|
||||
value: string
|
||||
onChange: (value: string) => void
|
||||
placeholder?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const BarraBusqueda: React.FC<Props> = ({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = 'Buscar…',
|
||||
className,
|
||||
}) => {
|
||||
const id = useId()
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-xs space-y-2">
|
||||
<Label htmlFor={id}>Search input with icon and button</Label>
|
||||
<div className="relative">
|
||||
<div className="text-muted-foreground pointer-events-none absolute inset-y-0 left-0 flex items-center justify-center pl-3 peer-disabled:opacity-50">
|
||||
<SearchIcon className="size-4" />
|
||||
<span className="sr-only">Search</span>
|
||||
</div>
|
||||
<Input
|
||||
id={id}
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="peer px-9 [&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none"
|
||||
/>
|
||||
<div className={['relative', className].filter(Boolean).join(' ')}>
|
||||
<div className="text-muted-foreground pointer-events-none absolute inset-y-0 left-0 flex items-center justify-center pl-3 peer-disabled:opacity-50">
|
||||
<SearchIcon className="size-4" />
|
||||
<span className="sr-only">Buscar</span>
|
||||
</div>
|
||||
<Input
|
||||
id={id}
|
||||
type="search"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
className="peer px-9 [&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputSearchIconDemo
|
||||
export default BarraBusqueda
|
||||
|
||||
93
src/components/planes/Filtro.tsx
Normal file
93
src/components/planes/Filtro.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
'use client'
|
||||
|
||||
import { CheckIcon, ChevronDown } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/command'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/components/ui/popover'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
export type Option = { value: string; label: string }
|
||||
|
||||
type Props = {
|
||||
options: Array<Option>
|
||||
value: string | null
|
||||
onChange: (value: string) => void
|
||||
placeholder?: string
|
||||
className?: string
|
||||
ariaLabel?: string
|
||||
}
|
||||
|
||||
const Filtro: React.FC<Props> = ({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
placeholder = 'Seleccionar…',
|
||||
className,
|
||||
ariaLabel,
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const label = value
|
||||
? (options.find((o) => o.value === value)?.label ?? placeholder)
|
||||
: placeholder
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className={cn('w-full justify-between', className)}
|
||||
aria-label={ariaLabel ?? 'Filtro combobox'}
|
||||
>
|
||||
{label}
|
||||
<ChevronDown className="opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar…" className="h-9" />
|
||||
<CommandList>
|
||||
<CommandEmpty>Sin resultados.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((opt) => (
|
||||
<CommandItem
|
||||
key={opt.value}
|
||||
value={opt.value}
|
||||
onSelect={(currentValue) => {
|
||||
onChange(currentValue)
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
{opt.label}
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'ml-auto',
|
||||
value === opt.value ? 'opacity-100' : 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
export default Filtro
|
||||
Reference in New Issue
Block a user