A lightweight, fully-featured, accessible, and customizable popover component for React apps.
- π― 12 placement options with smart auto-positioning
- π¨ Smooth animations and transitions
- π Multiple trigger types (click, hover, focus)
- π± Responsive and mobile-friendly
- βΏ Accessible (WAI-ARIA compliant)
- ποΈ Controlled and uncontrolled modes
- π― Auto-placement to stay within viewport
- ποΈ Highly customizable styling
- π¦ TypeScript support
- β‘ Optimized performance
- β No external dependencies
npm install @atawi/react-popoverimport { Popover } from "@atawi/react-popover";
import "@atawi/react-popover/dist/style.css"; // Optional: Import default styles
function App() {
return (
<Popover
trigger={<button>Click me</button>}
content={<div>Popover content</div>}
placement="top"
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
trigger |
ReactNode |
- | The element that triggers the popover |
content |
ReactNode |
- | The content to display in the popover |
placement |
PopoverPlacement |
'top' |
Preferred placement of the popover |
offset |
number |
8 |
Distance between trigger and popover |
className |
string |
'' |
Class name for the popover wrapper |
containerClassName |
string |
'' |
Class name for the container |
contentClassName |
string |
'' |
Class name for the content wrapper |
animatedClassName |
string |
'' |
Custom class name for animated state |
enterClassName |
string |
'' |
Custom class name for enter animation |
exitClassName |
string |
'' |
Custom class name for exit animation |
open |
boolean |
- | Control popover visibility externally |
onOpenChange |
(open: boolean) => void |
- | Callback when visibility changes |
style |
CSSProperties |
- | Additional styles for the popover |
autoPlacement |
boolean |
false |
Enable automatic repositioning |
animated |
boolean |
false |
Enable enter/exit animations |
triggerType |
PopoverTrigger | PopoverTrigger[] |
'click' |
How to trigger the popover |
hoverDelay |
number |
200 |
Delay before showing on hover |
closeDelay |
number |
400 |
Delay before hiding on hover out |
closeOnScroll |
boolean |
false |
Close popover when window is scrolled |
closeOnResize |
boolean |
false |
Close popover when window is resized |
<Popover
trigger={<button>Click me</button>}
content="Simple popover content"
placement="top"
/><Popover
trigger={<button>Hover me</button>}
content="Content that stays in viewport"
placement="top"
autoPlacement
triggerType="hover"
/><Popover
trigger={<button>Animated</button>}
content="Smooth animation"
placement="right"
animated
/><Popover
trigger={<button>Interactive</button>}
content="Accessible content"
placement="bottom"
triggerType={["hover", "focus"]}
/>function ControlledExample() {
const [open, setOpen] = useState(false);
return (
<Popover
trigger={<button>Controlled</button>}
content="Controlled content"
open={open}
onOpenChange={setOpen}
/>
);
}<Popover
trigger={<button>Styled</button>}
content="Custom styled content"
className="custom-popover"
contentClassName="custom-content"
style={{ maxWidth: "300px" }}
/><Popover
trigger={<button>Custom Animation</button>}
content="Smoothly animated content"
animated
animatedClassName="my-popover-animated"
enterClassName="my-popover-enter"
exitClassName="my-popover-exit"
/>.my-popover-animated {
transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
}
.my-popover-enter {
opacity: 1;
transform: scale(1) translateY(0);
}
.my-popover-exit {
opacity: 0;
transform: scale(0.9) translateY(-8px);
}The placement prop accepts the following values:
top|top-start|top-endbottom|bottom-start|bottom-endleft|left-start|left-endright|right-start|right-end
The triggerType prop accepts:
'click'- Opens on click/tap'hover'- Opens on mouse hover'focus'- Opens on focus (keyboard navigation)- Array of the above for multiple triggers
The component uses CSS modules and provides several class names for customization:
.container- The root container.trigger- The trigger wrapper.content- The popover content wrapper.contentInner- The inner content container.animated- Applied when animations are enabled.enter- Applied during enter animation.exit- Applied during exit animation
For complete control over animations, use the animation className props:
animatedClassName- Replaces the default animated classenterClassName- Replaces the default enter classexitClassName- Replaces the default exit class
This allows you to bypass CSS modules hashing and use your own class names.
The component follows WAI-ARIA guidelines:
- Proper ARIA attributes
- Keyboard navigation support
- Focus management
- Screen reader friendly
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- IE11 (with polyfills)
Contributions are welcome! Please read our contributing guidelines before submitting a pull request.
MIT Β© Atawi