Skip to main content

Popover

The Popover component displays floating content next to an anchor element. It's commonly used for complex interactive features that require more space than a tooltip but less prominence than a modal.

Import

import { Popover } from '@lazy-panda-ui/lazy-panda-ui';

Usage

import React from 'react';
import { Popover, Button } from '@lazy-panda-ui/lazy-panda-ui';

function MyComponent() {
return (
<Popover
content={
<div>
<h3>Popover Content</h3>
<p>This is the content of the popover.</p>
</div>
}
>
<Button>Click me</Button>
</Popover>
);
}

Props

NameTypeDefaultDescription
childrenReactNode-The anchor element
contentReactNode-Content to display in popover
position'top' | 'right' | 'bottom' | 'left''bottom'Preferred position
align'start' | 'center' | 'end''center'Alignment along the position axis
offsetnumber8Distance from anchor
openboolean-Controlled open state
defaultOpenbooleanfalseInitial open state
onOpenChange(open: boolean) => void-Open state change handler
trigger'click' | 'hover' | 'focus''click'How popover is triggered
closeOnClickOutsidebooleantrueClose when clicking outside
arrowbooleantrueShow arrow pointer

Examples

Basic Popover

<Popover
content={
<Stack spacing="md" p="md">
<Text weight="bold">Popover Title</Text>
<Text>This is a basic popover with some content.</Text>
</Stack>
}
>
<Button>Open Popover</Button>
</Popover>

Different Positions

function PositionExample() {
return (
<Stack direction="row" spacing="xl">
<Popover
position="top"
content="This appears above"
>
<Button>Top</Button>
</Popover>

<Popover
position="right"
content="This appears on the right"
>
<Button>Right</Button>
</Popover>

<Popover
position="bottom"
content="This appears below"
>
<Button>Bottom</Button>
</Popover>

<Popover
position="left"
content="This appears on the left"
>
<Button>Left</Button>
</Popover>
</Stack>
);
}

Hover Trigger

<Popover
trigger="hover"
content={
<Text>This popover appears on hover</Text>
}
>
<Button>Hover me</Button>
</Popover>

With Form

<Popover
content={
<Stack spacing="md" p="md" style={{ width: '300px' }}>
<Text weight="bold">Edit Profile</Text>
<Input
label="Name"
placeholder="Enter your name"
/>
<Input
label="Email"
type="email"
placeholder="Enter your email"
/>
<Button>Save Changes</Button>
</Stack>
}
>
<Button variant="outline">Edit Profile</Button>
</Popover>

Controlled Popover

function ControlledExample() {
const [open, setOpen] = React.useState(false);

return (
<Popover
open={open}
onOpenChange={setOpen}
content={
<Stack spacing="md" p="md">
<Text>Controlled popover state</Text>
<Button onClick={() => setOpen(false)}>
Close
</Button>
</Stack>
}
>
<Button onClick={() => setOpen(true)}>
{open ? 'Close' : 'Open'} Popover
</Button>
</Popover>
);
}

With Complex Content

<Popover
content={
<Stack spacing="md" p="md" style={{ width: '320px' }}>
<Stack direction="row" spacing="md" align="center">
<Avatar size="md" source={{ uri: '/user.jpg' }} />
<Stack spacing="xs">
<Text weight="bold">John Doe</Text>
<Text size="sm" color="gray">Software Engineer</Text>
</Stack>
</Stack>
<Divider />
<Stack spacing="sm">
<Button variant="ghost" leftIcon={<Icon name="message" />}>
Send Message
</Button>
<Button variant="ghost" leftIcon={<Icon name="user-plus" />}>
Add Contact
</Button>
<Button variant="ghost" leftIcon={<Icon name="block" />}>
Block User
</Button>
</Stack>
</Stack>
}
>
<Avatar
size="md"
source={{ uri: '/user.jpg' }}
style={{ cursor: 'pointer' }}
/>
</Popover>

Custom Animation

<Popover
content={
<div className="fade-in">
Animated content
</div>
}
style={{
'--popover-animation-duration': '0.2s',
}}
>
<Button>Animated Popover</Button>
</Popover>

Best Practices

  1. Keep content focused and concise
  2. Use appropriate triggers
  3. Consider mobile interactions
  4. Provide clear close options
  5. Handle overflow content
  6. Ensure keyboard accessibility
  7. Manage focus properly

API Reference

PopoverProps

interface PopoverProps {
children: ReactNode;
content: ReactNode;
position?: 'top' | 'right' | 'bottom' | 'left';
align?: 'start' | 'center' | 'end';
offset?: number;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: (open: boolean) => void;
trigger?: 'click' | 'hover' | 'focus';
closeOnClickOutside?: boolean;
arrow?: boolean;
className?: string;
style?: CSSProperties;
portal?: boolean;
portalContainer?: HTMLElement;
closeOnEscape?: boolean;
disabled?: boolean;
zIndex?: number;
}

Theme Customization

const theme = {
popover: {
background: '#ffffff',
borderRadius: '4px',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
zIndex: 1000,
arrow: {
size: '8px',
color: '#ffffff',
},
animation: {
duration: '0.2s',
timing: 'cubic-bezier(0.4, 0, 0.2, 1)',
},
},
};
  • Tooltip - For simple text hints
  • Dialog - For modal interactions
  • Menu - For dropdown menus
  • Select - For option selection