Skip to content
Agents tracked: 440 Downloads (7d): 202M down 19.5% GitHub stars: 10.4M Releases (7d): 607 Agent status: 3 with issuesSince last limit reset: Claude 28d · Codex 0d Updated Oct 21, 2026

Popover in Base UI

A popover shows floating content next to a trigger button. Base UI ships it as unstyled parts that you assemble and style yourself.

All Base UI examples Base UI: usage and stats

Popover in Base UI: screenshot of the example below running
The code below, running in Chromium on our server (Oct 12, 2026). Press Run to see it live and change it.

How it works

  1. Import the component. The example imports the Popover namespace from @base-ui/react and nests its parts: Root, Trigger, Portal, Positioner and Popup. [1]
  2. Render the popup in a portal. Popover.Portal moves the popup out of the normal page flow so it can sit above other content. sideOffset on the positioner adds a gap below the trigger. [1]
  3. Style it your way. Every part gets a className from a small stylesheet created in code. The popup fades in through the data-starting-style attribute, the same hook the official CSS uses. [2]

Run and edit it

It runs in your browser, in a sandboxed frame that cannot see this site; the packages load from esm.sh only after you press Run.

import { Popover } from '@base-ui/react';

const css = `
.trigger { height: 36px; padding: 0 16px; border: 1px solid #fff; background: #1f1f1f;
  color: #fff; font: 500 14px system-ui; border-radius: 8px; cursor: pointer; }
.trigger:focus-visible { outline: 2px solid #60a5fa; outline-offset: 2px; }
.popup { width: 240px; padding: 14px 16px; background: #fff; color: #111; border-radius: 10px;
  box-shadow: 0 10px 30px rgb(0 0 0 / 40%); font-family: system-ui; position: relative;
  transition: opacity 150ms, transform 150ms; }
.popup[data-starting-style], .popup[data-ending-style] { opacity: 0; transform: scale(0.96); }
.arrow { position: absolute; width: 12px; height: 12px; background: #fff; transform: rotate(45deg); }
.arrow[data-side='bottom'] { top: -6px; }
.title { margin: 0 0 4px; font-size: 15px; }
.desc { margin: 0; font-size: 14px; color: #444; }
`;

export default function App() {
  return (
    <div style={{ height: 360, display: 'flex', justifyContent: 'center', paddingTop: 90,
      background: '#111', boxSizing: 'border-box' }}>
      <style>{css}</style>
      <Popover.Root defaultOpen>
        <Popover.Trigger className="trigger">Notifications</Popover.Trigger>
        <Popover.Portal>
          <Popover.Positioner sideOffset={10}>
            <Popover.Popup className="popup">
              <Popover.Arrow className="arrow" />
              <Popover.Title className="title">Notifications</Popover.Title>
              <Popover.Description className="desc">
                You are all caught up. Good job!
              </Popover.Description>
            </Popover.Popup>
          </Popover.Positioner>
        </Popover.Portal>
      </Popover.Root>
    </div>
  );
}
Ctrl/⌘ + Enter runs

Free for signed-in members, with a daily limit. Describe the change in plain words; the new code runs only in your browser.

The popover starts open via defaultOpen; click the button or press Esc to close it. Code written by AgentGid [1].

Checked Oct 12, 2026: it starts without errors in Chromium with @base-ui/react 1.9.0, react 19.3.0, react-dom 19.3.0. Needs WebGL.

More Base UI examples

Dialog with focus control in Base UI Accessible form fields in Base UI Checkbox and Switch in Base UI Accordion in Base UI

Sources

  1. Docs: Quick start
  2. Docs: About Base UI

Explanations written by AgentGid from the official docs; the numbers in brackets point here. The code marked "written by AgentGid" is ours and free to copy.

Building something with Base UI? Ask AgentGid →