Popover
- The Popover component with context.PopoverContent
- The content for the popover.PopoverHeader
- The header for the popover.PopoverBody
- The body for the popover.PopoverFooter
- The footer for the popover.PopoverCloseButton
- The close button for the popover.PopoverAnchor
- The anchor for the popover.PopoverArrow
- The arrow for the popover.PopoverTrigger
- The trigger for the popover.
import {
Popover,
PopoverContent,
PopoverHeader,
PopoverBody,
PopoverFooter,
PopoverCloseButton,
PopoverAnchor,
PopoverArrow,
PopoverTrigger
} from "@dreamy-ui/react";
When Popover opens, focus is sent to PopoverContent. When it closes, focus is returned to the trigger.
For arrow, you can use hasArrow
prop or use <PopoverArrow />
component inside <PopoverContent />
.
export function BasicPopover() {
return (
<Popover hasArrow>
<PopoverTrigger>
<Button variant={"primary"}>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"primary"}>Delete</Button>
</PopoverFooter>
</PopoverContent>
</Popover>
);
}
Most of the time, you'll want to control the popover's open state. Use useControllable
hook to do that.
export function ControlledPopover() {
const { isOpen, onOpen, onClose } = useControllable();
const handleDelete = useCallback(() => {
/**
* Handle delete logic...
*/
onClose();
}, [onClose]);
return (
<Popover isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
<PopoverTrigger>
<Button variant={"primary"}>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"solid"} onClick={onClose}>
Cancel
</Button>
<Button variant={"primary"} onClick={handleDelete}>
Delete
</Button>
</PopoverFooter>
</PopoverContent>
</Popover>
);
}
You can set the initial focus element using initialFocusRef
prop.
export function FocusPopover() {
const { isOpen, onOpen, onClose } = useControllable();
const initialFocusRef = useRef<HTMLButtonElement>(null);
return (
<Popover
isOpen={isOpen}
onOpen={onOpen}
onClose={onClose}
initialFocusRef={initialFocusRef}
>
<PopoverTrigger>
<Button variant={"primary"}>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"solid"} onClick={onClose} ref={initialFocusRef}>
Cancel
</Button>
<Button variant={"primary"}>Delete</Button>
</PopoverFooter>
</PopoverContent>
</Popover>
);
}
You can customize the placement of the popover relative to the trigger element using the placement
prop.
export function PlacementPopovers() {
return (
<Flex wrapped gap={5}>
{(
[
"top",
"bottom",
"left",
"right",
"top-start",
"top-end",
"bottom-start",
"bottom-end",
"left-start",
"left-end",
"right-start",
"right-end"
] satisfies PlacementWithLogical[]
).map((placement) => (
<PlacementPopover key={placement} placement={placement} />
))}
</Flex>
);
}
export function PlacementPopover({ placement }: { placement: PlacementWithLogical }) {
return (
<Popover placement={placement}>
<PopoverTrigger>
<Button variant={"primary"}>{placement}</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"primary"}>Delete</Button>
</PopoverFooter>
</PopoverContent>
</Popover>
);
}
Use size
prop to set the size of the popover.
export function SizePopovers() {
return (
<Flex
wrapped
gap={5}
>
{(
["sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl", "8xl"]
).map((size) => (
<SizePopover key={size} size={size} />
))}
</Flex>
);
}
export function SizePopover({ size }: { size: string }) {
return (
<Popover size={size as any}>
<PopoverTrigger>
<Button
variant={"primary"}
w="fit-content"
>
{size}
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"primary"}>Delete</Button>
</PopoverFooter>
</PopoverContent>
</Popover>
);
}
You can customize the reduce motion behavior of the popover using the reduceMotion
prop.
<Popover reduceMotion>
<PopoverTrigger>
<Button variant={"primary"}>Reduced Motion</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Delete Post</PopoverHeader>
<PopoverBody>
Are you sure you want to delete this post? This action cannot be undone.
</PopoverBody>
<PopoverFooter>
<Button variant={"primary"}>Delete</Button>
</PopoverFooter>
</PopoverContent>
</Popover>