Popover
Popover is a container component that can overlay other components on page.
Usage#
import { Popover } from '@primereact/ui/popover';<Popover.Root>
<Popover.Trigger></Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={12} side="bottom" align="start">
<Popover.Popup>
<Popover.Content></Popover.Content>
<Popover.Close></Popover.Close>
<Popover.Arrow />
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
</Popover.Root>Examples#
Controlled#
Use the open and onOpenChange props to control the popover state.
'use client';
import { Times } from '@primeicons/react/times';
import { usePopoverOpenChangeEvent } from '@primereact/types/shared/popover';
import { Button } from '@primereact/ui/button';
import { InputText } from '@primereact/ui/inputtext';
import { Popover } from '@primereact/ui/popover';
import React from 'react';
export default function ControlledDemo() {
const [open, setOpen] = React.useState(false);
return (
<div className="flex gap-4 justify-center items-center">
<Button onClick={() => setOpen(!open)}>Show Popover</Button>
<Popover.Root open={open} onOpenChange={(e: usePopoverOpenChangeEvent) => setOpen(e.value)}>
<Popover.Trigger>Popover Trigger</Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={12}>
<Popover.Popup className="max-w-72 w-full">
<Popover.Arrow />
<Popover.Header>
<Popover.Title>Create a New Workspace</Popover.Title>
<Popover.Close as={Button} severity="secondary" variant="text" size="small" iconOnly>
<Times />
</Popover.Close>
</Popover.Header>
<Popover.Content>
<Popover.Description>Name your workspace to get started. You can always change this later.</Popover.Description>
<InputText placeholder="Workspace Name" className="mt-3 w-full" />
</Popover.Content>
<Popover.Footer>
<span className="text-xs text-surface-500 dark:text-surface-400 ">1 of 3</span>
<div className="flex-1 flex items-center justify-end gap-2">
<Button severity="secondary" variant="outlined" size="small">
Back
</Button>
<Button size="small">Next</Button>
</div>
</Popover.Footer>
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
</Popover.Root>
</div>
);
}
Alignment#
Use the side and align props to align the popover. To give an offset to the popover, use the sideOffset and alignOffset props.
'use client';
import { Times } from '@primeicons/react/times';
import { Button } from '@primereact/ui/button';
import { InputText } from '@primereact/ui/inputtext';
import { Popover } from '@primereact/ui/popover';
import * as React from 'react';
const sides = ['top', 'right', 'bottom', 'left'] as const;
const aligns = ['start', 'center', 'end'] as const;
export default function AlignmentDemo() {
const [side, setSide] = React.useState<(typeof sides)[number]>('bottom');
const [align, setAlign] = React.useState<(typeof aligns)[number]>('start');
return (
<div className="flex flex-col items-center min-h-60">
<div className="flex flex-col items-center justify-center gap-4 **:capitalize">
<div className="flex items-center justify-center gap-4 ">
{sides.map((s: (typeof sides)[number]) => (
<Button
key={s}
severity={side === s ? 'primary' : 'secondary'}
variant={side === s ? undefined : 'outlined'}
size="small"
onClick={() => setSide(s)}
>
{s}
</Button>
))}
</div>
<div className="flex items-center justify-center gap-4">
{aligns.map((a: (typeof aligns)[number]) => (
<Button
key={a}
severity={align === a ? 'primary' : 'secondary'}
variant={align === a ? undefined : 'outlined'}
size="small"
onClick={() => setAlign(a)}
>
{a}
</Button>
))}
</div>
</div>
<Popover.Root open>
<Popover.Trigger className="my-60 px-2.5 h-8 rounded-lg border border-surface flex items-center justify-center gap-2 bg-surface-0 dark:bg-surface-950 hover:bg-surface-100 dark:hover:bg-surface-900 data-open:bg-surface-100 dark:data-open:bg-surface-900 transition-colors text-sm font-medium">
Show Popover
</Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={12} side={side} align={align}>
<Popover.Popup className="max-w-72 w-full">
<Popover.Arrow />
<Popover.Header>
<Popover.Title>Create a New Workspace</Popover.Title>
<Popover.Close as={Button} severity="secondary" variant="text" size="small" iconOnly>
<Times />
</Popover.Close>
</Popover.Header>
<Popover.Content>
<Popover.Description>Name your workspace to get started. You can always change this later.</Popover.Description>
<InputText placeholder="Workspace Name" className="mt-3 w-full" />
</Popover.Content>
<Popover.Footer>
<span className="text-xs text-surface-500 dark:text-surface-400 ">1 of 3</span>
<div className="flex-1 flex items-center justify-end gap-2">
<Button severity="secondary" variant="outlined" size="small">
Back
</Button>
<Button size="small">Next</Button>
</div>
</Popover.Footer>
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
</Popover.Root>
</div>
);
}
Accessibility#
Screen Reader#
Popover component uses dialog role and since any attribute is passed to the root element, attributes like aria-label or aria-labelledby can be defined 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.
Popover Keyboard Support#
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. |