Components
Loading preview...
Displays rich content in a portal, triggered by a button.
npx shadcn@latest add https://21st.dev/r/shadcn/popover"use client";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Check, ChevronDown } from "lucide-react";
import { useId, useState } from "react";
const frameworks = [
{
value: "next.js",
label: "Next.js",
},
{
value: "sveltekit",
label: "SvelteKit",
},
{
value: "nuxt.js",
label: "Nuxt.js",
},
{
value: "remix",
label: "Remix",
},
{
value: "astro",
label: "Astro",
},
{
value: "angular",
label: "Angular",
},
{
value: "vue",
label: "Vue.js",
},
{
value: "react",
label: "React",
},
{
value: "ember",
label: "Ember.js",
},
{
value: "gatsby",
label: "Gatsby",
},
{
value: "eleventy",
label: "Eleventy",
},
{
value: "solid",
label: "SolidJS",
},
{
value: "preact",
label: "Preact",
},
{
value: "qwik",
label: "Qwik",
},
{
value: "alpine",
label: "Alpine.js",
},
{
value: "lit",
label: "Lit",
},
];
function Component() {
const id = useId();
const [open, setOpen] = useState<boolean>(false);
const [value, setValue] = useState<string>("");
return (
<div className="space-y-2 min-w-[300px]">
<Label htmlFor={id}>Select with search</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
id={id}
variant="outline"
role="combobox"
aria-expanded={open}
className="w-full justify-between bg-background px-3 font-normal outline-offset-0 hover:bg-background focus-visible:border-ring focus-visible:outline-[3px] focus-visible:outline-ring/20"
>
<span className={cn("truncate", !value && "text-muted-foreground")}>
{value
? frameworks.find((framework) => framework.value === value)?.label
: "Select framework"}
</span>
<ChevronDown
size={16}
strokeWidth={2}
className="shrink-0 text-muted-foreground/80"
aria-hidden="true"
/>
</Button>
</PopoverTrigger>
<PopoverContent
className="w-full min-w-[var(--radix-popper-anchor-width)] border-input p-0"
align="start"
>
<Command>
<CommandInput placeholder="Search framework..." />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue);
setOpen(false);
}}
>
{framework.label}
{value === framework.value && (
<Check size={16} strokeWidth={2} className="ml-auto" />
)}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
);
}
export { Component };