"use client";
import { Button, Popover } from "@vortexlabs/vortex";
export const PopoverExample = () => (
<Popover>
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>Open popover</Button>}
</Popover.Trigger>
<Popover.Content attributes={{ "aria-label": "Example popover" }}>
Popover content
</Popover.Content>
</Popover>
);Features
- Opens on click, hover, or focus.
- Supports text, controls, and actions.
- Adjusts placement when space is limited.
- Can match the trigger width.
Anatomy
<Popover>
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>Open popover</Button>}
</Popover.Trigger>
<Popover.Content />
</Popover>Position
Set position to choose a side and alignment; start and end follow text direction.
"use client";
import { Button, Popover, Stack } from "@vortexlabs/vortex";
export const PopoverPositionExample = () => (
<Stack direction="row" gap={2}>
{(
["top-center", "bottom-center", "start-center", "end-center"] as const
).map((position) => (
<Popover key={position} position={position}>
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>{position}</Button>}
</Popover.Trigger>
<Popover.Content>Popover content</Popover.Content>
</Popover>
))}
</Stack>
);Padding
The default is md. Use none when the content supplies its own spacing.
"use client";
import { Button, Popover, Stack } from "@vortexlabs/vortex";
export const PopoverPaddingExample = () => (
<Stack direction="row" gap={2}>
{(["none", "xs", "sm", "md", "lg", "xl"] as const).map((padding) => (
<Popover key={padding} padding={padding}>
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>{padding}</Button>}
</Popover.Trigger>
<Popover.Content>{`Content with padding “${padding}”.`}</Popover.Content>
</Popover>
))}
</Stack>
);Width
Set width="trigger" to match the trigger width.
"use client";
import { Button, Popover } from "@vortexlabs/vortex";
export const PopoverWidthExample = () => (
<Popover position="bottom-start" width="trigger">
<Popover.Trigger>
{(attributes) => (
<Button attributes={attributes}>Wide trigger button label</Button>
)}
</Popover.Trigger>
<Popover.Content>Popover content</Popover.Content>
</Popover>
);Triggers
Set triggerType to open on click, hover, or focus; hover also opens on keyboard focus.
"use client";
import { Button, Popover, Stack } from "@vortexlabs/vortex";
export const PopoverTriggerExample = () => (
<Stack direction="row" gap={2}>
<Popover triggerType="click">
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>Click</Button>}
</Popover.Trigger>
<Popover.Content>Popover content</Popover.Content>
</Popover>
<Popover triggerType="hover">
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>Hover</Button>}
</Popover.Trigger>
<Popover.Content>Popover content</Popover.Content>
</Popover>
<Popover triggerType="focus">
<Popover.Trigger>
{(attributes) => <Button attributes={attributes}>Focus me</Button>}
</Popover.Trigger>
<Popover.Content>Popover content</Popover.Content>
</Popover>
</Stack>
);Initial Focus
Set autoFocus={false} to focus the panel instead of its first control.
"use client";
import { Button, Popover, Stack } from "@vortexlabs/vortex";
export const PopoverFocusExample = () => (
<Stack direction="row" gap={2}>
{([true, false] as const).map((autoFocus) => (
<Popover key={String(autoFocus)} autoFocus={autoFocus}>
<Popover.Trigger>
{(attributes) => (
<Button attributes={attributes}>
{autoFocus
? "Focus first control"
: "Focus panel"}
</Button>
)}
</Popover.Trigger>
<Popover.Content>
<Stack gap={3}>
<p>Popover content</p>
<Button size="sm">Inner action</Button>
</Stack>
</Popover.Content>
</Popover>
))}
</Stack>
);Use Tooltip for brief supporting text.
Accessibility
Key
Description
TabShiftTab
Moves within the panel; hover-triggered panels let focus leave.
EnterSpace
Toggles a click-triggered popover from its button.
Escape
Requests dismissal; update
active in controlled mode.Set
aria-label in Popover.Content.attributes when the trigger label does not describe the panel.