Autocomplete

Chaining

How one pick leads to the next menu, and the keys that move through it.
::ca|                      Components › ::card, ::callout …
  ↵ (or type {)
::card{|}                  ::card › props   title*  variant  icon  .class …
  ↵ on variant (or type =)
::card{variant="|"}        ::card › variant   soft  outline  solid
  ↵ on outline
::card{variant="outline"|} ::card › props   title*  icon …
  type :ti ↵
::card{variant="outline" :title="|"}   :title › bindings   frontmatter  props  data
  → frontmatter, → site, ↵ name
::card{variant="outline" :title="frontmatter.site.name"|}
  } or Esc                 the chain ends; the body line and closer were inserted with the opener

Keys

KeyWhile a menu is open
Enter / Tabaccept; if the item has a next step, its menu opens
→accept an item that has a next level (shown with ›)
←undo the last chained pick and reopen its menu
{ = .accept the component, prop or binding key (the character is not typed twice)
Escclose the menu; the chain ends

Outside a menu, Tab moves to the next snippet field and opens its menu — for example from a component's {} to its body.

How it works

Each item says whether it has a next step. comark() passes activateOnCompletion to CodeMirror's autocomplete, so picking such an item reopens completion at the new cursor position, where the context resolver finds the next thing to complete. The menu's section header is the breadcrumb of that context (::card › variant).

← keeps a short stack of chained picks and reverts the last one when nothing was typed since. Commit keys are handled before CodeMirror's own, so { accepts ::card without adding a second brace.

Turn any of it off with options: chain: false stops reopening, drill: false frees the arrow keys.

Copyright © 2026