# Elements: Overlays

> Plainkit 0.28.0. Generated by scripts/build-skills.mjs from core/dist/elements/api.json. Do not edit: change the source and run the generator.

How to read these tables: see `elements-index.md`. Each element shows its first example; the others are in `references/full/examples-overlays.md` (kept apart so the group files stay short).

## `pk-badge-popover`

**Badge popover** (Overlays). A status pill that is a button: it opens a panel of details (heading, body, optional actions) anchored under it, and on a phone the panel spans the viewport inside the gutters. Escape, an outside press or focus leaving closes it.

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `variant` | enum | `"accent"` | `accent` `muted` `ok` `warn` `danger` `outline` | Colour, as pk-badge. |
| `heading` | string | `""` |  | Panel title; it also names the panel for assistive technology. |
| `label` | string | `""` |  | Accessible name of the panel when there is no heading (falls back to the pill text). |
| `placement` | string | `"bottom-start"` |  | Preferred side of the panel on a wide screen. |
| `open` | boolean | `false` |  | Whether the panel is shown. |

**Slots**

| Slot | Description |
|---|---|
| (default) | The pill text (for example a count and a noun: "5 failing"). |
| `details` | The panel body. |
| `actions` | Buttons at the foot of the panel; hidden when empty. A slotted element with data-close closes the panel. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-open` | `none` | The panel opened. |
| `pk-close` | `{ reason: string }` | The panel is closing (escape, outside, blur, toggle, action); cancelable. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Open the panel. |
| `hide()` | Close the panel. |
| `toggle()` | Open or close it. |

**CSS parts**

| Part | Description |
|---|---|
| `trigger` | The pill button. |
| `panel` | The panel. |
| `title` | The panel heading. |
| `body` | The details wrapper. |
| `actions` | The actions row. |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-badge-popover-bg` | `the variant colour` | Pill fill. |
| `--pk-badge-popover-fg` | `the variant text colour` | Pill text. |
| `--pk-badge-popover-w` | `var(--pop-w)` | Panel width on a wide screen. |

**Accessibility.** The pill is one native button (its own focus ring) with aria-expanded, aria-haspopup="dialog" and aria-controls the panel; the panel is a dialog named by its heading or label. Enter and Space toggle it; opened by keyboard, focus moves into the panel; Escape closes it and returns focus to the pill; an outside press or focus leaving closes it without moving focus. The pill text is the button's name, so put the meaning in words ("5 failing checks"), not only a colour or an icon.

Example: Failing checks

```html
<pk-badge-popover variant="warn" heading="5 failing checks">5 failing
  <div slot="details">Price, weight and 3 image checks need attention before this product can be published.</div>
  <pk-button slot="actions" size="mini" data-close>Dismiss</pk-button>
</pk-badge-popover>
```

## `pk-card-menu`

**Card menu** (Overlays). Also known as: card actions menu, more menu, kebab menu. The "..." (or settings) button of a card header that opens a menu of secondary actions. A pk-dropdown opened by an icon-only button, so the keyboard, the focus return and the placement are the dropdown's; put it in the actions slot of a pk-card with pk-menu-item children. With no pk-menu-item it draws nothing (its actions depend on state and none applies).

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `label` | string | `"Card actions"` | The accessible name of the button, which is also its tooltip. Name what the menu acts on when a page has several ("Orders actions"). |
| `icon-name` (property `iconName`) | string | `"more"` | The icon of the button: more (the default), settings, or any other name of the icon sprite. |
| `placement` | string | `"bottom-end"` | Which side the menu opens on. The default aligns it with the button at the end of the header. |
| `open` | boolean | `false` | Whether the menu is shown. |

**Slots**

