{
  "$schema": "https://mian.ro/schema/v2/registry.json",
  "schemaVersion": "2.0.0",
  "generatedAt": "2026-10-02T13:14:06.957Z",
  "id": "command",
  "name": "Command palette",
  "category": "Overlays",
  "description": "Search-and-run: filterable, grouped, keyboard-driven. Inline or in a dialog opened with ⌘K.",
  "tags": [
    "command",
    "command palette",
    "cmdk",
    "spotlight",
    "search",
    "launcher"
  ],
  "requiresJs": true,
  "license": "LicenseRef-MIAN-1.0",
  "composition": {
    "role": null,
    "intents": [
      "command palette",
      "search dialog",
      "cmd k",
      "quick actions",
      "spotlight search"
    ],
    "prominence": null,
    "density": null,
    "worksAfter": [],
    "worksBefore": [],
    "alternatives": [],
    "avoid": null
  },
  "url": "https://mian.ro/components/command",
  "markdownUrl": "https://mian.ro/ai/components/command.md",
  "classes": [
    {
      "name": "mn-command",
      "description": "Container."
    },
    {
      "name": "mn-command-input · mn-command-list · mn-command-group · mn-command-heading · mn-command-item · mn-command-empty · mn-command-footer",
      "description": "Parts."
    },
    {
      "name": "dialog.mn-modal.mn-command-dialog[data-mn-hotkey=\"k\"]",
      "description": "Opens on ⌘K / Ctrl+K."
    },
    {
      "name": "data-keywords",
      "description": "Extra search terms for an item."
    }
  ],
  "accessibility": [
    "The input is a combobox controlling a listbox; aria-activedescendant follows the highlight so focus stays in the input. Emits cancelable mn:select."
  ],
  "examples": [
    {
      "title": "Inline",
      "description": null,
      "html": "<div class=\"mn-command mn-command-bordered\" style=\"max-width:30rem\">\n  <div class=\"mn-command-input\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m20 20-3.5-3.5\"/></svg><input placeholder=\"Type a command or search…\" aria-label=\"Command\"></div>\n  <div class=\"mn-command-list\">\n    <div class=\"mn-command-group\" role=\"group\" aria-label=\"Suggestions\"><div class=\"mn-command-heading\">Suggestions</div>\n      <div class=\"mn-command-item\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"/><path d=\"M3 10h18M8 3v4M16 3v4\"/></svg> Calendar</div>\n      <div class=\"mn-command-item\" data-keywords=\"emoji smile\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 20s-7-4.4-9-9a5 5 0 0 1 9-3 5 5 0 0 1 9 3c-2 4.6-9 9-9 9Z\"/></svg> Search emoji</div>\n      <div class=\"mn-command-item\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M13 2 4 14h7l-1 8 9-12h-7Z\"/></svg> Launch</div>\n    </div>\n    <div class=\"mn-command-group\" role=\"group\" aria-label=\"Settings\"><div class=\"mn-command-heading\">Settings</div>\n      <div class=\"mn-command-item\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"8\" r=\"4\"/><path d=\"M4 21a8 8 0 0 1 16 0\"/></svg> Profile <small>⌘P</small></div>\n      <div class=\"mn-command-item\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\"/><path d=\"M3 10h18M7 15h3\"/></svg> Billing <small>⌘B</small></div>\n      <div class=\"mn-command-item\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z\"/></svg> Settings <small>⌘S</small></div>\n    </div>\n    <div class=\"mn-command-empty\" hidden>No results found.</div>\n  </div>\n  <div class=\"mn-command-footer\"><span><kbd class=\"mn-kbd\">↑</kbd><kbd class=\"mn-kbd\">↓</kbd>navigate</span><span><kbd class=\"mn-kbd\">↵</kbd>select</span></div>\n</div>"
    }
  ],
  "css": ".mn-command { display: flex; flex-direction: column; min-width: 0; font: 400 var(--mn-text-sm)/1.4 var(--mn-font); color: var(--mn-fg); }\n.mn-command-input {\n  display: flex; align-items: center; gap: .6rem; padding: 0 1rem;\n  border-bottom: var(--mn-border-w) solid var(--mn-border);\n}\n.mn-command-input svg { width: 1rem; height: 1rem; color: var(--mn-muted); flex: none; }\n.mn-command-input input { flex: 1; min-width: 0; height: 3rem; border: 0; background: none; color: var(--mn-fg); font: inherit; font-size: calc(var(--mn-text-sm) + 1px); }\n.mn-command-input input:focus { outline: none; }\n.mn-command-input input::placeholder { color: var(--mn-muted); }\n.mn-command-list { max-height: min(22rem, 60dvh); overflow: auto; padding: .4rem; scroll-padding: .4rem; }\n.mn-command-group + .mn-command-group { margin-top: .25rem; padding-top: .25rem; border-top: var(--mn-border-w) solid var(--mn-border); }\n.mn-command-group[hidden], .mn-command-item[hidden] { display: none; }\n.mn-command-heading { padding: .5rem .6rem .3rem; font-size: .75rem; font-weight: 600; color: var(--mn-muted); }\n.mn-command-item {\n  display: flex; align-items: center; gap: .65rem;\n  padding: .55rem .6rem; border-radius: calc(var(--mn-radius-box) - 4px);\n  color: inherit; text-decoration: none; cursor: pointer; scroll-margin: .4rem;\n}\n.mn-command-item[aria-selected=\"true\"] { background: var(--mn-hover); }\n.mn-command-item svg { width: 1rem; height: 1rem; color: var(--mn-muted); flex: none; }\n.mn-command-item small { margin-inline-start: auto; color: var(--mn-muted); font-size: .75rem; }\n.mn-command-empty { padding: 2rem 1rem; text-align: center; color: var(--mn-muted); }\n.mn-command-empty[hidden] { display: none; }\n.mn-command-footer { display: flex; gap: 1rem; padding: .55rem 1rem; border-top: var(--mn-border-w) solid var(--mn-border); color: var(--mn-muted); font-size: .75rem; }\n.mn-command-footer .mn-kbd { height: 1.25rem; min-width: 1.25rem; font-size: .6875rem; margin-inline-end: .25rem; }\n.mn-modal.mn-command-dialog { width: min(36rem, calc(100vw - 2rem)); margin-top: 12vh; }\n.mn-command-bordered { border: var(--mn-border-w) solid var(--mn-border); border-radius: var(--mn-radius-box); background: var(--mn-popover); box-shadow: var(--mn-shadow-md); overflow: hidden; }",
  "js": "register('command', (root) => {\n  each(root, '.mn-command', 'Cmd', (c) => {\n    const input = c.querySelector('.mn-command-input input');\n    const list = c.querySelector('.mn-command-list');\n    const empty = c.querySelector('.mn-command-empty');\n    if (!input || !list) return;\n    const items = () => [...list.querySelectorAll('.mn-command-item')];\n    input.setAttribute('role', 'combobox');\n    input.setAttribute('aria-expanded', 'true');\n    input.setAttribute('aria-controls', id(list, 'mn-cmdl'));\n    input.setAttribute('aria-autocomplete', 'list');\n    list.setAttribute('role', 'listbox');\n    items().forEach((it) => { it.setAttribute('role', 'option'); id(it, 'mn-cmd'); it.tabIndex = -1; });\n    let active = 0;\n    const visible = () => items().filter((i) => !i.hidden);\n    const mark = (i) => {\n      const v = visible();\n      items().forEach((x) => x.setAttribute('aria-selected', 'false'));\n      if (!v.length) { input.removeAttribute('aria-activedescendant'); return; }\n      active = (i + v.length) % v.length;\n      v[active].setAttribute('aria-selected', 'true');\n      input.setAttribute('aria-activedescendant', v[active].id);\n      v[active].scrollIntoView({ block: 'nearest' });\n    };\n    const filter = () => {\n      const terms = input.value.toLowerCase().trim().split(/\\s+/).filter(Boolean);\n      items().forEach((it) => {\n        const hay = (it.textContent + ' ' + (it.dataset.keywords || '')).toLowerCase();\n        it.hidden = !terms.every((t) => hay.includes(t));\n      });\n      c.querySelectorAll('.mn-command-group').forEach((g) => { g.hidden = !g.querySelector('.mn-command-item:not([hidden])'); });\n      if (empty) empty.hidden = visible().length > 0;\n      mark(0);\n    };\n    // Enter performs a real click on the highlighted item, so links navigate\n    // and any click behaviour on the item (e.g. data-mn-set-noodle) runs.\n    input.addEventListener('input', filter);\n    input.addEventListener('keydown', (e) => {\n      if (e.key === 'ArrowDown') { e.preventDefault(); mark(active + 1); }\n      else if (e.key === 'ArrowUp') { e.preventDefault(); mark(active - 1); }\n      else if (e.key === 'Enter') { e.preventDefault(); visible()[active]?.click(); }\n    });\n    list.addEventListener('pointermove', (e) => { const it = e.target.closest('.mn-command-item'); if (it && !it.hidden) mark(visible().indexOf(it)); });\n    list.addEventListener('click', (e) => {\n      const it = e.target.closest('.mn-command-item');\n      if (!it) return;\n      if (!emit(c, 'select', { item: it, value: it.dataset.value ?? it.textContent.trim() }, true)) { e.preventDefault(); return; }\n      it.closest('dialog')?.close();\n    });\n    const dlg = c.closest('dialog');\n    dlg?.addEventListener('close', () => { input.value = ''; filter(); });\n    filter();\n  });\n});\n// ⌘K / Ctrl+K opens any dialog marked data-mn-hotkey=\"k\".\ndocument.addEventListener('keydown', (e) => {\n  if (!(e.metaKey || e.ctrlKey) || e.altKey || e.shiftKey) return;\n  const dlg = document.querySelector(`dialog[data-mn-hotkey=\"${e.key.toLowerCase()}\"]`);\n  if (!dlg) return;\n  e.preventDefault();\n  if (dlg.open) dlg.close(); else { dlg.showModal(); dlg.querySelector('input')?.focus(); }\n});",
  "install": {
    "css": "https://mian.ro/dist/mian.css",
    "js": "https://mian.ro/dist/mian.js",
    "registryItem": "https://mian.ro/r/command.json"
  }
}
