"use client";
import { Button } from "@/components/ui/button";import { Input } from "@/components/ui/input";import { Label } from "@/components/ui/label";import { Popover, PopoverContent, PopoverTrigger,} from "@/components/ui/popover";
export function PopoverDemo() { return ( <Popover> <PopoverTrigger render={<Button variant="tertiary" />}> Open popover </PopoverTrigger> <PopoverContent className="w-80"> <div className="grid gap-4"> <div className="space-y-2"> <h4 className="font-medium leading-none">Dimensions</h4> <p className="text-muted-foreground text-sm"> Set the dimensions for the layer. </p> </div> <div className="grid gap-2"> <div className="grid grid-cols-3 items-center gap-4"> <Label htmlFor="popover-width">Width</Label> <Input variant="secondary" id="popover-width" defaultValue="100%" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-4"> <Label htmlFor="popover-max-width">Max. width</Label> <Input variant="secondary" id="popover-max-width" defaultValue="300px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-4"> <Label htmlFor="popover-height">Height</Label> <Input variant="secondary" id="popover-height" defaultValue="25px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-4"> <Label htmlFor="popover-max-height">Max. height</Label> <Input variant="secondary" id="popover-max-height" defaultValue="none" className="col-span-2 h-8" /> </div> </div> </div> </PopoverContent> </Popover> );}pnpm dlx shadcn@latest add @herocn/popoverimport { Button } from "@/components/ui/button"import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover"<Popover> <PopoverTrigger render={<Button variant="outline" />}> Open Popover </PopoverTrigger> <PopoverContent> <PopoverHeader> <PopoverTitle>Title</PopoverTitle> <PopoverDescription>Description text here.</PopoverDescription> </PopoverHeader> </PopoverContent></Popover>Use the following composition to build a Popover:
Popover├── PopoverTrigger└── PopoverContentA simple popover with a header, title, and description.
"use client";
import { Button } from "@/components/ui/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover";
export function PopoverBasic() { return ( <Popover> <PopoverTrigger render={<Button variant="tertiary" className="w-fit" />}> Open Popover </PopoverTrigger> <PopoverContent> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> );}Use the align prop on PopoverContent to control the horizontal alignment relative to the trigger.
"use client";
import { Button } from "@/components/ui/button";import { Popover, PopoverContent, PopoverTrigger,} from "@/components/ui/popover";
export function PopoverAlign() { return ( <div className="flex gap-6"> <Popover> <PopoverTrigger render={<Button variant="tertiary" size="sm" />}> Start </PopoverTrigger> <PopoverContent align="start" className="w-40"> Aligned to start </PopoverContent> </Popover> <Popover> <PopoverTrigger render={<Button variant="tertiary" size="sm" />}> Center </PopoverTrigger> <PopoverContent align="center" className="w-40"> Aligned to center </PopoverContent> </Popover> <Popover> <PopoverTrigger render={<Button variant="tertiary" size="sm" />}> End </PopoverTrigger> <PopoverContent align="end" className="w-40"> Aligned to end </PopoverContent> </Popover> </div> );}A popover with form fields inside.
"use client";
import { Button } from "@/components/ui/button";import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";import { Input } from "@/components/ui/input";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover";
export function PopoverForm() { return ( <Popover> <PopoverTrigger render={<Button variant="tertiary" />}> Open Popover </PopoverTrigger> <PopoverContent className="w-64"> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> <FieldGroup className="gap-4"> <Field orientation="horizontal"> <FieldLabel htmlFor="popover-form-width" className="w-1/2"> Width </FieldLabel> <Input variant="secondary" id="popover-form-width" defaultValue="100%" /> </Field> <Field orientation="horizontal"> <FieldLabel htmlFor="popover-form-height" className="w-1/2"> Height </FieldLabel> <Input variant="secondary" id="popover-form-height" defaultValue="25px" /> </Field> </FieldGroup> </PopoverContent> </Popover> );}Use the withArrow prop on PopoverContent to show an arrow pointing at the trigger.
"use client";
import { Button } from "@/components/ui/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover";
export function PopoverWithArrow() { return ( <Popover> <PopoverTrigger render={<Button variant="tertiary" className="w-fit" />}> Open Popover </PopoverTrigger> <PopoverContent withArrow> <PopoverHeader> <PopoverTitle>With Arrow</PopoverTitle> <PopoverDescription> This popover has an arrow at its top </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> );}To enable RTL support in shadcn/ui, see the RTL configuration guide.
"use client";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Button } from "@/components/ui/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover";
const translations: Translations = { en: { dir: "ltr", values: { title: "Dimensions", description: "Set the dimensions for the layer.", "inline-start": "Inline Start", left: "Left", top: "Top", bottom: "Bottom", right: "Right", "inline-end": "Inline End", }, }, ar: { dir: "rtl", values: { title: "الأبعاد", description: "تعيين الأبعاد للطبقة.", "inline-start": "بداية السطر", left: "يسار", top: "أعلى", bottom: "أسفل", right: "يمين", "inline-end": "نهاية السطر", }, }, he: { dir: "rtl", values: { title: "מימדים", description: "הגדר את המימדים לשכבה.", "inline-start": "תחילת השורה", left: "שמאל", top: "למעלה", bottom: "למטה", right: "ימין", "inline-end": "סוף השורה", }, },};
const physicalSides = ["left", "top", "bottom", "right"] as const;const logicalSides = ["inline-start", "inline-end"] as const;
export function PopoverRtl() { const { dir, language, t } = useTranslation(translations, "ar");
return ( <div lang={language} dir={dir} className="grid max-w-lg gap-4"> <div className="flex flex-wrap justify-center gap-2"> {physicalSides.map((side) => ( <Popover key={side}> <PopoverTrigger render={<Button variant="tertiary" size="sm" />}> {t[side]} </PopoverTrigger> <PopoverContent side={side} dir={dir}> <PopoverHeader> <PopoverTitle>{t.title}</PopoverTitle> <PopoverDescription>{t.description}</PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> ))} </div> <div className="flex flex-wrap justify-center gap-2"> {logicalSides.map((side) => ( <Popover key={side}> <PopoverTrigger render={<Button variant="tertiary" size="sm" />}> {t[side]} </PopoverTrigger> <PopoverContent side={side} dir={dir}> <PopoverHeader> <PopoverTitle>{t.title}</PopoverTitle> <PopoverDescription>{t.description}</PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> ))} </div> </div> );}The popover is built on Base UI Popover. PopoverContent sets default positioning and passes the remaining props to the popup.
| Prop | Type | Default |
|---|---|---|
| align | "start" | "center" | "end" | "center" |
Horizontal alignment of the popup relative to the anchor. | ||
| alignOffset | number | 0 |
Offset along the alignment axis. | ||
| side | "top" | "bottom" | "left" | "right" | "inline-start" | "inline-end" | "bottom" |
Which side of the anchor to place the popup on. Logical sides follow the document direction when used with `dir`. | ||
| sideOffset | number | 8 |
Distance between the anchor and the popup. | ||
| withArrow | boolean | false |
Adds an arrow to the Popover content | ||
See the Base UI Popover API reference for root, trigger, title, description, and other props.