Popover
A popup of content anchored to a trigger, as a compound component on Base UI's popover. Use it for something a person reads or fills in; a list of actions is a Menu.
tsx
import { Popover } from '@basmilius/react-ui';tsx
import { Bell } from 'lucide-react';
import { Button, IconButton, Popover } from '@basmilius/react-ui';
export default function PopoverDemo() {
return (
<Popover.Root>
<IconButton icon={Bell} label="Notifications" render={<Popover.Trigger />} />
<Popover.Popup className="w-72 p-3">
<Popover.Title className="text-sm font-medium text-text">Notifications</Popover.Title>
<Popover.Description className="mt-1 text-xs text-text-muted">Nothing new since you last looked.</Popover.Description>
<div className="mt-3 flex justify-end">
<Popover.Close render={<Button size="sm" variant="secondary" />}>Close</Popover.Close>
</div>
</Popover.Popup>
</Popover.Root>
);
}Parts
| Part | What it is |
|---|---|
Popover.Root | Holds the open state: open and onOpenChange, or defaultOpen. |
Popover.Trigger | The button that opens it. |
Popover.Popup | The portal, the positioner and the popup in one part. |
Popover.Title | A heading, which names the popup for a screen reader. |
Popover.Description | A sentence that describes it. |
Popover.Close | A button that closes it. |
Variants
variant decides the surface. menu, the default, is the padded card menus use. picker is a card whose content runs to its edges, such as a search field on top of a list. plain leaves the surface to you.
tsx
import { useState } from 'react';
import { Button, Input, Popover } from '@basmilius/react-ui';
const PEOPLE = ['Ada Lovelace', 'Alan Turing', 'Grace Hopper', 'Katherine Johnson', 'Margaret Hamilton'];
export default function PopoverPicker() {
const [query, setQuery] = useState('');
const matches = PEOPLE.filter((person) => person.toLowerCase().includes(query.toLowerCase()));
return (
<Popover.Root>
<Popover.Trigger render={<Button variant="secondary" />}>Assign</Popover.Trigger>
<Popover.Popup variant="picker">
<div className="border-b border-border p-1">
<Input
size="sm"
aria-label="Find a person"
placeholder="Find a person"
className="border-transparent"
value={query}
onChange={(event) => setQuery(event.target.value)}
/>
</div>
<ul className="max-h-60 overflow-auto p-1">
{matches.map((person) => (
<li key={person} className="rounded-md px-2.5 py-1.5 text-sm text-text hover:bg-surface-hover">
{person}
</li>
))}
</ul>
</Popover.Popup>
</Popover.Root>
);
}Placement
A popover opens under its trigger, lined up with its start, 8 pixels away. Popover.Popup takes the same placement props as Menu.Popup.
Keyboard
Opening moves focus into the popup, Escape closes it, and focus goes back to the trigger.
PopoverPopupProps and PopupVariant are exported types.