Popover
Popover is a thin wrapper over Ark UI popover that displays additional content in a floating layer anchored to a trigger. Content is styled with the existing --popover tokens and the portal/positioner are internal details — PopoverContent handles them. The close control is PopoverDismiss, and the arrow is toggled with the arrow prop.
// apps/docs/src/components/examples/popover/default/react.tsx
import {
Popover,
PopoverTrigger,
PopoverTitle,
PopoverDescription,
PopoverDismiss,
PopoverContent,
} from '@cloudvoyant/helical-react';
import { X } from 'lucide-react';
export default function ReactPopoverDefault() {
return (
<Popover>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverDismiss>
<X />
</PopoverDismiss>
<PopoverTitle>Favorite Frameworks</PopoverTitle>
<PopoverDescription>Tell us what is your favorite framework and why you love to use it.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/default/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverDismiss, PopoverContent } from '@cloudvoyant/helical-svelte';
import { X } from 'lucide-svelte';
</script>
<Popover>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverDismiss>
<X />
</PopoverDismiss>
<PopoverTitle>Favorite Frameworks</PopoverTitle>
<PopoverDescription>Tell us what is your favorite framework and why you love to use it.</PopoverDescription>
</PopoverContent>
</Popover>Examples
Anchor
// apps/docs/src/components/examples/popover/anchor/react.tsx
import {
Popover,
PopoverTrigger,
PopoverAnchor,
PopoverTitle,
PopoverDescription,
PopoverContent,
} from '@cloudvoyant/helical-react';
import { Input } from '@cloudvoyant/helical-react';
export default function ReactPopoverAnchor() {
return (
<Popover>
<div className="flex items-center gap-3">
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverAnchor>
<Input placeholder="Type here..." />
</PopoverAnchor>
</div>
<PopoverContent>
<PopoverTitle>Anchored Popover</PopoverTitle>
<PopoverDescription>
The popover positions relative to the anchor (the input), not the trigger.
</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/anchor/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverAnchor, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
import { Input } from '@cloudvoyant/helical-svelte';
</script>
<Popover>
<div class="flex items-center gap-3">
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverAnchor>
<Input placeholder="Type here..." />
</PopoverAnchor>
</div>
<PopoverContent>
<PopoverTitle>Anchored Popover</PopoverTitle>
<PopoverDescription>The popover positions relative to the anchor (the input), not the trigger.</PopoverDescription>
</PopoverContent>
</Popover>Arrow
// apps/docs/src/components/examples/popover/arrow/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverArrow() {
return (
<Popover>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent arrow>
<PopoverTitle>Notifications</PopoverTitle>
<PopoverDescription>You have 3 unread messages in your inbox.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/arrow/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent arrow>
<PopoverTitle>Notifications</PopoverTitle>
<PopoverDescription>You have 3 unread messages in your inbox.</PopoverDescription>
</PopoverContent>
</Popover>Close Behavior
// apps/docs/src/components/examples/popover/close-behavior/react.tsx
import {
Popover,
PopoverTrigger,
PopoverTitle,
PopoverDescription,
PopoverDismiss,
PopoverContent,
} from '@cloudvoyant/helical-react';
import { X } from 'lucide-react';
export default function ReactPopoverCloseBehavior() {
return (
<Popover closeOnEscape={false} closeOnInteractOutside={false}>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverDismiss>
<X />
</PopoverDismiss>
<PopoverTitle>Sticky Popover</PopoverTitle>
<PopoverDescription>
This popover ignores Escape and outside clicks. Use the dismiss button to close it.
</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/close-behavior/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverDismiss, PopoverContent } from '@cloudvoyant/helical-svelte';
import { X } from 'lucide-svelte';
</script>
<Popover closeOnEscape={false} closeOnInteractOutside={false}>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverDismiss>
<X />
</PopoverDismiss>
<PopoverTitle>Sticky Popover</PopoverTitle>
<PopoverDescription>This popover ignores Escape and outside clicks. Use the dismiss button to close it.</PopoverDescription>
</PopoverContent>
</Popover>Controlled
// apps/docs/src/components/examples/popover/controlled/react.tsx
import { useState } from 'react';
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverControlled() {
const [open, setOpen] = useState(false);
return (
<div className="flex items-center gap-4">
<Popover open={open} onOpenChange={(e) => setOpen(e.open)}>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Controlled Popover</PopoverTitle>
<PopoverDescription>This popover is fully controlled by the checkbox.</PopoverDescription>
</PopoverContent>
</Popover>
<label className="flex items-center gap-2 text-sm text-muted-foreground">
<input type="checkbox" checked={open} onChange={(e) => setOpen(e.target.checked)} />
Open
</label>
</div>
);
}<!-- apps/docs/src/components/examples/popover/controlled/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
let open = $state(false);
</script>
<div class="flex items-center gap-4">
<Popover bind:open>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Controlled Popover</PopoverTitle>
<PopoverDescription>This popover is fully controlled by the checkbox.</PopoverDescription>
</PopoverContent>
</Popover>
<label class="flex items-center gap-2 text-sm text-muted-foreground">
<input type="checkbox" bind:checked={open} />
Open
</label>
</div>Dialog Integration
Edit Profile
// apps/docs/src/components/examples/popover/dialog-integration/react.tsx
import {
Dialog,
DialogTrigger,
DialogTitle,
DialogDescription,
DialogDismiss,
DialogContent,
DialogBackdrop,
} from '@cloudvoyant/helical-react';
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
import { X } from 'lucide-react';
export default function ReactPopoverDialogIntegration() {
return (
<Dialog>
<DialogTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Dialog
</DialogTrigger>
<DialogBackdrop />
<DialogContent>
<DialogDismiss>
<X />
</DialogDismiss>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>Update your profile information below.</DialogDescription>
<Popover lazyMount unmountOnExit>
<PopoverTrigger className="rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground">
More Options
</PopoverTrigger>
<PopoverContent arrow>
<PopoverTitle>Additional Settings</PopoverTitle>
<PopoverDescription>This popover renders correctly above the dialog.</PopoverDescription>
</PopoverContent>
</Popover>
</DialogContent>
</Dialog>
);
}<!-- apps/docs/src/components/examples/popover/dialog-integration/svelte.svelte -->
<script lang="ts">
import {
Dialog,
DialogTrigger,
DialogTitle,
DialogDescription,
DialogDismiss,
DialogContent,
DialogBackdrop,
} from '@cloudvoyant/helical-svelte';
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
import { X } from 'lucide-svelte';
</script>
<Dialog>
<DialogTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Dialog
</DialogTrigger>
<DialogBackdrop />
<DialogContent>
<DialogDismiss>
<X />
</DialogDismiss>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>Update your profile information below.</DialogDescription>
<Popover lazyMount unmountOnExit>
<PopoverTrigger class="rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground">
More Options
</PopoverTrigger>
<PopoverContent arrow>
<PopoverTitle>Additional Settings</PopoverTitle>
<PopoverDescription>This popover renders correctly above the dialog.</PopoverDescription>
</PopoverContent>
</Popover>
</DialogContent>
</Dialog>Modality
// apps/docs/src/components/examples/popover/modality/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverModality() {
return (
<Popover modal>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Confirm Action</PopoverTitle>
<PopoverDescription>Focus is trapped inside this modal popover until dismissed.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/modality/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover modal>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Confirm Action</PopoverTitle>
<PopoverDescription>Focus is trapped inside this modal popover until dismissed.</PopoverDescription>
</PopoverContent>
</Popover>Multiple Triggers
// apps/docs/src/components/examples/popover/multiple-triggers/react.tsx
import { useState } from 'react';
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
const items = [
{ id: 'share', label: 'Share', detail: 'Share this item with others via link or email.' },
{ id: 'export', label: 'Export', detail: 'Export this item as PDF, CSV, or JSON.' },
{ id: 'archive', label: 'Archive', detail: 'Move this item to the archive for later reference.' },
];
export default function ReactPopoverMultipleTriggers() {
const [active, setActive] = useState(items[0]);
return (
<Popover onTriggerValueChange={(e) => setActive(items.find((i) => i.id === e.value) ?? items[0])}>
<div className="flex items-center gap-2">
{items.map((item) => (
<PopoverTrigger
key={item.id}
value={item.id}
className="rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground"
>
{item.label}
</PopoverTrigger>
))}
</div>
<PopoverContent>
<PopoverTitle>{active.label}</PopoverTitle>
<PopoverDescription>{active.detail}</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/multiple-triggers/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
const items = [
{ id: 'share', label: 'Share', detail: 'Share this item with others via link or email.' },
{ id: 'export', label: 'Export', detail: 'Export this item as PDF, CSV, or JSON.' },
{ id: 'archive', label: 'Archive', detail: 'Move this item to the archive for later reference.' },
];
let active = $state(items[0]);
</script>
<Popover onTriggerValueChange={(e) => (active = items.find((i) => i.id === e.value) ?? items[0])}>
<div class="flex items-center gap-2">
{#each items as item (item.id)}
<PopoverTrigger
value={item.id}
class="rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground"
>
{item.label}
</PopoverTrigger>
{/each}
</div>
<PopoverContent>
<PopoverTitle>{active.label}</PopoverTitle>
<PopoverDescription>{active.detail}</PopoverDescription>
</PopoverContent>
</Popover>Nested
// apps/docs/src/components/examples/popover/nested/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverNested() {
return (
<Popover>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Settings</PopoverTitle>
<PopoverDescription>Manage your preferences and account settings.</PopoverDescription>
<Popover lazyMount unmountOnExit positioning={{ placement: 'right' }}>
<PopoverTrigger className="mt-2 rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground">
Advanced
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Advanced Settings</PopoverTitle>
<PopoverDescription>Configure advanced options for power users.</PopoverDescription>
</PopoverContent>
</Popover>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/nested/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Settings</PopoverTitle>
<PopoverDescription>Manage your preferences and account settings.</PopoverDescription>
<Popover lazyMount unmountOnExit positioning={{ placement: 'right' }}>
<PopoverTrigger class="mt-2 rounded-md bg-secondary px-3 py-1.5 text-sm font-medium text-secondary-foreground">
Advanced
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Advanced Settings</PopoverTitle>
<PopoverDescription>Configure advanced options for power users.</PopoverDescription>
</PopoverContent>
</Popover>
</PopoverContent>
</Popover>Placement
// apps/docs/src/components/examples/popover/placement/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverPlacement() {
return (
<Popover positioning={{ placement: 'left-start', offset: { mainAxis: 12, crossAxis: 12 } }}>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Left Placement</PopoverTitle>
<PopoverDescription>This popover appears on the left with custom offset values.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/placement/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover positioning={{ placement: 'left-start', offset: { mainAxis: 12, crossAxis: 12 } }}>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Left Placement</PopoverTitle>
<PopoverDescription>This popover appears on the left with custom offset values.</PopoverDescription>
</PopoverContent>
</Popover>Popover With Tooltip
// apps/docs/src/components/examples/popover/popover-with-tooltip/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
import { Tooltip, TooltipTrigger, TooltipContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverWithTooltip() {
return (
<Popover>
<Tooltip>
<TooltipTrigger asChild>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Open Popover
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent>Shows on hover over the trigger</TooltipContent>
</Tooltip>
<PopoverContent>
<PopoverTitle>Popover with Tooltip</PopoverTitle>
<PopoverDescription>The trigger also shows a tooltip on hover.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/popover-with-tooltip/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
import { Tooltip, TooltipTrigger, TooltipContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover>
<Tooltip>
<TooltipTrigger>
{#snippet asChild(propsFn)}
<PopoverTrigger
{...propsFn()}
class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground"
>
Open Popover
</PopoverTrigger>
{/snippet}
</TooltipTrigger>
<TooltipContent>Shows on hover over the trigger</TooltipContent>
</Tooltip>
<PopoverContent>
<PopoverTitle>Popover with Tooltip</PopoverTitle>
<PopoverDescription>The trigger also shows a tooltip on hover.</PopoverDescription>
</PopoverContent>
</Popover>Root Provider
Popover is closed
Popover is closed
// apps/docs/src/components/examples/popover/root-provider/react.tsx
import {
usePopover,
PopoverProvider,
PopoverTrigger,
PopoverTitle,
PopoverDescription,
PopoverContent,
} from '@cloudvoyant/helical-react';
export default function ReactPopoverRootProvider() {
const popover = usePopover({ positioning: { placement: 'bottom-start' } });
return (
<div className="flex flex-col items-center gap-4">
<p className="text-sm text-muted-foreground">Popover is {popover.open ? 'open' : 'closed'}</p>
<PopoverProvider value={popover}>
<PopoverTrigger className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Toggle Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Controlled Externally</PopoverTitle>
<PopoverDescription>This popover is controlled via the usePopover hook.</PopoverDescription>
</PopoverContent>
</PopoverProvider>
</div>
);
}<!-- apps/docs/src/components/examples/popover/root-provider/svelte.svelte -->
<script lang="ts">
import { usePopover, PopoverProvider, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
const popover = usePopover({ id: 'popover-1', positioning: { placement: 'bottom-start' } });
</script>
<div class="flex flex-col items-center gap-4">
<p class="text-sm text-muted-foreground">Popover is {popover().open ? 'open' : 'closed'}</p>
<PopoverProvider value={popover}>
<PopoverTrigger class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground">
Toggle Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Controlled Externally</PopoverTitle>
<PopoverDescription>This popover is controlled via the usePopover hook.</PopoverDescription>
</PopoverContent>
</PopoverProvider>
</div>Same Width
// apps/docs/src/components/examples/popover/same-width/react.tsx
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-react';
export default function ReactPopoverSameWidth() {
return (
<Popover positioning={{ sameWidth: true }}>
<PopoverTrigger
className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground"
style={{ minWidth: 200 }}
>
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Matched Width</PopoverTitle>
<PopoverDescription>This popover matches the width of its trigger element.</PopoverDescription>
</PopoverContent>
</Popover>
);
}<!-- apps/docs/src/components/examples/popover/same-width/svelte.svelte -->
<script lang="ts">
import { Popover, PopoverTrigger, PopoverTitle, PopoverDescription, PopoverContent } from '@cloudvoyant/helical-svelte';
</script>
<Popover positioning={{ sameWidth: true }}>
<PopoverTrigger
class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground"
style="min-width: 200px"
>
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Matched Width</PopoverTitle>
<PopoverDescription>This popover matches the width of its trigger element.</PopoverDescription>
</PopoverContent>
</Popover>API Reference
Popover
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open / onOpenChange |
boolean / (details) => void |
— | Controlled open state. |
defaultOpen |
boolean |
false |
Initial open state when uncontrolled. |
modal |
boolean |
false |
Trap focus, block scroll, and hide outside content from screen readers. |
closeOnEscape |
boolean |
true |
Close when Escape is pressed. |
closeOnInteractOutside |
boolean |
true |
Close on click/focus outside. |
positioning |
PositioningOptions |
— | Placement/offset/sameWidth (see Ark positioning). |
lazyMount / unmountOnExit |
boolean |
false |
Mount/unmount content only around open/close. |
Accepts all Ark PopoverRootProps.
PopoverProvider
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
UsePopoverReturn |
— | The API object from usePopover(). |
PopoverTrigger
Accepts all Ark PopoverTriggerProps plus className/class. Supports the value prop for multiple triggers.
PopoverAnchor
Accepts all Ark PopoverAnchorProps plus className/class. Positions the popover relative to this element instead of the trigger.
PopoverContent
Props
| Prop | Type | Default | Description |
|---|---|---|---|
arrow |
boolean |
false |
Render the arrow pointing at the trigger. |
Accepts all Ark PopoverContentProps plus className/class.
PopoverTitle
Accepts all Ark PopoverTitleProps plus className/class.
PopoverDescription
Accepts all Ark PopoverDescriptionProps plus className/class.
PopoverDismiss
Accepts all Ark PopoverCloseTriggerProps plus className/class. Ships with aria-label="Close".
PopoverIndicator
Accepts all Ark PopoverIndicatorProps plus className/class. Rotates 180° while open.
Hooks
usePopover— Ark machine factory; returnsUsePopoverReturnforPopoverProvider.usePopoverContext— reads the current popover state from context.
Accessibility
The content carries role="dialog" with aria-labelledby/aria-describedby wired to PopoverTitle/PopoverDescription by Ark. Keyboard support: Space/Enter open and close; Tab/Shift+Tab move focus through the content; Esc closes and returns focus to the trigger.
Theme extensions
None. The popover reuses existing tokens (--popover, --popover-foreground, --border, --ring, --muted) — no theme.css changes.