Skip to content
  1. Keyline UI
  2. Popover
Keyline UIComponents
  • Get started
    • Installation
    • Theming
    • Modes
    • Configuration
    • Composition
  • Actions
    • Button
    • Button group
    • Split button
    • Toggle
    • Toggle group
    • Toolbar
    • Menu
    • Menubar
    • Context menu
  • Inputs
    • Field and form
    • Checkbox
    • Checkbox group
    • Radio group
    • Switch
    • Slider
    • Segmented
    • Select
    • Native select
    • Combobox
    • Multiselect
    • Number field
    • OTP field
    • Time field
    • Date picker and calendar
    • Date range
  • Data
    • Table
    • Chart
    • Stat and meter
    • Status and badge
    • Progress
    • Skeleton
    • Empty
    • Avatar
    • Kbd
    • Marker
  • Navigation
    • Tabs
    • Breadcrumb
    • Pagination
    • Nav
    • Navigation menu
    • Command menu
  • Overlays
    • Dialog
    • Alert dialog
    • Drawer
    • Sheet
    • Popover
    • Hover card
    • Tooltip
    • Toast
    • Notice
  • Layout
    • App shell
    • Sidebar
    • Panel
    • Resizable
    • Scroll area
    • Accordion
    • Collapsible
    • Carousel
    • Inspector
    • Item
    • Direction
  • Conversation
    • Message
    • Bubble
    • Message scroller
    • Attachment
    • Questionnaire
  • Blocks
    • Shipments

Popover

A small panel about the control that opened it. It docks to the trigger and shares its edge, so the two read as one shape. It holds a quick edit or a few settings; the page around it stays live, and a click outside or Escape puts it away.

Loading the live example…

"use client"

import { useState } from "react"
import { Button } from "@/components/keyline/ui/button"
import { Field, FieldFrame, FieldLabel, FieldTextarea } from "@/components/keyline/ui/field"
import { Popover, PopoverBody, PopoverClose, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger } from "@/components/keyline/ui/popover"

export function DeliveryNote() {
  const [note, setNote] = useState("Loading dock is round the back.")
  const [draft, setDraft] = useState(note)

  return (
    <div className="grid gap-3 text-[14px]">
      <div className="flex flex-wrap items-center gap-3">
        <span>
          <span className="font-kl-mono text-[13px]">DM-4107</span> · Lackawanna County
        </span>
        <Popover onOpenChange={(o) => o && setDraft(note)}>
          <PopoverTrigger render={<Button size="compact" />}>Delivery note</PopoverTrigger>
          <PopoverContent className="w-[min(340px,calc(100vw-24px))]">
            <PopoverHeader title="Delivery note" description="Darryl reads it before he loads the truck." />
            <PopoverBody>
              <Field>
                <FieldLabel className="sr-only">Note</FieldLabel>
                <FieldFrame>
                  <FieldTextarea rows={3} value={draft} onChange={(e) => setDraft(e.target.value)} />
                </FieldFrame>
              </Field>
            </PopoverBody>
            <PopoverFooter>
              <PopoverClose render={<Button layout="cell" />}>Cancel</PopoverClose>
              <PopoverClose render={<Button layout="cell" variant="primary" onClick={() => setNote(draft.trim())} />}>Save note</PopoverClose>
            </PopoverFooter>
          </PopoverContent>
        </Popover>
      </div>
      <p role="status" className="m-0 text-kl-ink-2">
        {note ? `Note: ${note}` : "No delivery note."}
      </p>
    </div>
  )
}

Installation

npx shadcn@latest add @keyline-ui/popover

Run it where your components.json is. The first time, map the @keyline-ui registry: one command, in Installation.

Usage

import { Popover, PopoverBody, PopoverClose, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger } from "@/components/keyline/ui/popover"
<Popover>
  <PopoverTrigger render={<Button size="compact" />}>Delivery note</PopoverTrigger>
  <PopoverContent>
    <PopoverHeader title="Delivery note" description="…" />
    <PopoverBody>…</PopoverBody>
    <PopoverFooter>
      <PopoverClose render={<Button layout="cell" />}>Cancel</PopoverClose>
    </PopoverFooter>
  </PopoverContent>
</Popover>

Props

PropTypeDefaultDescription
side · alignBase UI side · alignDefault "bottom" · "start"On PopoverContent: where it docks. It flips when there's no room.
attachWeight1 | 2 | 3Default 2The trigger&apos;s edge weight, so the shared edge matches: 1 for a cell, 2 for a control.
detachedbooleanDefault falseSits one gutter away in its own frame, for content not about the trigger.
anchorElement | refDefault the triggerDocks to another element.
PopoverHeader{ title, description?, close?, closeLabel? }Default —A header row with a close cell.

Built on Base UI Popover; its other props pass through.

Sheet 52 of 73PreviousSheetNextHover card
On this page