Popover is a container component that can overlay other components on page.
import { Popover } from 'primereact/popover';
<Popover>
<Popover.Trigger></Popover.Trigger>
<Popover.Portal>
<Popover.Content>
<Popover.Close />
</Popover.Content>
</Popover.Portal>
</Popover>
import { InputText } from 'primereact/inputtext';
import { Label } from 'primereact/label';
import { Popover } from 'primereact/popover';
export default function BasicDemo() {
return (
<div className="card flex items-center justify-center">
<Popover>
<Popover.Trigger>Show Popover</Popover.Trigger>
<Popover.Portal>
<Popover.Content>
<div className="flex flex-col gap-2 p-2 max-w-xs">
<p className="text-lg font-semibold mb-0.5">Dimensions</p>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="width">Width</Label>
<InputText id="width" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="maxWidth">Max. width</Label>
<InputText id="maxWidth" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="height">Height</Label>
<InputText id="height" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="maxHeight">Max. height</Label>
<InputText id="maxHeight" fluid />
</div>
</div>
<Popover.Close className="absolute top-4 right-4" />
</Popover.Content>
</Popover.Portal>
</Popover>
</div>
);
}
Use the open
and onOpenChange
props to control the popover state.
import { usePopoverOpenChangeEvent } from '@primereact/types/shared/popover';
import { Button } from 'primereact/button';
import { InputText } from 'primereact/inputtext';
import { Label } from 'primereact/label';
import { Popover } from 'primereact/popover';
import React from 'react';
function ControlledDemo() {
const [open, setOpen] = React.useState(false);
return (
<div className="card flex gap-4 justify-center items-center">
<Button onClick={() => setOpen(!open)}>Show Popover</Button>
<Popover open={open} onOpenChange={(e: usePopoverOpenChangeEvent) => setOpen(e.value)}>
<Popover.Trigger>Popover Trigger</Popover.Trigger>
<Popover.Portal>
<Popover.Content>
<div className="flex flex-col gap-2 p-2 max-w-xs">
<p className="text-lg font-semibold mb-0.5">Dimensions</p>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="width">Width</Label>
<InputText id="width" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="maxWidth">Max. width</Label>
<InputText id="maxWidth" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="height">Height</Label>
<InputText id="height" fluid />
</div>
<div className="grid grid-cols-2 items-center">
<Label htmlFor="maxHeight">Max. height</Label>
<InputText id="maxHeight" fluid />
</div>
</div>
<Popover.Close className="absolute top-4 right-4" />
</Popover.Content>
</Popover.Portal>
</Popover>
</div>
);
}
export default ControlledDemo;
import { usePopoverOpenChangeEvent } from '@primereact/types/shared/popover';
import { Popover } from 'primereact/popover';
import React from 'react';
const members = [
{ name: 'Amy Elsner', image: 'amyelsner.png', email: '[email protected]', role: 'Owner' },
{ name: 'Bernardo Dominic', image: 'bernardodominic.png', email: '[email protected]', role: 'Editor' },
{ name: 'Ioni Bowcher', image: 'ionibowcher.png', email: '[email protected]', role: 'Viewer' }
];
function SelectDataDemo() {
const [selectedMember, setSelectedMember] = React.useState<(typeof members)[0] | null>(members[0]);
const [open, setOpen] = React.useState(false);
return (
<div className="card flex justify-center">
<Popover open={open} onOpenChange={(e: usePopoverOpenChangeEvent) => setOpen(e.value)}>
<Popover.Trigger className="min-w-48">{selectedMember?.name}</Popover.Trigger>
<Popover.Portal>
<Popover.Content>
<div className="flex flex-col gap-4">
<div>
<span className="font-medium block mb-2">Team Members</span>
<ul className="list-none p-0 m-0 flex flex-col">
{members.map((member) => (
<li
key={member.name}
className="flex items-center gap-2 px-2 py-3 hover:bg-emphasis cursor-pointer rounded-border"
onClick={() => {
setSelectedMember(member);
setOpen(false);
}}
>
<img src={`https://primefaces.org/cdn/primevue/images/avatar/${member.image}`} style={{ width: '32px' }} />
<div>
<span className="font-medium">{member.name}</span>
<div className="text-sm text-surface-500 dark:text-surface-400">{member.email}</div>
</div>
</li>
))}
</ul>
</div>
</div>
</Popover.Content>
</Popover.Portal>
</Popover>
</div>
);
}
export default SelectDataDemo;
Popover component uses dialog role and since any attribute is passed to the root element you may define attributes like aria-label or aria-labelledby to describe the popup contents. In addition aria-modal is added since focus is kept within the popup.
Popover adds aria-expanded state attribute and aria-controls to the trigger so that the relation between the trigger and the popup is defined.
When the popup gets opened, the first focusable element receives the focus and this can be customized by adding autofocus to an element within the popup.
Key | Function |
---|---|
tab | Moves focus to the next the focusable element within the popup. |
shift + tab | Moves focus to the previous the focusable element within the popup. |
escape | Closes the popup and moves focus to the trigger. |