Skip to content
Browse docs

Popover

Beta

A floating panel that opens next to its trigger.

---
import Popover from "@/components/ui/popover/Popover.astro";
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.astro";
import PopoverContent from "@/components/ui/popover/PopoverContent.astro";
import PopoverTitle from "@/components/ui/popover/PopoverTitle.astro";
import PopoverDescription from "@/components/ui/popover/PopoverDescription.astro";
import PopoverClose from "@/components/ui/popover/PopoverClose.astro";
import Button from "@/components/ui/button/Button.astro";
---

<Popover>
  <PopoverTrigger>Share</PopoverTrigger>
  <PopoverContent>
    <PopoverTitle>Share this page</PopoverTitle>
    <PopoverDescription>Anyone with the link can view it.</PopoverDescription>
    <div class="flex gap-2">
      <Button size="sm">Copy link</Button>
      <PopoverClose>Done</PopoverClose>
    </div>
  </PopoverContent>
</Popover>

Installation

npx eris-ui@latest add popover
pnpm dlx eris-ui@latest add popover
bunx eris-ui@latest add popover
yarn dlx eris-ui@latest add popover

Installs @zag-js/popover, @zag-js/vanilla. Also adds button.

Placement

placement picks the side of the trigger: top, bottom, left or right, each with an optional -start or -end to line the panel up with an edge of the trigger. The default is bottom. gutter is the gap in pixels, 8 by default.

When the panel does not fit on that side, it flips to the opposite one and shifts to stay on screen. It is positioned against the viewport, so a parent with overflow: hidden does not clip it.

---
import Popover from "@/components/ui/popover/Popover.astro";
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.astro";
import PopoverContent from "@/components/ui/popover/PopoverContent.astro";
---

<div class="flex flex-wrap justify-center gap-3">
  <Popover placement="top">
    <PopoverTrigger>Top</PopoverTrigger>
    <PopoverContent class="w-44">Opens above the trigger.</PopoverContent>
  </Popover>
  <Popover placement="right">
    <PopoverTrigger>Right</PopoverTrigger>
    <PopoverContent class="w-44">Opens beside the trigger.</PopoverContent>
  </Popover>
  <Popover placement="bottom-start" gutter={16}>
    <PopoverTrigger>Bottom start</PopoverTrigger>
    <PopoverContent class="w-44">Lined up with the left edge, 16px away.</PopoverContent>
  </Popover>
</div>

By default the rest of the page stays usable: Tab moves out of the panel and on through the page. With modal, focus stays inside until the popover closes and screen readers only see the panel. Use it for a short task that should be finished or cancelled, like a rename.

---
import Popover from "@/components/ui/popover/Popover.astro";
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.astro";
import PopoverContent from "@/components/ui/popover/PopoverContent.astro";
import PopoverTitle from "@/components/ui/popover/PopoverTitle.astro";
import PopoverClose from "@/components/ui/popover/PopoverClose.astro";
import Button from "@/components/ui/button/Button.astro";
---

<Popover modal>
  <PopoverTrigger>Rename</PopoverTrigger>
  <PopoverContent>
    <PopoverTitle>Rename project</PopoverTitle>
    <input
      aria-label="Project name"
      value="eris"
      class="h-11 rounded-field border border-border bg-field px-3 outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:outline-solid"
    />
    <div class="flex gap-2">
      <Button size="sm">Save</Button>
      <PopoverClose>Cancel</PopoverClose>
    </div>
  </PopoverContent>
</Popover>

Staying open

A click outside closes the popover. Set closeOnInteractOutside={false} to keep it open until the user presses Esc or a PopoverClose.

Naming the panel

The panel is announced as a dialog. PopoverTitle gives it its name and PopoverDescription its description. If you leave the title out, give PopoverContent an aria-label.

Keyboard

Key Does
Enter or Space on the trigger Opens the popover and moves focus inside
Tab / Shift Tab Moves through the panel, then on through the page unless modal
Esc Closes the popover and returns focus to the trigger

Parts

Component Renders
Popover The root. Props: id, defaultOpen, placement, gutter, modal, closeOnInteractOutside
PopoverTrigger The button that opens it. Props: variant, size, as on Button
PopoverContent The floating panel
PopoverTitle The panel’s name, an h3
PopoverDescription The panel’s description
PopoverClose A button that closes it. Props: variant, size