Skip to content
kitn AI/UI

Menu

kai-menu

Builds the whole menu, keyboard navigation included, from a plain data tree.

  • Shadow DOM
  • JSON items tree
  • Submenus + checkboxes
  • Keyboard navigable

Build the menu from its items tree, set in JavaScript because arrays can’t be HTML attributes. Each item is an action (id + label, optional icon/shortcut), a heading, a separator, a checkbox (add checked), or a submenu (nest more items). Selecting a leaf fires kai-select with its id.

The trigger is the built-in button (trigger-icon / trigger-label), or your own element in slot="trigger".

<kai-menu trigger-icon="plus" label="Add content"></kai-menu>
<script type="module">
import '@kitn.ai/ui/web-components';
const menu = document.querySelector('kai-menu');
menu.items = [
{ heading: true, label: 'Actions' },
{ id: 'add-files', label: 'Add files or photos', icon: 'paperclip', shortcut: '⌘U' },
{ id: 'add-github', label: 'Add from GitHub', icon: 'github' },
{ separator: true },
{ id: 'web-search', label: 'Web search', icon: 'globe', checked: true },
];
menu.addEventListener('kai-select', (e) => {
console.log(e.detail); // { id } — or { id, checked } for a checkbox item
});
</script>

The menu builds its own trigger from the trigger-* props; slot your own element for full control of it:

SlotModePurpose
replaceYour own trigger element; replaces the built-in button driven by the `trigger-icon` / `trigger-label` props.
<kai-menu>
<button slot="trigger" aria-label="Open menu">+</button>
</kai-menu>
PropertyTypeDefaultNotes
theme'auto'Color mode (`auto` follows prefers-color-scheme).
items—Tree of menu items. Set as a JS property, not an HTML attribute.
placement—Optional placement hint (unused by the underlying Dropdown which always positions bottom-start, kept for future extension).
triggerIcon—Built-in trigger: a leading icon (a named icon, an image URL/data-URI, or text). A slotted trigger overrides it.
triggerLabel—Built-in trigger: a text label.
triggerIconTrailing—Built-in trigger: a trailing icon (e.g. `"chevron-down"` for a select look).
label—Accessible name for a trigger with no visible label. Ignored when `triggerLabel` is set.
fullfalseStretch the trigger to the full width of its container (a block row). Attribute: `full`.
open—Drive/observe the open state: `el.open = true` or the bare `open` attribute. Listen for `kai-open-change`.
defaultOpen—Initial open state on mount (uncontrolled seed).
disabled—Disable the trigger: click/keyboard and `show()` no longer open the menu.
EventDetailNotes
The menu opened or closed (by click, keyboard, Escape, outside-click, or a method).
A leaf item was selected. Plain: `{ id }`; checkbox: `{ id, checked }` with the NEW state; radio: `{ id, radioGroup }`.
MethodSignatureNotes
(): voidOpen it programmatically (no-op while disabled).
(): voidClose it programmatically.
(): voidFlip the open state (closes while disabled).

This element wraps these SolidJS components — reach for them directly when you need finer control than the props expose.

DropdownDropdownTriggerDropdownContentDropdownItemDropdownSeparatorDropdownLabelDropdownCheckboxItemDropdownRadioItemDropdownSubDropdownSubTriggerDropdownSubContentKbd