Skip to content
LuoForge/Tungsten
Components/Popover·

Popover

since v8.3.0

Popover root — pairs with PopoverTrigger and PopoverContent.

Wraps @radix-ui/react-popover (per ADR-0001) — Radix owns positioning,

collision handling, focus management, dismiss (ESC / outside-click), and

portal semantics; we own class output and the public API. First consumer is

DatePicker's desktop calendar surface.

Install

Add the package and import the component.

pnpm add @hey-mike/tungsten
pnpm add @hey-mike/tungsten
import { Popover } from '@hey-mike/tungsten';
import { Popover } from '@hey-mike/tungsten';

Preview

Same fixtures used by the visual-regression suite.

Usage

apps/docs/app/snapshots/popover/page.tsx

import { Popover, PopoverTrigger, PopoverContent, Button } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';

export default function PopoverSnapshot() {
  return (
    <VariantGrid
      title="Popover"
      // Gallery thumbnail: a static, non-portaled mock of the open popover (the
      // real PopoverContent portals to document.body and would leak onto the
      // detail page from the hidden hero wrapper). The variant below stays closed
      // — the interactive preview opens the real popover on click.
      hero={
        <HeroSpecimen className="max-w-[200px]">
          <div className="flex flex-col items-center gap-2">
            <span className="bg-button-primary-bg text-button-primary-text rounded-md px-3 py-1.5 text-sm font-medium">
              Open popover
            </span>
            <div className="border-stroke bg-surface shadow-overlay w-full rounded-lg border p-2.5 text-left">
              <p className="text-ink-1 text-sm font-semibold">Floating panel</p>
              <p className="text-ink-2 text-xs">Surface, stroke, overlay shadow.</p>
            </div>
          </div>
        </HeroSpecimen>
      }
      variants={[
        {
          label: 'trigger',
          node: (
            <Popover>
              <PopoverTrigger asChild>
                <Button>Open popover</Button>
              </PopoverTrigger>
              <PopoverContent>
                <div className="flex flex-col gap-2 p-1 text-sm">
                  <p className="text-ink-1 font-semibold">Floating panel</p>
                  <p className="text-ink-2">Tokens: surface, stroke, overlay shadow.</p>
                </div>
              </PopoverContent>
            </Popover>
          ),
        },
      ]}
    />
  );
}
import { Popover, PopoverTrigger, PopoverContent, Button } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';

export default function PopoverSnapshot() {
  return (
    <VariantGrid
      title="Popover"
      // Gallery thumbnail: a static, non-portaled mock of the open popover (the
      // real PopoverContent portals to document.body and would leak onto the
      // detail page from the hidden hero wrapper). The variant below stays closed
      // — the interactive preview opens the real popover on click.
      hero={
        <HeroSpecimen className="max-w-[200px]">
          <div className="flex flex-col items-center gap-2">
            <span className="bg-button-primary-bg text-button-primary-text rounded-md px-3 py-1.5 text-sm font-medium">
              Open popover
            </span>
            <div className="border-stroke bg-surface shadow-overlay w-full rounded-lg border p-2.5 text-left">
              <p className="text-ink-1 text-sm font-semibold">Floating panel</p>
              <p className="text-ink-2 text-xs">Surface, stroke, overlay shadow.</p>
            </div>
          </div>
        </HeroSpecimen>
      }
      variants={[
        {
          label: 'trigger',
          node: (
            <Popover>
              <PopoverTrigger asChild>
                <Button>Open popover</Button>
              </PopoverTrigger>
              <PopoverContent>
                <div className="flex flex-col gap-2 p-1 text-sm">
                  <p className="text-ink-1 font-semibold">Floating panel</p>
                  <p className="text-ink-2">Tokens: surface, stroke, overlay shadow.</p>
                </div>
              </PopoverContent>
            </Popover>
          ),
        },
      ]}
    />
  );
}

Props

Surface specific to <Popover />.

PropTypeDefaultDescription
defaultOpenbooleanRender the content open on mount. Useful for visual snapshots. Uncontrolled mode.
openbooleanControlled open state. Pair with onOpenChange.
onOpenChange((open: boolean) => void)Fires whenever Radix wants to open or close the popover.
modalbooleanPosition the content relative to a PopoverAnchor instead of the trigger.

Sub-components

Composition slots re-exported from the same module.

PopoverTrigger

No library-specific props. Pass through standard HTML attributes for the underlying element.

PopoverAnchor

No library-specific props. Pass through standard HTML attributes for the underlying element.

PopoverContent

No library-specific props. Pass through standard HTML attributes for the underlying element.

PopoverClose

No library-specific props. Pass through standard HTML attributes for the underlying element.

Source