Popover
---import { Button } from "@/components/starwind/button";import { Input } from "@/components/starwind/input";import { Label } from "@/components/starwind/label";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";---
<Popover> <PopoverTrigger asChild> <Button variant="outline">Open popover</Button> </PopoverTrigger> <PopoverContent class="w-80"> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> <div class="grid gap-2 px-0.5"> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-width">Width</Label> <Input id="popover-width" value="100%" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-max-width">Max. width</Label> <Input id="popover-max-width" value="300px" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-height">Height</Label> <Input id="popover-height" value="25px" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-max-height">Max. height</Label> <Input id="popover-max-height" value="none" class="col-span-2 h-8" /> </div> </div> </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Input } from "@/components/starwind/input";import { Label } from "@/components/starwind/label";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";
export function Example() { return ( <> <Popover> <PopoverTrigger asChild> <Button variant="outline">Open popover</Button> </PopoverTrigger> <PopoverContent className="w-80"> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> <div className="grid gap-2 px-0.5"> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-width">Width</Label> <Input id="popover-width" defaultValue="100%" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-max-width">Max. width</Label> <Input id="popover-max-width" defaultValue="300px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-height">Height</Label> <Input id="popover-height" defaultValue="25px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-max-height">Max. height</Label> <Input id="popover-max-height" defaultValue="none" className="col-span-2 h-8" /> </div> </div> </PopoverContent> </Popover> </> );}Installation
pnpx starwind@latest add popovernpx starwind@latest add popoveryarn dlx starwind@latest add popoverUsage
---import { Button } from "@/components/starwind/button";import { Input } from "@/components/starwind/input";import { Label } from "@/components/starwind/label";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";---
<Popover> <PopoverTrigger asChild> <Button variant="outline">Open popover</Button> </PopoverTrigger> <PopoverContent class="w-80"> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> <div class="grid gap-2 px-0.5"> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-width">Width</Label> <Input id="popover-width" value="100%" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-max-width">Max. width</Label> <Input id="popover-max-width" value="300px" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-height">Height</Label> <Input id="popover-height" value="25px" class="col-span-2 h-8" /> </div> <div class="grid grid-cols-3 items-center gap-3"> <Label for="popover-max-height">Max. height</Label> <Input id="popover-max-height" value="none" class="col-span-2 h-8" /> </div> </div> </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Input } from "@/components/starwind/input";import { Label } from "@/components/starwind/label";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";
export function Example() { return ( <> <Popover> <PopoverTrigger asChild> <Button variant="outline">Open popover</Button> </PopoverTrigger> <PopoverContent className="w-80"> <PopoverHeader> <PopoverTitle>Dimensions</PopoverTitle> <PopoverDescription> Set the dimensions for the layer. </PopoverDescription> </PopoverHeader> <div className="grid gap-2 px-0.5"> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-width">Width</Label> <Input id="popover-width" defaultValue="100%" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-max-width">Max. width</Label> <Input id="popover-max-width" defaultValue="300px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-height">Height</Label> <Input id="popover-height" defaultValue="25px" className="col-span-2 h-8" /> </div> <div className="grid grid-cols-3 items-center gap-3"> <Label htmlFor="popover-max-height">Max. height</Label> <Input id="popover-max-height" defaultValue="none" className="col-span-2 h-8" /> </div> </div> </PopoverContent> </Popover> </> );}Composition
Use a trigger and content inside the root. Header, title, and description are optional content helpers.
Popover├── PopoverTrigger└── PopoverContent └── PopoverHeader ├── PopoverTitle └── PopoverDescriptionWhen to Use
Use Popover for contextual content, settings, or quick actions that stay near their trigger.
Hover Open
Enable hover behavior with openOnHover. Use closeDelay to control how long the popover stays open after the pointer leaves.
---import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";---
<Popover openOnHover closeDelay={120}> <PopoverTrigger asChild> <Button variant="outline">Quick close</Button> </PopoverTrigger> <PopoverContent class="w-56"> <PopoverHeader> <PopoverTitle>Fast close delay</PopoverTitle> <PopoverDescription> This popover closes quickly with `closeDelay` set to 120ms. </PopoverDescription> </PopoverHeader> </PopoverContent></Popover>
<Popover openOnHover closeDelay={500}> <PopoverTrigger asChild> <Button variant="outline">Slow close</Button> </PopoverTrigger> <PopoverContent class="w-56"> <PopoverHeader> <PopoverTitle>Longer close delay</PopoverTitle> <PopoverDescription> This popover remains open longer with `closeDelay` set to 500ms. </PopoverDescription> </PopoverHeader> </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";
export function Example() { return ( <> <Popover openOnHover closeDelay={120}> <PopoverTrigger asChild> <Button variant="outline">Quick close</Button> </PopoverTrigger> <PopoverContent className="w-56"> <PopoverHeader> <PopoverTitle>Fast close delay</PopoverTitle> <PopoverDescription> This popover closes quickly with `closeDelay` set to 120ms. </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover>
<Popover openOnHover closeDelay={500}> <PopoverTrigger asChild> <Button variant="outline">Slow close</Button> </PopoverTrigger> <PopoverContent className="w-56"> <PopoverHeader> <PopoverTitle>Longer close delay</PopoverTitle> <PopoverDescription> This popover remains open longer with `closeDelay` set to 500ms. </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> </> );}Nested Popovers
Nested popovers work without immediately closing the parent popover while you interact with child content.
---import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";---
<Popover> <PopoverTrigger asChild> <Button>Nested popover</Button> </PopoverTrigger> <PopoverContent class="w-72" align="start"> <PopoverHeader> <PopoverTitle>Parent popover</PopoverTitle> <PopoverDescription> Open the nested popover below to verify nested interaction behavior. </PopoverDescription> </PopoverHeader> <div class="mt-2"> <Popover> <PopoverTrigger asChild> <Button variant="outline">Open child</Button> </PopoverTrigger> <PopoverContent side="right" align="start" class="w-64"> <PopoverHeader> <PopoverTitle>Child popover</PopoverTitle> <PopoverDescription> These will stay nicely positioned even as the viewport shrinks or expands. </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> </div> </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/starwind/popover";
export function Example() { return ( <> <Popover> <PopoverTrigger asChild> <Button>Nested popover</Button> </PopoverTrigger> <PopoverContent className="w-72" align="start"> <PopoverHeader> <PopoverTitle>Parent popover</PopoverTitle> <PopoverDescription> Open the nested popover below to verify nested interaction behavior. </PopoverDescription> </PopoverHeader> <div className="mt-2"> <Popover> <PopoverTrigger asChild> <Button variant="outline">Open child</Button> </PopoverTrigger> <PopoverContent side="right" align="start" className="w-64"> <PopoverHeader> <PopoverTitle>Child popover</PopoverTitle> <PopoverDescription> These will stay nicely positioned even as the viewport shrinks or expands. </PopoverDescription> </PopoverHeader> </PopoverContent> </Popover> </div> </PopoverContent> </Popover> </> );}Alignment
Use the align prop on PopoverContent to control horizontal alignment relative to the trigger.
---import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverTrigger } from "@/components/starwind/popover";---
<Popover> <PopoverTrigger asChild> <Button variant="outline">Start</Button> </PopoverTrigger> <PopoverContent align="start" class="w-40"> Aligned to start. </PopoverContent></Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline">Center</Button> </PopoverTrigger> <PopoverContent align="center" class="w-40"> Aligned to center. </PopoverContent></Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline">End</Button> </PopoverTrigger> <PopoverContent align="end" class="w-40"> Aligned to end. </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverTrigger } from "@/components/starwind/popover";
export function Example() { return ( <> <Popover> <PopoverTrigger asChild> <Button variant="outline">Start</Button> </PopoverTrigger> <PopoverContent align="start" className="w-40"> Aligned to start. </PopoverContent> </Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline">Center</Button> </PopoverTrigger> <PopoverContent align="center" className="w-40"> Aligned to center. </PopoverContent> </Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline">End</Button> </PopoverTrigger> <PopoverContent align="end" className="w-40"> Aligned to end. </PopoverContent> </Popover> </> );}Side and Offset
Position content with side and add spacing from the trigger with sideOffset.
---import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverTrigger } from "@/components/starwind/popover";---
<Popover> <PopoverTrigger asChild> <Button variant="outline" class="w-full">Top</Button> </PopoverTrigger> <PopoverContent side="top" sideOffset={12} class="w-44"> side="top" with sideOffset=12 and a quicker animation. </PopoverContent></Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" class="w-full">Right</Button> </PopoverTrigger> <PopoverContent side="right" align="start" sideOffset={16} class="w-44"> side="right" + align="start". </PopoverContent></Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" class="w-full">Bottom</Button> </PopoverTrigger> <PopoverContent side="bottom" align="end" sideOffset={8} class="w-44"> side="bottom" + align="end". </PopoverContent></Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" class="w-full">Left</Button> </PopoverTrigger> <PopoverContent side="left" sideOffset={14} class="w-44"> side="left" with a longer animation duration. </PopoverContent></Popover>import { Button } from "@/components/starwind/button";import { Popover, PopoverContent, PopoverTrigger } from "@/components/starwind/popover";
export function Example() { return ( <> <Popover> <PopoverTrigger asChild> <Button variant="outline" className="w-full">Top</Button> </PopoverTrigger> <PopoverContent side="top" sideOffset={12} className="w-44"> side="top" with sideOffset=12 and a quicker animation. </PopoverContent> </Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" className="w-full">Right</Button> </PopoverTrigger> <PopoverContent side="right" align="start" sideOffset={16} className="w-44"> side="right" + align="start". </PopoverContent> </Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" className="w-full">Bottom</Button> </PopoverTrigger> <PopoverContent side="bottom" align="end" sideOffset={8} className="w-44"> side="bottom" + align="end". </PopoverContent> </Popover>
<Popover> <PopoverTrigger asChild> <Button variant="outline" className="w-full">Left</Button> </PopoverTrigger> <PopoverContent side="left" sideOffset={14} className="w-44"> side="left" with a longer animation duration. </PopoverContent> </Popover> </> );}API Reference
Styled Component API
These props are added or materially changed by the installed styled component. Standard HTML attributes remain available through the inherited interfaces noted below. Expand a prop to see named type definitions and framework-specific imports. Follow the Primitive and Runtime links for lower-level behavior props.
Popover Trigger
Inherits button attributes.
Contains the following additional props:
asChild boolean false
- Description
- Merges the component behavior and props into its child element.
- Classification
- Primitive override
- Primitive prop
- popover.Trigger.asChild
Popover Content
Inherits div attributes.
Contains the following additional props:
disablePortal boolean false
- Description
- Keeps the public Portal wrapper inline instead of moving it to a target.
- Classification
- Wrapper prop
exitMotion "popover" | "fade" "popover"
- Description
- Selects the motion treatment used while floating content closes.
- Classification
- Styled variant
portalContainer string —
- Description
- Sets the CSS selector for the public Portal wrapper target.
- Classification
- Wrapper prop
Primitive And Runtime API
Use these references when you need the lower-level behavior APIs behind Popover.
Primitive API
Runtime API
- Popover primitive
createPopoverfrom@starwind-ui/runtime/popover
Changelog
View version history v2.1.0 3 releases
v2.1.0
- Added
portalContaineranddisablePortaltoPopoverContentfor custom portal targets and inline rendering.
v2.0.3
- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.
v2.0.0
- Rebuilt Popover on Starwind Runtime for open state, floating placement, dismissal, and nesting.
- See the Popover Primitive for the underlying unstyled anatomy and behavior API.