Popover
Displays rich content in a portal, triggered by a button.
This component uses newly available browser features
This component uses CSS Anchor Positioning which has only been widely supported since January 2026. If you're targeting older or less mainstream browsers then maybe this component isn't for you, yet.
Alternatively you can use Singlestage 0.4 which positions the component correctly but with limited flexibility for alignment, or roll your own using Singlestage CSS classes for consistent styling.
More Infouse leptos::prelude::*; use singlestage::*; #[component] pub fn PopoverExample() -> impl IntoView { view! { <Popover> <PopoverTrigger> <Button variant="outline">"Open popover"</Button> </PopoverTrigger> <PopoverContent class="w-80"> <form> <FieldSet class="gap-4"> <FieldLegend variant="label">"Dimensions"</FieldLegend> <FieldDescription>"Set the dimensions for the layer."</FieldDescription> <FieldGroup class="gap-2 [&_input]:max-w-48 [&_input]:h-8"> <Field orientation="horizontal"> <FieldLabel>"Width"</FieldLabel> <Input value="100%" autofocus=true /> </Field> <Field orientation="horizontal"> <FieldLabel>"Max. width"</FieldLabel> <Input value="300px" /> </Field> <Field orientation="horizontal"> <FieldLabel>"Height"</FieldLabel> <Input value="25px" /> </Field> <Field orientation="horizontal"> <FieldLabel>"Max. height"</FieldLabel> <Input value="none" /> </Field> </FieldGroup> </FieldSet> </form> </PopoverContent> </Popover> } }
Basic
A simple popover with a header, title, and description.
use leptos::prelude::*; use singlestage::*; #[component] pub fn PopoverBasicExample() -> impl IntoView { view! { <Popover> <PopoverTrigger> <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> } }
Align
Use the align prop on PopoverContent to control the horizontal alignment.
use leptos::prelude::*; use singlestage::*; #[component] pub fn PopoverAlignExample() -> impl IntoView { view! { <div class="flex gap-6"> <Popover> <PopoverTrigger> <Button variant="outline" size="sm"> "Start" </Button> </PopoverTrigger> <PopoverContent align="start" class="w-40"> "Aligned to start" </PopoverContent> </Popover> <Popover> <PopoverTrigger> <Button variant="outline" size="sm"> "Center" </Button> </PopoverTrigger> <PopoverContent align="center" class="w-40"> "Aligned to center" </PopoverContent> </Popover> <Popover> <PopoverTrigger> <Button variant="outline" size="sm"> "End" </Button> </PopoverTrigger> <PopoverContent align="end" class="w-40"> "Aligned to end" </PopoverContent> </Popover> </div> } }
With Form
A popover with form fields inside.
use leptos::prelude::*; use singlestage::*; #[component] pub fn PopoverFormExample() -> impl IntoView { view! { <Popover> <PopoverTrigger> <Button variant="outline">"Open Popover"</Button> </PopoverTrigger> <PopoverContent class="w-64" align="start"> <PopoverHeader> <PopoverTitle>"Dimensions"</PopoverTitle> <PopoverDescription>"Set the dimensions for the layer."</PopoverDescription> </PopoverHeader> <FieldGroup class="gap-4"> <Field orientation="horizontal"> <FieldLabel label_for="width" class="w-1/2"> "Width" </FieldLabel> <Input id="width" value="100%" /> </Field> <Field orientation="horizontal"> <FieldLabel label_for="height" class="w-1/2"> "Height" </FieldLabel> <Input id="height" value="25px" /> </Field> </FieldGroup> </PopoverContent> </Popover> } }
Anatomy
Import all parts and piece them together.
use leptos::prelude::*; use singlestage::*; #[component] pub fn PopoverAnatomy() -> impl IntoView { view! { <Popover> <PopoverTrigger> <Button /> </PopoverTrigger> <PopoverContent> <PopoverHeader> <PopoverTitle /> <PopoverDescription /> </PopoverHeader> </PopoverContent> </Popover> } }
API Reference
Popover
Contains all the parts of a popover.
| Name | Type | Default | Description |
|---|---|---|---|
| modal | bool | false | Set whether or not this popover should be modal meaning it can't be light dismissed Use this along with the `open` signal for a manually managed popover |
| open | bool | false | Reactive signal that can remotely control the open state of the popover **but is not coupled to the actual open state of the popover** unless `modal` is set to `true` |
PopoverContent
The component that pops out when the popover is open.
| Name | Type | Default | Description |
|---|---|---|---|
| align | String | "start" | Set how to align the popover. Accepted values are "start" | "center" | "end" |
| side | String | "bottom" | Set which side the popover opens relative to the trigger. Accepted values are "top" | "right" | "bottom" | "left". |
PopoverHeader
A styled header container for use inside a PopoverContent.