Popover

Manual until a YAML contract lands in monochrome/spec/components/.

Anchored contextual panel. Ids: mct:popover:<id> / mcc:popover:<id>. Uses the Popover API (popover="manual"). Mutually exclusive with other popovers (opening one closes another).

Unlike Menu, Popover has no menuitem keyboard model. Optional Title and Description for accessible naming.

Composition

Root
  Trigger
  Content (div popover="manual")
    Title? (optional)
    Description? (optional)
    (body)

Usage

HTML

html
<button type="button" id="mct:popover:details" aria-controls="mcc:popover:details" aria-expanded="false">
  Show details
</button>
<div id="mcc:popover:details" aria-labelledby="mct:popover:details" aria-hidden="true" popover="manual" tabindex="-1">
  <p>A popover reveals contextual information.</p>
</div>

Author CSS may wrap or style these elements; monochrome ships no classes.

With a description:

html
<div id="mcc:popover:details"
  aria-labelledby="mct:popover:details"
  aria-describedby="mcc:popover-description:details"
  aria-hidden="true"
  popover="manual"
  tabindex="-1">
  <p id="mcc:popover-description:details">A short description for AT.</p>
  <button type="button">Action</button>
</div>

Bare label (skip aria-labelledby):

html
<div id="mcc:popover:filter" aria-label="Filter results" aria-hidden="true" popover="manual" tabindex="-1">
  ...
</div>

React

jsx
import { Popover } from "@monochrome-ui/react"

<Popover.Root>
  <Popover.Trigger>Show details</Popover.Trigger>
  <Popover.Content>
    <Popover.Title>Details</Popover.Title>
    <Popover.Description>A popover reveals contextual information.</Popover.Description>
  </Popover.Content>
</Popover.Root>

Vue

vue
<script setup lang="ts">
import { Popover } from "@monochrome-ui/vue"
</script>

<template>
  <Popover.Root>
    <Popover.Trigger>Show details</Popover.Trigger>
    <Popover.Content>
      <Popover.Title>Details</Popover.Title>
      <Popover.Description>A popover reveals contextual information.</Popover.Description>
    </Popover.Content>
  </Popover.Root>
</template>

Parts

Root

Required for wrappers. Element: div. Mints shared <id> for Trigger and Content.

Trigger

Required. Element: button.

Kind Name Type / value Default Description
attr type "button"
attr id mct:popover:<id>
attr aria-controls mcc:popover:<id>
attr aria-expanded "true" | "false" "false"
attr aria-disabled "true" | absent absent Blocks open when "true".
prop disabled boolean false Emits aria-disabled.

No aria-haspopup (unlike Menu/Dialog).

Content

Required. Element: div.

Kind Name Type / value Default Description
attr id mcc:popover:<id>
attr aria-labelledby mct:popover:<id> | absent Default when no aria-label. Points at the trigger, not at Title.
attr aria-describedby mcc:popover-description:<id> | absent Wrappers emit unless aria-description is passed.
attr aria-label string | absent Bare accessible name; skips aria-labelledby.
attr aria-description string | absent Bare description; skips wrapper aria-describedby.
attr aria-hidden "true" | "false" "true"
attr popover "manual"
attr tabindex "-1" Focusable panel.
attr role "dialog" | absent absent Optional dialog semantics (fixtures use this for filter-style panels).

Title

Optional. Element: h2 (or h1-h6 via as). Id: mcc:popover-title:<id>.

Title is for the visual outline and heading structure. Wrappers do not wire Content aria-labelledby to Title; the accessible name still comes from the trigger (aria-labelledby → Trigger) or from Content aria-label.

Kind Name Type Default Description
prop as "h1""h6" "h2" Heading level.

Description

Optional. Element: p. Id: mcc:popover-description:<id>.

Wrappers emit aria-describedby pointing here by default. Render Description, or pass aria-label / aria-description on Content, so the reference does not dangle.

Notes

  • Open: showPopover(), Trigger aria-expanded="true", Content aria-hidden="false", position CSS vars published.
  • Close: Trigger toggle, outside click, Escape (after tooltip/menu layers), scroll that moves the anchor, focusout patterns handled by core.
  • Structure independence: Trigger and Content need not be adjacent; linkage is ids / aria-controls / labelling.
  • Positioning: Author CSS using --top, --right, --bottom, --left, --pw, --ph on the content element. No CSS shipped.
  • Vs Menu: No role="menu", no typeahead, no menuitem roles. Prefer Menu for action lists; Popover for free-form content.

Keyboard

Key Behavior
Enter / Space on Trigger Toggle open/closed
Escape Close open popover; focus returns to trigger
Tab Moves through focusables inside Content when open

No arrow-key roving inside the popover.

See also