Popover
A floating content panel that appears relative to a trigger element
Default Variant
Standard popover style with medium shadow and border.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<Popover>
8 <PopoverTrigger variant="button">Open Popover</PopoverTrigger>
9 <PopoverContent>
10 <div class="space-y-2">
11 <h4 class="font-medium leading-none">Default Style</h4>
12 <p class="text-sm text-muted-foreground">
13 This is the standard popover appearance with balanced shadow and border.
14 </p>
15 </div>
16 </PopoverContent>
17</Popover>Bordered Variant
Emphasized border with lighter shadow for a more defined look.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<Popover>
8 <PopoverTrigger variant="outline">Bordered Popover</PopoverTrigger>
9 <PopoverContent variant="bordered">
10 <div class="space-y-2">
11 <h4 class="font-medium leading-none">Bordered Style</h4>
12 <p class="text-sm text-muted-foreground">
13 Features a prominent border with lighter shadow for clear definition.
14 </p>
15 </div>
16 </PopoverContent>
17</Popover>Elevated Variant
Floating appearance with larger shadow and no border.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6<Popover>
7 <PopoverTrigger variant="button">Elevated Popover</PopoverTrigger>
8 <PopoverContent variant="elevated">
9 <div class="space-y-2">
10 <h4 class="font-medium leading-none">Elevated Style</h4>
11 <p class="text-sm text-muted-foreground">
12 Creates a floating effect with enhanced shadow and no border.
13 </p>
14 </div>
15 </PopoverContent>
16</Popover>Minimal Variant
Subtle appearance with light border and small shadow.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<Popover>
8 <PopoverTrigger variant="ghost">Minimal Popover</PopoverTrigger>
9 <PopoverContent variant="minimal">
10 <div class="space-y-2">
11 <h4 class="font-medium leading-none">Minimal Style</h4>
12 <p class="text-sm text-muted-foreground">
13 Understated design with subtle border and shadow.
14 </p>
15 </div>
16 </PopoverContent>
17</Popover>Ghost Variant
Transparent background for complete custom styling.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<Popover>
8 <PopoverTrigger variant="button">Custom Styled</PopoverTrigger>
9 <PopoverContent
10 variant="ghost"
11 class="bg-gradient-to-r from-purple-500 to-pink-500 text-white"
12 >
13 <div class="space-y-2">
14 <h4 class="font-medium leading-none">Custom Style</h4>
15 <p class="text-sm">
16 Ghost variant allows complete custom styling with gradients and colors.
17 </p>
18 </div>
19 </PopoverContent>
20</Popover>Size Variants
Small, default, and large sizes for different content amounts.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<div class="flex flex-wrap gap-4">
8 <Popover>
9 <PopoverTrigger variant="button" size="sm">Small</PopoverTrigger>
10 <PopoverContent size="sm">
11 <p class="text-sm">Compact popover for brief content.</p>
12 </PopoverContent>
13 </Popover>
14
15 <Popover>
16 <PopoverTrigger variant="button">Default</PopoverTrigger>
17 <PopoverContent>
18 <div class="space-y-2">
19 <h4 class="font-medium">Default Size</h4>
20 <p class="text-sm text-muted-foreground">Standard size for most use cases.</p>
21 </div>
22 </PopoverContent>
23 </Popover>
24
25 <Popover>
26 <PopoverTrigger variant="button" size="lg">Large</PopoverTrigger>
27 <PopoverContent size="lg">
28 <div class="space-y-3">
29 <h3 class="text-lg font-semibold">Large Popover</h3>
30 <p class="text-sm text-muted-foreground">
31 Spacious layout for detailed content and complex interactions.
32 </p>
33 <div class="flex gap-2 pt-2">
34 <Button size="sm">Confirm</Button>
35 <Button variant="outline" size="sm">Cancel</Button>
36 </div>
37 </div>
38 </PopoverContent>
39 </Popover>
40
41 <Popover>
42 <PopoverTrigger variant="outline">Auto Width</PopoverTrigger>
43 <PopoverContent size="auto" class="w-auto">
44 <p>Content determines width</p>
45 </PopoverContent>
46 </Popover>
47</div>Animation Variants
Different entry and exit animations for visual variety.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<div class="flex flex-wrap gap-4">
8 <Popover>
9 <PopoverTrigger variant="button">Default (Combined)</PopoverTrigger>
10 <PopoverContent animation="default">
11 <p class="text-sm">Fade, zoom, and slide combined</p>
12 </PopoverContent>
13 </Popover>
14
15 <Popover>
16 <PopoverTrigger variant="button">Fade</PopoverTrigger>
17 <PopoverContent animation="fade">
18 <p class="text-sm">Simple fade in/out effect</p>
19 </PopoverContent>
20 </Popover>
21
22 <Popover>
23 <PopoverTrigger variant="button">Scale</PopoverTrigger>
24 <PopoverContent animation="scale">
25 <p class="text-sm">Zoom in/out effect</p>
26 </PopoverContent>
27 </Popover>
28
29 <Popover>
30 <PopoverTrigger variant="button">Slide</PopoverTrigger>
31 <PopoverContent animation="slide">
32 <p class="text-sm">Slide from placement direction</p>
33 </PopoverContent>
34 </Popover>
35
36 <Popover>
37 <PopoverTrigger variant="button">None</PopoverTrigger>
38 <PopoverContent animation="none">
39 <p class="text-sm">Instant show/hide</p>
40 </PopoverContent>
41 </Popover>
42</div>Placement Options
Position popover on any side of the trigger element.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<div class="flex flex-wrap gap-4 items-center justify-center min-h-[200px]">
8 <Popover>
9 <PopoverTrigger variant="outline">Top</PopoverTrigger>
10 <PopoverContent side="top">
11 <p class="text-sm">Positioned above trigger</p>
12 </PopoverContent>
13 </Popover>
14
15 <Popover>
16 <PopoverTrigger variant="outline">Right</PopoverTrigger>
17 <PopoverContent side="right">
18 <p class="text-sm">Positioned to the right</p>
19 </PopoverContent>
20 </Popover>
21
22 <Popover>
23 <PopoverTrigger variant="outline">Bottom</PopoverTrigger>
24 <PopoverContent side="bottom">
25 <p class="text-sm">Positioned below trigger</p>
26 </PopoverContent>
27 </Popover>
28
29 <Popover>
30 <PopoverTrigger variant="outline">Left</PopoverTrigger>
31 <PopoverContent side="left">
32 <p class="text-sm">Positioned to the left</p>
33 </PopoverContent>
34 </Popover>
35</div>Alignment Options
Align popover to start, center, or end of trigger.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<div class="flex flex-wrap gap-4">
8 <Popover>
9 <PopoverTrigger variant="outline">Align Start</PopoverTrigger>
10 <PopoverContent align="start">
11 <p class="text-sm">Aligned to start of trigger</p>
12 </PopoverContent>
13 </Popover>
14
15 <Popover>
16 <PopoverTrigger variant="outline">Align Center</PopoverTrigger>
17 <PopoverContent align="center">
18 <p class="text-sm">Aligned to center (default)</p>
19 </PopoverContent>
20 </Popover>
21
22 <Popover>
23 <PopoverTrigger variant="outline">Align End</PopoverTrigger>
24 <PopoverContent align="end">
25 <p class="text-sm">Aligned to end of trigger</p>
26 </PopoverContent>
27 </Popover>
28</div>Trigger Variants
Different trigger styles for various use cases.
1
2<script lang="ts">
3 import { PopoverPrimitives } from "@kareyes/aether";
4 const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
5</script>
6
7<div class="flex flex-wrap gap-4">
8 <Popover>
9 <PopoverTrigger variant="button">Button Style</PopoverTrigger>
10 <PopoverContent>
11 <p class="text-sm">Primary button trigger</p>
12 </PopoverContent>
13 </Popover>
14
15 <Popover>
16 <PopoverTrigger variant="outline">Outline Style</PopoverTrigger>
17 <PopoverContent>
18 <p class="text-sm">Outlined button trigger</p>
19 </PopoverContent>
20 </Popover>
21
22 <Popover>
23 <PopoverTrigger variant="ghost">Ghost Style</PopoverTrigger>
24 <PopoverContent>
25 <p class="text-sm">Ghost button trigger</p>
26 </PopoverContent>
27 </Popover>
28
29 <Popover>
30 <PopoverTrigger variant="link">Link Style</PopoverTrigger>
31 <PopoverContent>
32 <p class="text-sm">Link-style trigger</p>
33 </PopoverContent>
34 </Popover>
35
36 <Popover>
37 <PopoverTrigger variant="default" class="rounded-full p-2 hover:bg-accent">
38 <Info class="h-4 w-4" />
39 </PopoverTrigger>
40 <PopoverContent size="sm">
41 <p class="text-sm">Custom icon trigger</p>
42 </PopoverContent>
43 </Popover>
44</div>With Arrow Indicator
Add a visual arrow pointing to the trigger element.
1
2
3<script lang="ts">
4 import { PopoverPrimitives } from "@kareyes/aether";
5 const { Popover, PopoverTrigger, PopoverContent, PopoverArrow } = PopoverPrimitives;
6</script>
7
8<div class="flex flex-wrap gap-4">
9 <Popover>
10 <PopoverTrigger variant="button">With Arrow</PopoverTrigger>
11 <PopoverContent>
12 <PopoverArrow class="fill-popover" />
13 <div class="space-y-2">
14 <h4 class="font-medium leading-none">Arrow Indicator</h4>
15 <p class="text-sm text-muted-foreground">
16 The arrow clearly points to the trigger element.
17 </p>
18 </div>
19 </PopoverContent>
20 </Popover>
21
22 <Popover>
23 <PopoverTrigger variant="outline">Arrow Top</PopoverTrigger>
24 <PopoverContent side="top">
25 <PopoverArrow class="fill-popover" />
26 <p class="text-sm">Arrow on the bottom when placed on top</p>
27 </PopoverContent>
28 </Popover>
29</div>Advanced Examples
Real-world use cases with complex content and interactions.
Form in Popover
User Profile Popover
Action Menu
With Close Button
Contextual Help
Multiple Popovers
1
2<script lang="ts">
3 import { Card, Button, Input, Label, PopoverPrimitives } from "@kareyes/aether";
4 import { Settings, User, MoreVertical, HelpCircle, Calendar, Bell, Share2 } from "@kareyes/aether/icons";
5 const { Popover, PopoverTrigger, PopoverContent, PopoverClose } = PopoverPrimitives;
6</script>
7
8<!-- Form in Popover -->
9<Popover>
10 <PopoverTrigger variant="button">
11 <Settings class="mr-2 h-4 w-4" />
12 Dimensions
13 </PopoverTrigger>
14 <PopoverContent class="w-80">
15 <div class="grid gap-4">
16 <div class="space-y-2">
17 <h4 class="font-medium leading-none">Dimensions</h4>
18 <p class="text-sm text-muted-foreground">Set the dimensions for the layer.</p>
19 </div>
20 <div class="grid gap-2">
21 <div class="grid grid-cols-3 items-center gap-4">
22 <Label for="width">Width</Label>
23 <Input id="width" value="100%" class="col-span-2 h-8" />
24 </div>
25 <div class="grid grid-cols-3 items-center gap-4">
26 <Label for="height">Height</Label>
27 <Input id="height" value="25px" class="col-span-2 h-8" />
28 </div>
29 </div>
30 </div>
31 </PopoverContent>
32</Popover>
33
34<!-- User Profile Popover -->
35<Popover>
36 <PopoverTrigger variant="default" class="rounded-full">
37 <div class="flex items-center gap-2 px-3 py-2 rounded-full hover:bg-accent">
38 <User class="h-5 w-5" />
39 <span class="text-sm font-medium">John Doe</span>
40 </div>
41 </PopoverTrigger>
42 <PopoverContent variant="elevated" size="sm" align="start">
43 <div class="flex flex-col gap-3">
44 <div class="flex items-center gap-3">
45 <div class="flex h-10 w-10 items-center justify-center rounded-full bg-primary text-primary-foreground">
46 <User class="h-5 w-5" />
47 </div>
48 <div>
49 <p class="font-medium">John Doe</p>
50 <p class="text-sm text-muted-foreground">john@example.com</p>
51 </div>
52 </div>
53 <div class="flex flex-col gap-1">
54 <Button variant="ghost" size="sm" class="justify-start">Profile</Button>
55 <Button variant="ghost" size="sm" class="justify-start">Settings</Button>
56 <Button variant="ghost" size="sm" class="justify-start">Sign out</Button>
57 </div>
58 </div>
59 </PopoverContent>
60</Popover>
61
62<!-- With Close Button -->
63<Popover>
64 <PopoverTrigger variant="button">Open</PopoverTrigger>
65 <PopoverContent>
66 <div class="space-y-4">
67 <div class="space-y-2">
68 <h4 class="font-medium leading-none">Confirmation</h4>
69 <p class="text-sm text-muted-foreground">Are you sure you want to proceed?</p>
70 </div>
71 <div class="flex gap-2">
72 <PopoverClose class="flex-1">
73 <Button variant="outline" size="sm" class="w-full">Cancel</Button>
74 </PopoverClose>
75 <PopoverClose class="flex-1">
76 <Button size="sm" class="w-full">Confirm</Button>
77 </PopoverClose>
78 </div>
79 </div>
80 </PopoverContent>
81</Popover>Features
- 🎨 5 Visual Variants: Default, Bordered, Elevated, Minimal, Ghost
- 📏 4 Size Options: Small, Default, Large, Auto
- ✨ 5 Animation Styles: Default (combined), Fade, Scale, Slide, None
- 🎯 Trigger Variants: Default, Button, Outline, Ghost, Link
- ♿ Fully Accessible: Built on bits-ui primitives with keyboard navigation
- 🎭 Customizable: Extensive styling options with Tailwind
- 🔄 Reactive: Svelte 5 runes for optimal performance
- 📍 Smart Positioning: Automatic collision detection and placement
Implementation Details
The Popover component is built using tailwind-variants (tv) for a robust variant system and bits-ui for accessible primitives.
Component Architecture
PopoverContent Component
- Uses
tv()function for variant management - 5 visual variants with distinct styling:
- Default: Standard shadow with border
- Bordered: Emphasized border with lighter shadow
- Elevated: No border with larger shadow
- Minimal: Subtle appearance with light border
- Ghost: Transparent background without shadow
- 4 size options for flexible layouts
- 5 animation options for different entry/exit effects
- Exported types:
PopoverContentVariant,PopoverContentSize,PopoverContentAnimation
PopoverTrigger Component
- 5 trigger variants for different use cases:
- Default: Unstyled (for custom triggers)
- Button: Primary button style
- Outline: Outlined button style
- Ghost: Ghost button style
- Link: Link style with underline
- 3 size options (sm, default, lg)
- Exported types:
PopoverTriggerVariant,PopoverTriggerSize
Usage
Basic Example
<script lang="ts">
import { PopoverPrimitives } from "@kareyes/aether";
const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
</script>
<Popover>
<PopoverTrigger variant="button">Open Popover</PopoverTrigger>
<PopoverContent>
<div class="space-y-2">
<h4 class="font-medium leading-none">Dimensions</h4>
<p class="text-sm text-muted-foreground">
Set the dimensions for the layer.
</p>
</div>
</PopoverContent>
</Popover>
With Custom Trigger
<Popover>
<PopoverTrigger variant="default" class="rounded-full w-10 h-10 bg-primary text-primary-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="1"/>
<circle cx="12" cy="5" r="1"/>
<circle cx="12" cy="19" r="1"/>
</svg>
</PopoverTrigger>
<PopoverContent variant="elevated" size="sm">
<p class="text-sm">Additional options</p>
</PopoverContent>
</Popover>
With Positioning
<Popover>
<PopoverTrigger variant="outline">Open</PopoverTrigger>
<PopoverContent side="top" align="start" sideOffset={8}>
<p>This popover appears above the trigger</p>
</PopoverContent>
</Popover>
With Controlled State
<script lang="ts">
import { PopoverPrimitives } from "@kareyes/aether";
const { Popover, PopoverTrigger, PopoverContent, PopoverClose } = PopoverPrimitives;
import { Button } from "@kareyes/aether";
let open = $state(false);
</script>
<Popover bind:open>
<PopoverTrigger variant="button">Toggle</PopoverTrigger>
<PopoverContent>
<div class="space-y-4">
<p class="text-sm">Popover is {open ? 'open' : 'closed'}</p>
<PopoverClose>
<Button variant="outline" size="sm">Close</Button>
</PopoverClose>
</div>
</PopoverContent>
</Popover>
Content Variants
Default Variant
The standard popover style with medium shadow and border.
<PopoverContent variant="default">
Standard popover appearance
</PopoverContent>
Bordered Variant
Emphasized border with lighter shadow for a more defined look.
<PopoverContent variant="bordered">
Popover with emphasized border
</PopoverContent>
Elevated Variant
No border with larger shadow for a floating appearance.
<PopoverContent variant="elevated">
Floating popover with elevation
</PopoverContent>
Minimal Variant
Subtle appearance with light border and small shadow.
<PopoverContent variant="minimal">
Minimal, understated popover
</PopoverContent>
Ghost Variant
Transparent background without shadow for custom styling.
<PopoverContent variant="ghost" class="bg-gradient-to-r from-purple-500 to-pink-500 text-white">
Custom styled popover
</PopoverContent>
Size Variants
Small
Compact popover for minimal content.
<PopoverContent size="sm">
<p class="text-sm">Compact content</p>
</PopoverContent>
Default
Standard size for most use cases.
<PopoverContent size="default">
<p>Standard content</p>
</PopoverContent>
Large
Spacious popover for detailed content.
<PopoverContent size="lg">
<h3 class="text-lg font-semibold mb-2">Detailed Information</h3>
<p>More content with extra space</p>
</PopoverContent>
Auto
Auto-width popover with default padding.
<PopoverContent size="auto" class="w-auto">
<p>Content determines width</p>
</PopoverContent>
Animation Variants
Default Animation
Combined fade, zoom, and slide animations.
<PopoverContent animation="default">
Smooth combined animation
</PopoverContent>
Fade Animation
Simple fade in/out effect.
<PopoverContent animation="fade">
Subtle fade animation
</PopoverContent>
Scale Animation
Zoom in/out effect.
<PopoverContent animation="scale">
Scale animation
</PopoverContent>
Slide Animation
Slide from the direction of placement.
<PopoverContent animation="slide">
Slide-in animation
</PopoverContent>
No Animation
Instant show/hide without animation.
<PopoverContent animation="none">
No animation
</PopoverContent>
Trigger Variants
Button Trigger
Primary button style for prominent actions.
<PopoverTrigger variant="button">
Click Me
</PopoverTrigger>
Outline Trigger
Outlined style for secondary actions.
<PopoverTrigger variant="outline">
More Options
</PopoverTrigger>
Ghost Trigger
Subtle hover effect without background.
<PopoverTrigger variant="ghost">
Hover Me
</PopoverTrigger>
Link Trigger
Link style with underline on hover.
<PopoverTrigger variant="link">
Learn More
</PopoverTrigger>
Advanced Examples
Form in Popover
<script lang="ts">
import { PopoverPrimitives } from "@kareyes/aether";
const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
import { Button } from "@kareyes/aether";
import { Input } from "@kareyes/aether";
import { Label } from "@kareyes/aether";
let width = $state("100%");
let maxWidth = $state("300px");
let height = $state("25px");
let maxHeight = $state("none");
</script>
<Popover>
<PopoverTrigger variant="button">Open Dimensions</PopoverTrigger>
<PopoverContent class="w-80">
<div class="grid gap-4">
<div class="space-y-2">
<h4 class="font-medium leading-none">Dimensions</h4>
<p class="text-sm text-muted-foreground">
Set the dimensions for the layer.
</p>
</div>
<div class="grid gap-2">
<div class="grid grid-cols-3 items-center gap-4">
<Label for="width">Width</Label>
<Input id="width" bind:value={width} class="col-span-2 h-8" />
</div>
<div class="grid grid-cols-3 items-center gap-4">
<Label for="maxWidth">Max. width</Label>
<Input id="maxWidth" bind:value={maxWidth} class="col-span-2 h-8" />
</div>
<div class="grid grid-cols-3 items-center gap-4">
<Label for="height">Height</Label>
<Input id="height" bind:value={height} class="col-span-2 h-8" />
</div>
<div class="grid grid-cols-3 items-center gap-4">
<Label for="maxHeight">Max. height</Label>
<Input id="maxHeight" bind:value={maxHeight} class="col-span-2 h-8" />
</div>
</div>
</div>
</PopoverContent>
</Popover>
User Profile Popover
<script lang="ts">
import { PopoverPrimitives } from "@kareyes/aether";
const { Popover, PopoverTrigger, PopoverContent } = PopoverPrimitives;
import { Avatar } from "@kareyes/aether";
import { Button } from "@kareyes/aether";
</script>
<Popover>
<PopoverTrigger variant="default">
<Avatar src="/avatar.jpg" alt="User" />
</PopoverTrigger>
<PopoverContent variant="elevated" size="sm" align="end">
<div class="flex flex-col gap-3">
<div class="flex items-center gap-3">
<Avatar src="/avatar.jpg" alt="User" class="h-12 w-12" />
<div>
<p class="font-medium">John Doe</p>
<p class="text-sm text-muted-foreground">john@example.com</p>
</div>
</div>
<div class="flex flex-col gap-1">
<Button variant="ghost" size="sm" class="justify-start">Profile</Button>
<Button variant="ghost" size="sm" class="justify-start">Settings</Button>
<Button variant="ghost" size="sm" class="justify-start">Sign out</Button>
</div>
</div>
</PopoverContent>
</Popover>
Action Menu Popover
<Popover>
<PopoverTrigger variant="ghost" size="sm">
<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="1"/>
<circle cx="12" cy="5" r="1"/>
<circle cx="12" cy="19" r="1"/>
</svg>
</PopoverTrigger>
<PopoverContent variant="minimal" size="auto" class="p-1 w-40">
<div class="flex flex-col">
<button class="px-3 py-2 text-sm hover:bg-accent rounded text-left">Edit</button>
<button class="px-3 py-2 text-sm hover:bg-accent rounded text-left">Duplicate</button>
<button class="px-3 py-2 text-sm hover:bg-accent rounded text-left">Archive</button>
<div class="h-px bg-border my-1"></div>
<button class="px-3 py-2 text-sm hover:bg-accent rounded text-left text-destructive">Delete</button>
</div>
</PopoverContent>
</Popover>
Props Reference
Popover (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
open |
boolean |
false |
Controlled open state |
onOpenChange |
(open: boolean) => void |
- | Callback when open state changes |
...restProps |
PopoverPrimitive.RootProps |
- | All bits-ui Popover.Root props |
PopoverTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
'default' | 'button' | 'outline' | 'ghost' | 'link' |
'default' |
Trigger visual style |
size |
'default' | 'sm' | 'lg' |
'default' |
Trigger size |
class |
string |
- | Additional CSS classes |
ref |
HTMLButtonElement | null |
null |
Reference to the trigger element |
...restProps |
PopoverPrimitive.TriggerProps |
- | All bits-ui Popover.Trigger props |
PopoverContent
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
'default' | 'bordered' | 'elevated' | 'minimal' | 'ghost' |
'default' |
Content visual style |
size |
'sm' | 'default' | 'lg' | 'auto' |
'default' |
Content size |
animation |
'default' | 'fade' | 'scale' | 'slide' | 'none' |
'default' |
Entry/exit animation |
side |
'top' | 'right' | 'bottom' | 'left' |
'bottom' |
Preferred placement side |
align |
'start' | 'center' | 'end' |
'center' |
Alignment relative to trigger |
sideOffset |
number |
4 |
Distance from trigger in pixels |
alignOffset |
number |
0 |
Offset along alignment axis |
class |
string |
- | Additional CSS classes |
ref |
HTMLDivElement | null |
null |
Reference to the content element |
portalProps |
PopoverPrimitive.PortalProps |
- | Props for the portal component |
...restProps |
PopoverPrimitive.ContentProps |
- | All bits-ui Popover.Content props |
PopoverClose
Inherits all props from bits-ui Popover.Close. Typically used as a wrapper around buttons or interactive elements to close the popover.
PopoverArrow
| Prop | Type | Default | Description |
|---|---|---|---|
class |
string |
- | Additional CSS classes |
...restProps |
PopoverPrimitive.ArrowProps |
- | All bits-ui Popover.Arrow props |
Accessibility
The Popover component follows WAI-ARIA guidelines:
Keyboard Navigation
- Tab: Move focus to/from the trigger
- Space/Enter: Open/close the popover when trigger is focused
- Escape: Close the popover when content is open
- Tab (when open): Trap focus within popover or allow cycling based on configuration
Screen Reader Support
- Proper ARIA attributes (
aria-haspopup,aria-expanded,aria-controls) - Content is announced when popover opens
- Focus management handles proper announcements
- Trigger-content relationship is clearly communicated
Best Practices
- Descriptive Triggers: Use clear, descriptive text or labels
- Focus Management: Ensure focus returns to trigger on close
- Keyboard Accessible: All interactive elements should be keyboard accessible
- Sufficient Contrast: Ensure content meets WCAG contrast requirements
- Mobile Friendly: Consider touch targets and mobile interactions
Styling Tips
Custom Width
<PopoverContent size="auto" class="w-96">
Custom width content
</PopoverContent>
Custom Colors
<PopoverContent variant="ghost" class="bg-blue-500 text-white border border-blue-600">
Custom colored popover
</PopoverContent>
No Padding
<PopoverContent class="p-0">
<img src="/image.jpg" alt="Full bleed image" class="rounded-md" />
</PopoverContent>
With Arrow
<script lang="ts">
import { PopoverPrimitives } from "@kareyes/aether";
const { Popover, PopoverTrigger, PopoverContent, PopoverArrow } = PopoverPrimitives;
</script>
<Popover>
<PopoverTrigger variant="button">Show Arrow</PopoverTrigger>
<PopoverContent>
<PopoverArrow class="fill-popover" />
<p>Popover with arrow indicator</p>
</PopoverContent>
</Popover>
Common Patterns
Dropdown Menu Alternative
Use popover for custom dropdown menus with more control than standard dropdowns.
Contextual Help
Display additional information or help text without navigating away.
Quick Actions
Show action buttons or forms in a compact overlay.
User Previews
Display user information on hover or click of avatars/names.
Settings Panels
Small configuration panels that don't warrant a full modal.
Related Components
- Dropdown Menu: For standard menu interactions
- Dialog: For modal dialogs that require user attention
- Tooltip: For simple hover hints
- Sheet: For larger side panels
- Context Menu: For right-click contextual actions