Overlays & menus
Command Menu
Command palette grouped by category
detent-command-menu
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-overlays
- Group
- Overlays & menus
7.1 KB gzip for the class module · inlines the shared spring
Variants
Recorded states
openrecorded state; no setter
Usage
Import
import '/components/command-menu/define.js';
// or register it yourself
import { DetentCommandMenu } from '/components/command-menu/command-menu.js';
Attributes
is-open
Properties
itemsisOpenonCloseonNavigateDocsonSelectComponentqueryactiveIndex
Slots
No slots are recorded for this component.
Events
detent-close— {}detent-select-component— {}detent-navigate-docs— {}
Example
Runnable example: site/examples/command-menu.ts. The snippet below is generated from the catalogued attributes.
<detent-command-menu
is-open
></detent-command-menu>
Property-only values
const element = document.querySelector('detent-command-menu');
if (element !== null) {
// onClose: () => void
element.onClose = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/CommandMenu.tsxsha256 a50beed1444e…
Native files
The native module and its artifacts:
src/components/command-menu/command-menu.tssrc/components/command-menu/styles.csssrc/components/command-menu/define.tsdocs/components/command-menu.mdsite/examples/command-menu.tstests/browser/command-menu.spec.tsevidence/components/command-menu.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
is-open | isOpen | boolean | false | Presence semantics: present means true, absent means false. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
items | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
isOpen | boolean | false | Property-only: assign from script; not accepted as an attribute. |
onClose | () => void | Required | Property-only: assign from script; not accepted as an attribute. |
onNavigateDocs | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
onSelectComponent | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
query | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
activeIndex | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-close | onClose | () => void | Composed, bubbles; fires only for a user action. |
detent-select-component | onSelectComponent | (id: string) => void | Composed, bubbles; fires only for a user action. |
detent-navigate-docs | onNavigateDocs | (topicId?: string) => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- items is consumer data. Upstream built its rows from the site's generated catalog index plus onSelect closures; the native component takes plain-data rows and reports the selection target through id/topicId (PC-3.1, PC-6.3).
- ⌘K / Ctrl+K toggles. Upstream's document listener only _closed_ an open palette; the host page opened it. A palette with no trigger slot would be unreachable for a keyboard-only user, so the shortcut toggles (PC-12.6 accessibility correction).
- Top layer instead of a fixed overlay. Upstream used fixed inset-0 divs; the native port uses <dialog>.showModal() so no ancestor stacking or overflow can clip it and the page behind is inert (PC-9.8, PC-12.4).
- One combobox, no roving buttons. Upstream put role="option" on focusable <button> elements while tracking selection by index; the native rows are non-focusable options driven by aria-activedescendant (PC-12.1).
- The palette is theme-driven in both schemes. Upstream's surface colours were hard-coded dark hexes (#141414, #1F1F1F, #FAFAFA); the native palette reads --detent-color-* tokens with light and dark values (PC-9.5).
- Spring, not AnimatePresence. The entrance/exit is the shared spring helper with the recorded springSnappy physics; the per-item CornerDownLeft icon is replaced by a text ↵ mark (PC-10.2, PC-11.5).
- onClose is optional. Upstream typed it as required; the native port keeps it as an optional hook and always emits detent-close (PC-6.2).
- Page scroll is locked while open, which upstream did not do; without it the background scrolls behind a modal dialog.
- className is replaced by documented parts and custom properties.
What it does
It opens as a real modal dialog in the browser's top layer, so no ancestor transform, overflow or z-index can clip or mislayer it.
Upstream behaviour
- Global hotkey listener (⌘K / Ctrl+K)
- Arrow key navigation with wrapping
- Category badges and action shortcuts
Differences from upstream
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- items is consumer data. Upstream built its rows from the site's generated catalog index plus onSelect closures; the native component takes plain-data rows and reports the selection target through id/topicId (PC-3.1, PC-6.3).
- ⌘K / Ctrl+K toggles. Upstream's document listener only _closed_ an open palette; the host page opened it. A palette with no trigger slot would be unreachable for a keyboard-only user, so the shortcut toggles (PC-12.6 accessibility correction).
- Top layer instead of a fixed overlay. Upstream used fixed inset-0 divs; the native port uses <dialog>.showModal() so no ancestor stacking or overflow can clip it and the page behind is inert (PC-9.8, PC-12.4).
- One combobox, no roving buttons. Upstream put role="option" on focusable <button> elements while tracking selection by index; the native rows are non-focusable options driven by aria-activedescendant (PC-12.1).
- The palette is theme-driven in both schemes. Upstream's surface colours were hard-coded dark hexes (#141414, #1F1F1F, #FAFAFA); the native palette reads --detent-color-* tokens with light and dark values (PC-9.5).
- Spring, not AnimatePresence. The entrance/exit is the shared spring helper with the recorded springSnappy physics; the per-item CornerDownLeft icon is replaced by a text ↵ mark (PC-10.2, PC-11.5).
- onClose is optional. Upstream typed it as required; the native port keeps it as an optional hook and always emits detent-close (PC-6.2).
- Page scroll is locked while open, which upstream did not do; without it the background scrolls behind a modal dialog.
- className is replaced by documented parts and custom properties.