| Slot | Description |
|---|---|
| (default) | pk-menu-item children (give each a value to tell them apart in pk-select, or an href). |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-select` | `{ item: element, value: string, checked: boolean }` | An item was chosen (the pk-dropdown's event, which reaches this element). |
| `pk-open` | `none` | Opened. |
| `pk-close` | `{ reason: string }` | Closed. |

**CSS parts**

| Part | Description |
|---|---|
| `menu` | The pk-dropdown. |
| `button` | The icon pk-button that opens it. |

**Accessibility.** The button is named by label and carries aria-haspopup=menu and aria-expanded (set by the pk-dropdown); Enter, Space and ArrowDown open it, arrows, Home, End and typeahead move between items, Escape or choosing an item closes it and returns focus to the button.

Example: In a card header

```html
<pk-card heading="Orders">
  <pk-card-menu slot="actions" label="Orders actions">
    <pk-menu-item value="export">Export</pk-menu-item>
    <pk-menu-item value="archive">Archive</pk-menu-item>
    <pk-menu-item value="delete" danger>Delete</pk-menu-item>
  </pk-card-menu>
  <p>Recent orders.</p>
</pk-card>
```

## `pk-command-palette`

**Command palette** (Overlays). A keyboard-first launcher: Ctrl/Cmd+K opens a dialog with a search field over grouped commands, fuzzy-matched with highlights, recents when the field is empty, arrows and Enter to run.

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `open` | boolean | `false` | Whether it is shown |
| `placeholder` | string | `"Type a command or search…"` | The placeholder setting |
| `recents-key` (property `recentsKey`) | string | `"pk-palette-recents"` | Browser storage key; empty disables recents. |
| `no-shortcut` (property `noShortcut`) | boolean | `false` | Do not bind Ctrl/Cmd+K on the page. |
| `label` | string | `"Command palette"` | Accessible name of the dialog. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-select` | `{ item: object, id: string }` | A command was chosen (id is the item's id); navigates to href when it has one and the event is not cancelled. |
| `pk-open` | `none` | It opened (the shortcut, show(), or open set by the host). |
| `pk-close` | `{ reason: string }` | A close was asked for (Escape, backdrop, the shortcut, hide()) or a command was chosen (reason "select", already closed). Cancelable except for "select": preventDefault keeps it open. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |
| `items (property)` | { id, label, group?, hint?, keywords?, href?, shortcut? }[] (property only). |

**CSS parts**

| Part | Description |
|---|---|
| `dialog` | The native dialog |
| `search` | Search row |
| `input` | Text field |
| `hint` | Keyboard hint |
| `list` | The results list (group headings and option rows are built inside it) |
| `empty` | Empty state text |
| `status` | Live status region |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-palette-w` | `min(40rem, viewport)` | Palette width |

**Accessibility.** A native modal dialog; the input is a combobox controlling a listbox with aria-activedescendant; a polite status announces the result count; groups are labelled. With reduced transparency asked for (prefers-reduced-transparency), the backdrop is not blurred. A theme's glass surface tokens (--surface-blur, --surface-tint) give the panel a frosted look; with reduced transparency or more contrast asked for, or without backdrop-filter support, the panel is solid --color-panel.

Example: Command palette

```html
<pk-button data-open="#command-palette" variant="secondary">Open the palette</pk-button>
<pk-command-palette id="command-palette"></pk-command-palette>
```

## `pk-context-menu`

**Context menu** (Overlays). A menu opened at the pointer by right click, by Shift+F10 or the Menu key, or by a touch long press, over the region it wraps.

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `open` | boolean | `false` | Whether the menu is shown. |
| `disabled` | boolean | `false` | Leave the browser menu alone. |

**Slots**

| Slot | Description |
|---|---|
| (default) | The region the menu belongs to. |
| `menu` | pk-menu-item children. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-select` | `{ item: element, value: string, checked: boolean }` | An item was chosen. |
| `pk-open` | `{ x: number, y: number, target: element, context: string }` | It opened at the pointer position. target is the element that was right-clicked, long-pressed or Shift+F10'd. context is the value of its nearest ancestor's data-pk-context attribute (for example a pk-table row id), unset when none is present; only context reaches Blazor, since a DOM element cannot cross JS interop. |
| `pk-close` | `{ reason: string }` | A close was asked for (Escape, outside press, choosing an item). Cancelable: preventDefault keeps it open. |

**Methods**

| Method | Description |
|---|---|
| `showAt(x, y)` | See the description |
| `hide()` | Closes it |

**CSS parts**

| Part | Description |
|---|---|
| `menu` | The menu layer |

**Accessibility.** The menu is role=menu and takes focus on open; the region is not made focusable, so the keyboard route is the region’s own focusable content plus Shift+F10 or the Menu key.

Example: Right-click, long-press or Shift+F10

```html
<pk-context-menu><pk-card><p>Right-click here.</p></pk-card><pk-menu-item slot="menu">Rename</pk-menu-item><pk-menu-item slot="menu">Duplicate</pk-menu-item><pk-menu-item slot="menu" danger>Delete</pk-menu-item></pk-context-menu>
```

## `pk-dialog`

**Dialog** (Overlays). Also known as: modal. A native modal dialog in five sizes with a scrolling body, full screen on a phone; plus confirm, alert and prompt patterns that return a promise. The backdrop never closes it: every dialog offers its own Cancel or Close. Declarative openers: data-open="#id", data-toggle and data-close work without any script (installed when the element connects).

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `open` | boolean | `false` |  | Whether it is shown |
| `heading` | string | `""` |  | The heading setting |
| `size` | enum | `"md"` | `sm` `md` `lg` `xl` `fullscreen` | The size setting |
| `scrollable` | boolean | `false` |  | The body scrolls inside a bounded dialog. |
| `hide-close` (property `hideClose`) | boolean | `false` |  | Hide the header close button (the dialog offers its own Cancel in the footer). |
| `close-label` (property `closeLabel`) | string | `"Close"` |  | The accessible name of the close (x) button; set it for another language or wording. |
| `max-width` (property `maxWidth`) | number | `0` |  | Card width in pixels before the viewport clamp; 0 keeps the size preset. On a phone every dialog is full screen, so max-width applies from the tablet up. |
| `tint` | enum | `"none"` | `none` `product` `archived` | A tinted card: product (green) or archived (red); a pale wash in the light theme and a dark wash in the dark theme. |
| `controlled` | boolean | `false` |  | The host owns open: close requests (Escape, close button, backdrop, swipe) only raise pk-close and never close the element; the host closes it by clearing open. Used by Blazor wrappers. |

**Slots**

| Slot | Description |
|---|---|
| `header` | Custom header. |
| (default) | Body. |
| `footer` | Actions. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-open` | `none` | pk-open |
| `pk-close` | `{ reason: string }` | escape, close button or method. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |
| `PkDialog.confirm(options) -> Promise<boolean>` | See the description |
| `PkDialog.alert(options) -> Promise<void>` | See the description |
| `PkDialog.prompt(options) -> Promise<string\|null>` | See the description |

**CSS parts**

| Part | Description |
|---|---|
| `dialog` | The native dialog |
| `header` | Header row |
| `title` | Heading text |
| `close` | Close or dismiss button |
| `body` | Main content |
| `footer` | Footer row |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-dialog-w` | `min(35rem, viewport)` | Dialog width |

**Accessibility.** Native <dialog>: focus is trapped and returned by the browser, the page behind is inert, Escape closes; labelled by its heading. A destructive confirm focuses Cancel. With reduced transparency asked for (prefers-reduced-transparency), the backdrop is not blurred. A theme's glass surface tokens (--surface-blur, --surface-tint) give the panel a frosted look; with reduced transparency or more contrast asked for, or without backdrop-filter support, the panel is solid --color-panel. The close button is named by close-label (default "Close").

Example: Dialog with a footer

```html
<pk-button data-open="#discard-dialog" variant="secondary">Discard draft</pk-button>
<pk-dialog id="discard-dialog" heading="Discard this draft?" size="sm"><p>Escape closes this, Tab stays inside, and focus returns to the button that opened it.</p><pk-button slot="footer" variant="ghost">Cancel</pk-button><pk-button slot="footer" variant="warn">Discard</pk-button></pk-dialog>
```

## `pk-drawer`

**Drawer** (Overlays). Also known as: popup. A panel that slides in from the left, right or bottom over a dimmed page, on a native modal dialog: backdrop, focus trap and Escape come with it. A bottom sheet has a grab handle and swipe-to-close on touch. Declarative openers: data-open="#id", data-toggle and data-close work without any script (installed when the element connects).

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `open` | boolean | `false` |  | Whether it is shown |
| `side` | enum | `"right"` | `left` `right` `bottom` | Edge it slides from. |
| `heading` | string | `""` |  | Title; also the accessible name. |
| `persistent` | boolean | `false` |  | The backdrop does not close it. |
| `close-label` (property `closeLabel`) | string | `"Close"` |  | The accessible name of the close (x) button; set it for another language or wording. |
| `wide` | boolean | `false` |  | A wider panel (up to 70% of the viewport). |
| `controlled` | boolean | `false` |  | The host owns open: close requests (Escape, close button, backdrop, swipe) only raise pk-close and never close the element; the host closes it by clearing open. Used by Blazor wrappers. |
| `docked` | boolean | `false` |  | A non-modal inspector: it sits inside the nearest positioned ancestor instead of the viewport, has no backdrop and no focus trap, and the page behind stays usable. Escape still asks to close. |

**Slots**

| Slot | Description |
|---|---|
| `header` | Custom header content. |
| (default) | Body. |
| `footer` | Actions. |
| `actions` | Actions strip under the header (Save, Cancel). |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-open` | `none` | pk-open |
| `pk-close` | `{ reason: string }` | escape, backdrop, close button, swipe or method. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |

**CSS parts**

| Part | Description |
|---|---|
| `panel` | The floating panel |
| `handle` | Grab handle of a bottom sheet |
| `header` | Header row |
| `title` | Heading text |
| `close` | Close or dismiss button |
| `body` | Main content |
| `footer` | Footer row |
| `actions` | Actions strip under the header |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-drawer-w` | `min(24rem, 90vw)` | Side drawer width |
| `--pk-drawer-h` | `85dvh` | Bottom sheet maximum height |

**Accessibility.** A native modal dialog with an accessible name; focus returns to the opener on close; Escape and the backdrop close it (set persistent to keep the backdrop inert). A theme's glass surface tokens (--surface-blur, --surface-tint) give the panel a frosted look; with reduced transparency or more contrast asked for, or without backdrop-filter support, the panel is solid --color-flyout. The close button is named by close-label (default "Close").

Example: Drawer from the right

```html
<pk-button data-open="#filters-drawer" variant="secondary">Filters</pk-button>
<pk-drawer id="filters-drawer" side="right" heading="Filters"><p>Filter controls go here.</p><pk-button slot="footer">Apply</pk-button></pk-drawer>
```

## `pk-dropdown`

**Dropdown menu** (Overlays). Also known as: dropdown menu. A menu opened from a trigger: buttons or links, headers, dividers, checkable items and submenus, with full keyboard support (arrows, Home, End, typeahead, Right/Left for submenus, Escape).

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `open` | boolean | `false` | Whether the menu is shown. |
| `placement` | string | `"bottom-start"` | Preferred side. |
| `keep-open` (property `keepOpen`) | boolean | `false` | Stay open after an item is chosen (multi-select filters). |
| `hide-empty` (property `hideEmpty`) | boolean | `false` | Draws no trigger while the menu has no item to choose (only headers and dividers, or nothing): a menu of state-dependent actions disappears instead of opening empty. |
| `mega` | boolean | `false` | A wide panel whose items flow into columns (navbar mega menu). |

**Slots**

| Slot | Description |
|---|---|
| `trigger` | The button that opens it. |
| (default) | pk-menu-item children. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-select` | `{ item: element, value: string, checked: boolean }` | An item was chosen. |
| `pk-open` | `none` | Opened. |
| `pk-close` | `{ reason: string }` | Closed. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |

**CSS parts**

| Part | Description |
|---|---|
| `menu` | The menu layer |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-dropdown-min-w` | `12rem` | Minimum menu width |

**Writes to host nodes**

| Target | Writes | Why |
|---|---|---|
| the slotted trigger | `aria-haspopup`, `aria-expanded` | aria-haspopup=menu and aria-expanded (true or false, as the open state) describe the popup the trigger controls; refreshed on every open change and when the trigger is replaced. Kept when the element disconnects. |

**Accessibility.** Trigger has aria-haspopup=menu and aria-expanded; the menu is role=menu; items are menuitem, menuitemcheckbox or menuitemradio; focus moves to the first item on keyboard open and returns to the trigger on close. A theme's glass surface tokens (--surface-blur, --surface-tint) give the menu a frosted look; with reduced transparency or more contrast asked for, or without backdrop-filter support, the menu is solid --color-panel.

Example: Menu with a header, checkable items and a submenu

```html
<pk-dropdown><pk-button slot="trigger" variant="ghost">Actions</pk-button><pk-menu-item type="header">Order</pk-menu-item><pk-menu-item>Edit</pk-menu-item><pk-menu-item type="checkbox" checked>Show archived</pk-menu-item><pk-menu-item type="divider"></pk-menu-item><pk-menu-item danger>Delete</pk-menu-item></pk-dropdown>
```

## `pk-lightbox`

**Lightbox** (Overlays). A full-screen image viewer on a native dialog: caption, counter, previous and next with arrow keys and swipe, neighbours preloaded, only safe image sources.

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `index` | number | `0` | The index setting |
| `label` | string | `"Image viewer"` | Accessible name |
| `open` | boolean | `false` | Whether it is shown |

**Slots**

| Slot | Description |
|---|---|
| (default) | The trigger. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-change` | `{ index: number }` | Another image is shown. |
| `pk-close` | `{ reason: string }` | pk-close |
| `pk-open` | `{ }` | It opened. |

**Methods**

| Method | Description |
|---|---|
| `show(index)` | See the description |
| `hide()` | Closes it |
| `items (property)` | { src, alt, caption }[] (property only). |

**CSS parts**

| Part | Description |
|---|---|
| `dialog` | The native dialog |
| `close` | Close or dismiss button |
| `prev` | Previous control |
| `next` | Next control |
| `figure` | Image and caption |
| `image` | The image |
| `caption` | Caption text |
| `counter` | Position counter |

**Accessibility.** Native dialog with a label; the image has alt text from the item; the counter is a polite status; arrow keys and swipe navigate, Escape closes. With reduced transparency asked for (prefers-reduced-transparency), the backdrop is not blurred.

Example: Lightbox trigger

```html
<pk-lightbox label="Product images"><pk-button variant="ghost">Open the gallery</pk-button></pk-lightbox>
```

## `pk-menu-item`

**Menu item** (Overlays). One row of a dropdown or context menu: a plain item, a checkbox, a radio, a section header or a divider; optional prefix and suffix (shortcut) and a nested submenu.

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `type` | enum | `"item"` | `item` `checkbox` `radio` `header` `divider` | What the row is. |
| `checked` | boolean | `false` |  | Checkbox and radio state. |
| `disabled` | boolean | `false` |  | Skipped by keyboard, not activatable. |
| `danger` | boolean | `false` |  | Destructive styling. |
| `warning` | boolean | `false` |  | Warning styling: a consequential action that is not destructive (danger wins when both are set). |
| `value` | string | `""` |  | Reported in pk-select; defaults to the label. |
| `href` | string | `""` |  | Renders as a link. |
| `open` | boolean | `false` |  | A submenu is open. The item opens and closes it itself (pointer, Enter, Space or Right opens; Left or Escape inside it closes) and raises pk-submenu-toggle; a change the host makes raises nothing. |
| `description` | string | `""` |  | Plain text under the label: muted, smaller, wrapping inside the menu width, and the item's accessible description (not its name or typeahead text). Keep it to one short sentence, such as the consequence of the action; the description slot takes markup instead. |

**Slots**

| Slot | Description |
|---|---|
| (default) | Label. |
| `prefix` | Icon before the label, in a fixed cell like pk-nav-item's icon slot. |
| `suffix` | Shortcut after it. |
| `badge` | A count or status pill at the end of the row, styled like pk-nav-item's badge slot. |
| `description` | A secondary line under the label (one short sentence); it takes the place of the description attribute and, like it, is the item's accessible description. |
| `submenu` | Nested pk-menu-item children. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-select` | `{ item: element, value: string, checked: boolean }` | Chosen (bubbles to the dropdown). |
| `pk-submenu-toggle` | `{ open: boolean }` | The item opened or closed its submenu itself (pointer, keys); open already has the new value. Not raised for a change the host made. |

**CSS parts**

| Part | Description |
|---|---|
| `mark` | Check or radio mark |
| `label` | Label text |
| `description` | The description line under the label |
| `chevron` | Submenu or branch chevron |
| `submenu` | The submenu layer |

**Writes to host nodes**

| Target | Writes | Why |
|---|---|---|
| sibling pk-menu-item elements of type radio | `checked` | Choosing a radio item unchecks its radio siblings (the group is the parent). Not undone on disconnect. The description text is the item own accessible description through its ElementInternals (aria(), not an attribute on another node). |

**Accessibility.** The host takes role menuitem, menuitemcheckbox or menuitemradio (header and divider are presentation and separator); aria-checked and aria-disabled follow the props. The description (attribute or slot) is hidden from the name and is the item's accessible description, set as aria-description through ElementInternals (an aria-describedby id cannot cross the shadow root) and refreshed when the slot or attribute changes and when the item takes focus; it is not part of typeahead or of the value pk-select reports.

Example: Item types

```html
<div class="stack"><pk-menu-item type="header">Header</pk-menu-item><pk-menu-item>Plain item</pk-menu-item><pk-menu-item type="checkbox" checked>Checkbox</pk-menu-item><pk-menu-item type="radio" checked>Radio</pk-menu-item><pk-menu-item disabled>Disabled</pk-menu-item><pk-menu-item warning>Close period</pk-menu-item><pk-menu-item danger>Delete</pk-menu-item></div>
```

## `pk-popover`

**Popover** (Overlays). A small non-modal panel anchored to its trigger with a heading, body and actions; opens on click or hover, flips and shifts to stay on screen, closes on Escape, an outside press or focus leaving. variant="confirm" asks a yes/no question beside the control that was pressed. Declarative openers: data-open="#id", data-toggle and data-close work without any script (installed when the element connects).

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `open` | boolean | `false` |  | Whether the panel is shown. |
| `placement` | string | `"bottom-start"` |  | Preferred side. |
| `trigger` | enum | `"click"` | `click` `hover` `manual` | What opens it. |
| `heading` | string | `""` |  | Panel title. |
| `label` | string | `""` |  | Accessible name when there is no heading. |
| `variant` | enum | `"default"` | `default` `confirm` | confirm adds Cancel and Confirm buttons. |
| `message` | string | `""` |  | Body text for the confirm variant. |
| `confirm-label` (property `confirmLabel`) | string | `"Confirm"` |  | Confirm button text. |
| `cancel-label` (property `cancelLabel`) | string | `"Cancel"` |  | Cancel button text. |
| `danger` | boolean | `false` |  | Styles Confirm as destructive. |

**Slots**

| Slot | Description |
|---|---|
| `trigger` | The control that opens it. |
| (default) | Panel body. |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-open` | `none` | Panel opened. |
| `pk-close` | `{ reason: string }` | Panel closed (escape, outside, cancel, confirm, toggle). |
| `pk-confirm` | `none` | Confirm pressed (variant confirm). |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |
| `toggle()` | Toggles it |

**CSS parts**

| Part | Description |
|---|---|
| `panel` | The floating panel |
| `title` | Heading text |
| `body` | Main content |
| `actions` | Action buttons |
| `cancel` | Cancel button |
| `confirm` | Confirm button |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-popover-w` | `--pop-w` | Panel width |

**Writes to host nodes**

| Target | Writes | Why |
|---|---|---|
| the slotted trigger | `aria-haspopup`, `aria-expanded` | aria-haspopup=dialog and aria-expanded (true or false, as the open state) describe the popup the trigger controls; refreshed on every open change and when the trigger is replaced. Kept when the element disconnects. |

**Accessibility.** The trigger carries aria-expanded; the panel is role=dialog (role=alertdialog for confirm) with a label; focus moves in on keyboard open and returns to the trigger on close. A theme's glass surface tokens (--surface-blur, --surface-tint) give the panel a frosted look; with reduced transparency or more contrast asked for, or without backdrop-filter support, the panel is solid --color-panel.

Example: Popover on click

```html
<pk-popover heading="Order 1042"><pk-button slot="trigger" variant="ghost">Details</pk-button>Placed Sep 12, three lines, shipping to Portland.</pk-popover>
```

## `pk-tooltip`

**Tooltip** (Overlays). A short label for the control it wraps, shown on hover, on keyboard focus and on a touch long press. Placed beside the target and flipped when it would leave the screen.

**Props**

| Attribute | Type | Default | Description |
|---|---|---|---|
| `text` | string | `""` | The label. |
| `placement` | string | `"top"` | Preferred side; flips when it does not fit. |
| `delay` | number | `400` | Mouse hover delay; focus is immediate. |
| `shown` | boolean | `false` | Read-only state for CSS (:host([shown])). |
| `interactive` | boolean | `false` | A hint card: the panel stays open while the pointer is over it, a tap on touch toggles it, and it can hold links and rich content. |
| `help` | boolean | `false` | Draws its own info button as the target (the default slot then holds text that follows it). |
| `enrich` | boolean | `false` | Underlines the wrapped value with a dotted line to show it has context. |
| `heading` | string | `""` | A bold heading inside the panel. |
| `label` | string | `"Help"` | Accessible name of the built-in info button. |

**Slots**

| Slot | Description |
|---|---|
| (default) | The element the tip describes. |
| `content` | Rich tip content in place of text. |
| `links` | Links shown under the panel text (a doc link, a more link). |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-show` | `none` | The tip appeared. |
| `pk-hide` | `none` | The tip went away. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it |
| `hide()` | Closes it |

**CSS parts**

| Part | Description |
|---|---|
| `tip` | The tooltip label |
| `help` | The built-in info button |
| `target` | Wraps the slotted target |
| `heading` | The panel heading |
| `links` | The links row |
| `body` | The panel text |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-tooltip-max-w` | `min(20rem, viewport)` | Maximum width |

**Writes to host nodes**

| Target | Writes | Why |
|---|---|---|
| the slotted target | `aria-description` | The tip text is also the target accessible description (an id in the shadow tree cannot reach the target). Set only when the target has none, taken off again when the text or the target changes and when the tooltip disconnects. The single write that is undone on disconnect. |

**Accessibility.** The tip is a role=tooltip node in the shadow tree, and the slotted target gets aria-description with the same text (an accessible description: nothing is added to your markup, and no id has to cross the shadow boundary; a target that already has its own aria-description keeps it). Escape hides it. Wrap a focusable element (button, link); never the only way to learn something essential.

Example: Tooltip on hover, focus and long press

```html
<pk-cluster><pk-tooltip text="Saves the draft without publishing"><pk-button variant="ghost">Save draft</pk-button></pk-tooltip><pk-tooltip text="Opens to the right" placement="right"><pk-button variant="ghost">Right</pk-button></pk-tooltip></pk-cluster>
```

## `pk-tray`

**Tray** (Overlays). Also known as: tool dock, bottom panel, dev tools, console panel. A persistent, non-modal tool panel pinned to a viewport edge (bottom, top, start or end) with a floating launcher and a small, medium or large size choice. No backdrop, no focus trap: the page behind stays usable. Opens from its launcher or a keyboard chord (hotkey), closes from Close, Escape inside it or the chord. Choose pk-drawer for a modal panel, pk-dock for panels arranged inside a page, and pk-tray for a tool panel over a page.

**Props**

| Attribute | Type | Default | Values | Description |
|---|---|---|---|---|
| `open` | boolean | `false` |  | Whether the panel is shown. The element writes it when the user opens or closes it (launcher, Close, Escape inside the panel, the hotkey); show(), hide() and toggle() change it silently. |
| `size` | enum | `"medium"` | `small` `medium` `large` | How much of the viewport the panel takes: its height at the bottom and top edges (25, 40 and 65 percent of the viewport height), its width at the start and end edges. |
| `sizes` | boolean | `false` |  | Draw the built-in size choice (Small, Medium, Large) in the header. Off lets the page provide its own and set size. |
| `label` | string | `""` |  | The panel's accessible name (a complementary landmark), also its header title. Required. |
| `launcher-label` (property `launcherLabel`) | string | `""` |  | The floating launcher's text. Required unless the launcher slot supplies a name. |
| `launcher-variant` (property `launcherVariant`) | enum | `"default"` | `default` `icon` | icon turns the launcher into a bare circle around one icon (put a pk-icon in the launcher slot; launcher-label stays its accessible name): no border, transparent while the tray is closed, filled while it is open, a padding of --pk-tray-launcher-padding. On a phone it keeps the 44px touch target. default is the labelled secondary button. |
| `hotkey` | string | `""` |  | A chord that toggles the tray from anywhere on the page, such as Ctrl+` or Ctrl+Shift+D (Cmd counts as Ctrl). Empty turns it off. The launcher's title and aria-keyshortcuts name it. |
| `edge` | enum | `"bottom"` | `bottom` `top` `start` `end` | The viewport edge the panel is pinned to. start and end are the inline edges (left and right in a left-to-right page, swapped in a right-to-left one). |

**Slots**

| Slot | Description |
|---|---|
| (default) | The panel content. It scrolls inside the panel, and its last row stays clear of the launcher. |
| `trailing` | Extra controls in the header, beside the size choice and Close. |
| `launcher` | Replaces the launcher's text (an icon plus words, for example). |

**Events**

| Event | Detail | Description |
|---|---|---|
| `pk-open` | `{ reason: string }` | The user opened the tray: launcher or hotkey. |
| `pk-close` | `{ reason: string }` | The user asked to close it: close, escape, launcher or hotkey. Cancelable: preventDefault keeps it open. |
| `pk-size-change` | `{ size: string }` | The user picked another size in the built-in choice. |

**Methods**

| Method | Description |
|---|---|
| `show()` | Opens it (no event) |
| `hide()` | Closes it (no event) |
| `toggle()` | Opens it when closed, closes it when open (no event) |

**CSS parts**

| Part | Description |
|---|---|
| `panel` | The fixed panel (a complementary landmark) |
| `header` | Header row: title, trailing slot, size choice, Close |
| `title` | The label as a header title |
| `sizes` | The built-in size choice (a pk-button-group) |
| `close` | The Close button |
| `body` | The scrolling content area |
| `launcher` | The floating launcher button |

**CSS custom properties**

| Property | Default | Description |
|---|---|---|
| `--pk-tray-height` | `set from size` | The panel height at the bottom and top edges; overrides the size choice |
| `--pk-tray-width` | `set from size` | The panel width at the start and end edges; overrides the size choice |
| `--pk-tray-small-h` | `25vh` | Height of the small size |
| `--pk-tray-medium-h` | `40vh` | Height of the medium size |
| `--pk-tray-large-h` | `65vh` | Height of the large size |
| `--pk-tray-z` | `var(--z-flyout)` | Stacking level of the panel |
| `--pk-tray-launcher-inset-block-end` | `var(--space-3)` | Distance of the launcher from the bottom edge of the viewport |
| `--pk-tray-launcher-inset-inline-end` | `var(--space-3)` | Distance of the launcher from the inline end edge (the start edge with edge="start") |
| `--pk-tray-launcher-padding` | `var(--space-1)` | Padding around the icon of launcher-variant="icon" |
| `--pk-tray-launcher-z` | `var(--z-pop)` | Stacking level of the launcher, above the open panel |

**Accessibility.** The panel is a labelled complementary landmark; nothing else on the page is made inert and focus is never trapped. The launcher is a real toggle button (aria-pressed) that stays reachable above the open panel; opening it by the launcher moves focus to the first control in the panel, closing by the launcher, Close or Escape returns focus to the launcher, and closing by the hotkey leaves focus where it is unless it was inside the panel. Escape closes only while focus is inside the panel, so a page-level Escape is not taken. The size choice is a labelled single-select button group. The hotkey is named in the launcher's title and aria-keyshortcuts.

Example: Tool tray at the bottom with a size choice

```html
<pk-button data-open="#tools-tray" variant="secondary">Open the tool tray</pk-button>
<pk-tray id="tools-tray" label="Tools" launcher-label="Tools" hotkey="Ctrl+`" sizes><p>Tool content goes here.</p></pk-tray>
```
