Popover
Non-modal floating panel anchored to a trigger. Use for settings panels and pickers.
Examples
Align
Use the align prop on PopoverContent to control the horizontal alignment.
import { Button } from "@codefast/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@codefast/ui/popover";
export function PopoverAlignments() {
return (
<div className="flex gap-6">
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm">
Start
</Button>
</PopoverTrigger>
<PopoverContent align="start" className="w-40">
Aligned to start
</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm">
Center
</Button>
</PopoverTrigger>
<PopoverContent align="center" className="w-40">
Aligned to center
</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm">
End
</Button>
</PopoverTrigger>
<PopoverContent align="end" className="w-40">
Aligned to end
</PopoverContent>
</Popover>
</div>
);
}
Basic
A simple popover with a header, title, and description.
import { Button } from "@codefast/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@codefast/ui/popover";
export function PopoverBasic() {
return (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">Open Popover</Button>
</PopoverTrigger>
<PopoverContent align="start">
<PopoverHeader>
<PopoverTitle>Dimensions</PopoverTitle>
<PopoverDescription>Set the dimensions for the layer.</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
);
}
With Form
A popover with form fields inside.
import { Button } from "@codefast/ui/button";
import { Field, FieldGroup, FieldLabel } from "@codefast/ui/field";
import { Input } from "@codefast/ui/input";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@codefast/ui/popover";
export function PopoverForm() {
return (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">Open Popover</Button>
</PopoverTrigger>
<PopoverContent className="w-64" align="start">
<PopoverHeader>
<PopoverTitle>Dimensions</PopoverTitle>
<PopoverDescription>Set the dimensions for the layer.</PopoverDescription>
</PopoverHeader>
<FieldGroup className="gap-4">
<Field orientation="horizontal">
<FieldLabel htmlFor="width" className="w-1/2">
Width
</FieldLabel>
<Input id="width" defaultValue="100%" />
</Field>
<Field orientation="horizontal">
<FieldLabel htmlFor="height" className="w-1/2">
Height
</FieldLabel>
<Input id="height" defaultValue="25px" />
</Field>
</FieldGroup>
</PopoverContent>
</Popover>
);
}
RTL
Right-to-left layout support for languages such as Arabic and Hebrew.
Translations are AI-generated for demonstration and may be imperfect.
import { Button } from "@codefast/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@codefast/ui/popover";
import type { Translations } from "#/features/components-catalog/components/detail/language";
import { useTranslation } from "#/features/components-catalog/components/detail/language-context";
const translations: Translations = {
en: {
dir: "ltr",
values: {
title: "Dimensions",
description: "Set the dimensions for the layer.",
left: "Left",
top: "Top",
bottom: "Bottom",
right: "Right",
},
},
ar: {
dir: "rtl",
values: {
title: "الأبعاد",
description: "تعيين الأبعاد للطبقة.",
left: "يسار",
top: "أعلى",
bottom: "أسفل",
right: "يمين",
},
},
he: {
dir: "rtl",
values: {
title: "מימדים",
description: "הגדר את המימדים לשכבה.",
left: "שמאל",
top: "למעלה",
bottom: "למטה",
right: "ימין",
},
},
};
const physicalSides = ["left", "top", "bottom", "right"] as const;
export function PopoverRtl() {
const { dir, t } = useTranslation(translations, "ar");
return (
<div className="flex flex-wrap justify-center gap-2">
{physicalSides.map((side) => (
<Popover key={side}>
<PopoverTrigger asChild>
<Button variant="outline">{t[side]}</Button>
</PopoverTrigger>
<PopoverContent side={side} dir={dir}>
<PopoverHeader>
<PopoverTitle>{t.title}</PopoverTitle>
<PopoverDescription>{t.description}</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
))}
</div>
);
}
Anatomy
How the parts nest — every slot the component exposes, in composition order.
Features
- Non-modal by default — the rest of the page stays interactive while it's open; set modal to trap focus like a Dialog.
- PopoverAnchor lets the panel point at a different element than the one that opens it.
- side/align/sideOffset on PopoverContent control placement and the gap from the trigger.
API reference
Props for each part of the component. All native element props are also forwarded.
Popover
Root. Manages open state. Non-modal by default.
openbooleanThe controlled open state.
defaultOpenbooleanThe open state when initially rendered (uncontrolled).
Default
falseonOpenChange(open: boolean) => voidCalled when the open state changes.
modalbooleanWhen true, traps focus and blocks outside interaction.
Default
false
PopoverContent
side"top" | "right" | "bottom" | "left"The preferred edge of the trigger to render against.
Default
"bottom"align"start" | "center" | "end"The preferred alignment against the trigger.
Default
"center"sideOffsetnumberGap in px between trigger and content.
Default
4
Accessibility
Built to be keyboard-navigable and screen-reader friendly out of the box.
| Key | Function |
|---|---|
| Space | Opens the popover when the trigger is focused. |
| Tab | Moves through focusable elements inside the content. |
| Esc | Closes the popover and returns focus to the trigger. |
- Focus moves into the content on open and returns to the trigger on close.
- Unlike a Dialog it is non-modal — the rest of the page stays interactive unless modal is set.
- Use a Tooltip for hover hints; reach for a Popover when the panel holds controls.
Guidelines
Conventions that keep usage consistent across an app.
Do
- Anchor short, focused tasks to the control they relate to.
- Give the panel a title with PopoverTitle when it contains a form.
Don’t
- Don’t put long, primary content in a popover — use a Dialog or a page.
- Don’t use a Popover for passive hints — that’s a Tooltip.
Explore further
Ready to integrate?
Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.