Nasaq
Components

Popover

Anchored floating panel opened by a click on a trigger, holding rich content such as text, forms or actions. Wraps Base UI Popover.

PreviewOpen ↗

Code

import { Button, Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@fadymondy/nasaq/web";export function DeployInfo() {  return (    <Popover>      <PopoverTrigger render={<Button variant="outline" />}>Details</PopoverTrigger>      <PopoverContent>        <PopoverTitle>Deployment window</PopoverTitle>        <PopoverDescription>Releases go out Sunday to Thursday.</PopoverDescription>        <PopoverClose render={<Button size="sm" />}>Got it</PopoverClose>      </PopoverContent>    </Popover>  );}

Overlays · stable

Live examples and controls: Popover in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/popover.json

A small panel that opens next to a trigger when it is clicked. It holds arbitrary content (an explanation, a mini form, a set of actions) without leaving the page. Built on Base UI Popover, so it handles positioning, collision flipping, focus and dismissal.

When to use

  • Extra detail or a small form attached to one control.
  • Content that needs to be interactive, so a tooltip is not enough.

When not to use

  • A list of actions: use a DropdownMenu.
  • A one-line hint on hover or focus: use a Tooltip.
  • A preview shown on hover: use a HoverCard.
  • Blocking decisions or long forms: use a Dialog.

Import

import { Popover, PopoverTrigger, PopoverContent } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"

Quick start

import { Button, Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@fadymondy/nasaq/web";

export function DeployInfo() {
  return (
    <Popover>
      <PopoverTrigger render={<Button variant="outline" />}>Details</PopoverTrigger>
      <PopoverContent>
        <PopoverTitle>Deployment window</PopoverTitle>
        <PopoverDescription>Releases go out Sunday to Thursday.</PopoverDescription>
        <PopoverClose render={<Button size="sm" />}>Got it</PopoverClose>
      </PopoverContent>
    </Popover>
  );
}

Anatomy

Popover                     Base UI Popover.Root
├─ PopoverTrigger           Base UI Popover.Trigger (use render={<Button />})
└─ PopoverContent           Portal + positioner + popup   data-slot="popover-content"
   ├─ PopoverTitle          data-slot="popover-title"
   ├─ PopoverDescription    data-slot="popover-description"
   └─ PopoverClose          Base UI Popover.Close

API

Popover = Popover.Root, PopoverTrigger = Popover.Trigger, PopoverClose = Popover.Close. They take the Base UI props.

ExportCommon props
Popoveropen?, defaultOpen?, onOpenChange?, modal?
PopoverTriggerrender?, openOnHover?, delay?, disabled?
PopoverCloserender?

PopoverContent

PopoverContentProps extends Base UI Popover.Popup props.

PropTypeDefaultDescription
side?Popover.Positioner side ("top" | "bottom" | "left" | "right" | "inline-start" | "inline-end")"bottom"Side of the trigger to open on.
align?"start" | "center" | "end""center"Alignment against the trigger.
sideOffset?number6Gap to the trigger in px.
className?stringnoneMerged onto the popup (width is w-72 by default).

PopoverTitle / PopoverDescription

Base UI Popover.Title / Popover.Description props. They label the popup for assistive tech (aria-labelledby, aria-describedby).

Examples

Controlled

import { Button, Popover, PopoverContent, PopoverTrigger } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function Controlled() {
  const [open, setOpen] = useState(false);
  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger render={<Button />}>{open ? "Hide" : "Show"}</PopoverTrigger>
      <PopoverContent side="inline-end" align="start">Opens at the inline end.</PopoverContent>
    </Popover>
  );
}

Arabic

import { Button, Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@fadymondy/nasaq/web";

export function DeployInfoAr() {
  return (
    <Popover>
      <PopoverTrigger render={<Button variant="outline" />}>التفاصيل</PopoverTrigger>
      <PopoverContent align="start">
        <PopoverTitle>نافذة النشر</PopoverTitle>
        <PopoverDescription>تُنشر الإصدارات من الأحد إلى الخميس.</PopoverDescription>
      </PopoverContent>
    </Popover>
  );
}

Accessibility

Base UI sets aria-expanded and aria-controls on the trigger, and the popup is labelled by PopoverTitle and described by PopoverDescription.

KeyAction
Enter / Space on triggerToggles the popover.
TabMoves through the popup content, then on.
EscCloses and returns focus to the trigger.
  • Give an icon-only trigger an aria-label.
  • Localise the title, description and close text.

RTL & i18n

  • Use side="inline-start" / "inline-end" so the placement mirrors with dir. align="start" follows the reading direction.
  • The popup inherits direction from the app provider; portalled content outside a dir wrapper needs dir set on PopoverContent in isolated demos.
  • No built-in strings.

Styling & tokens

  • Surface level 3: bg-popover, text-popover-foreground, border-border, rounded-floating, shadow-floating.
  • State attributes on the popup: data-starting-style, data-ending-style, data-side, data-open.
  • Extend with className; never override colours with raw hex.

Do / Don't

  • Do keep it short; move long content to a Dialog.
  • Do give the trigger a visible label or aria-label.
  • Don't put a menu of actions in it; use a DropdownMenu.
  • Don't use left / right for side when inline-start / inline-end is meant.

Lab

https://docs.nasaqui.com/?path=/docs/components-overlays-popover--docs

On this page