Menu

Component

Interactive examples and API documentation

Horizontal Menu
Horizontal top navigation menu.
Code
<%= render Hakumi::Menu::Component.new(mode: :horizontal, default_selected_keys: ["mail"]) do |menu| %>
  <% menu.with_item(key: "mail", label: "Navigation One", icon: :mail) %>
  <% menu.with_item(key: "app", label: "Navigation Two", icon: :appstore, disabled: true) %>
  <% menu.with_submenu(key: "submenu", label: "Navigation Three", icon: :setting) do |submenu| %>
    <% submenu.with_group(label: "Item 1") do |group| %>
      <% group.with_item(key: "setting:1", label: "Option 1") %>
      <% group.with_item(key: "setting:2", label: "Option 2") %>
    <% end %>
    <% submenu.with_group(label: "Item 2") do |group| %>
      <% group.with_item(key: "setting:3", label: "Option 3") %>
      <% group.with_item(key: "setting:4", label: "Option 4") %>
    <% end %>
  <% end %>
  <% menu.with_item(key: "alipay", label: "Navigation Four - Link", href: "https://ant.design", target: "_blank") %>
<% end %>
Vertical Menu
Vertical menu with popup submenus.
Code
<%= render Hakumi::Menu::Component.new(mode: :vertical, style: "width: 256px;") do |menu| %>
  <% menu.with_submenu(key: "sub1", label: "Navigation One", icon: :mail) do |submenu| %>
    <% submenu.with_group(label: "Item 1") do |group| %>
      <% group.with_item(key: "1", label: "Option 1") %>
      <% group.with_item(key: "2", label: "Option 2") %>
    <% end %>
    <% submenu.with_group(label: "Item 2") do |group| %>
      <% group.with_item(key: "3", label: "Option 3") %>
      <% group.with_item(key: "4", label: "Option 4") %>
    <% end %>
  <% end %>
  <% menu.with_submenu(key: "sub2", label: "Navigation Two", icon: :appstore) do |submenu| %>
    <% submenu.with_item(key: "5", label: "Option 5") %>
    <% submenu.with_item(key: "6", label: "Option 6") %>
    <% submenu.with_submenu(key: "sub3", label: "Submenu") do |sub| %>
      <% sub.with_item(key: "7", label: "Option 7") %>
      <% sub.with_item(key: "8", label: "Option 8") %>
    <% end %>
  <% end %>
  <% menu.with_submenu(key: "sub4", label: "Navigation Three", icon: :setting) do |submenu| %>
    <% submenu.with_item(key: "9", label: "Option 9") %>
    <% submenu.with_item(key: "10", label: "Option 10") %>
    <% submenu.with_item(key: "11", label: "Option 11") %>
    <% submenu.with_item(key: "12", label: "Option 12") %>
  <% end %>
<% end %>
Inline Menu
Vertical menu with inline submenus that expand/collapse.
Code
<%= render Hakumi::Menu::Component.new(
  mode: :inline,
  default_selected_keys: ["1"],
  default_open_keys: ["sub1"],
  style: "width: 256px;"
) do |menu| %>
  <% menu.with_submenu(key: "sub1", label: "Navigation One", icon: :mail) do |submenu| %>
    <% submenu.with_group(label: "Item 1") do |group| %>
      <% group.with_item(key: "1", label: "Option 1") %>
      <% group.with_item(key: "2", label: "Option 2") %>
    <% end %>
    <% submenu.with_group(label: "Item 2") do |group| %>
      <% group.with_item(key: "3", label: "Option 3") %>
      <% group.with_item(key: "4", label: "Option 4") %>
    <% end %>
  <% end %>
  <% menu.with_submenu(key: "sub2", label: "Navigation Two", icon: :appstore) do |submenu| %>
    <% submenu.with_item(key: "5", label: "Option 5") %>
    <% submenu.with_item(key: "6", label: "Option 6") %>
    <% submenu.with_submenu(key: "sub3", label: "Submenu") do |sub| %>
      <% sub.with_item(key: "7", label: "Option 7") %>
      <% sub.with_item(key: "8", label: "Option 8") %>
    <% end %>
  <% end %>
  <% menu.with_divider %>
  <% menu.with_submenu(key: "sub4", label: "Navigation Three", icon: :setting) do |submenu| %>
    <% submenu.with_item(key: "9", label: "Option 9") %>
    <% submenu.with_item(key: "10", label: "Option 10") %>
    <% submenu.with_item(key: "11", label: "Option 11") %>
    <% submenu.with_item(key: "12", label: "Option 12") %>
  <% end %>
  <% menu.with_group(label: "Group") do |group| %>
    <% group.with_item(key: "13", label: "Option 13") %>
    <% group.with_item(key: "14", label: "Option 14") %>
  <% end %>
<% end %>
Collapsed Inline Menu
Inline menu can be collapsed. Click the button to toggle. Shows only icons when collapsed.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle) do %>
  <%= render Hakumi::Button::Component.new(
    type: :primary,
    icon: :menu_fold,
    id: "collapse-toggle-btn"
  ) %>

  <%= render Hakumi::Menu::Component.new(
    mode: :inline,
    default_selected_keys: ["1"],
    default_open_keys: ["sub1"],
    style: "width: 256px;",
    id: "collapsible-menu"
  ) do |menu| %>
    <% menu.with_item(key: "1", label: "Option 1", icon: :pie_chart) %>
    <% menu.with_item(key: "2", label: "Option 2", icon: :desktop) %>
    <% menu.with_submenu(key: "sub1", label: "Navigation One", icon: :mail) do |submenu| %>
      <% submenu.with_item(key: "5", label: "Option 5") %>
      <% submenu.with_item(key: "6", label: "Option 6") %>
    <% end %>
    <% menu.with_submenu(key: "sub2", label: "Navigation Two", icon: :appstore) do |submenu| %>
      <% submenu.with_item(key: "9", label: "Option 9") %>
      <% submenu.with_item(key: "10", label: "Option 10") %>
    <% end %>
  <% end %>
<% end %>

<script>
  (() => {
    const btn = document.getElementById("collapse-toggle-btn")
    const menu = document.getElementById("collapsible-menu")
    if (!btn || !menu) return

    const wire = () => {
      const api = menu.hakumiComponent?.api
      if (!api) return false

      btn.addEventListener("click", () => api.toggleCollapsed())
      return true
    }

    if (wire()) return

    const onRegister = ({ detail }) => {
      if (detail.id !== menu.id) return
      if (wire()) window.removeEventListener("hakumi-component:registered", onRegister)
    }

    window.addEventListener("hakumi-component:registered", onRegister)
  })()
</script>

Menu API

Prop Type Default Description
mode :horizontal | :vertical or :inline :vertical Type of menu.
selectable Boolean true Allow selecting menu items.
multiple Boolean false Allow multiple items to be selected.
inline_collapsed Boolean false Collapsed state of inline menu.
inline_indent Integer 24 Indent (in pixels) of inline menu items on each level.
default_selected_keys Array[String] [] Array of initially selected keys.
default_open_keys Array[String] [] Array of initially opened SubMenu keys.
trigger_submenu_action :hover or :click :hover Trigger mode for opening submenus.
items (slot) Slot - Menu items via with_item, with_submenu, with_group, with_divider.

Menu Item API

Prop Type Default Description
key String - Unique key of menu item (required).
label String - Menu item label text.
icon Symbol or Component - Icon displayed before the label.
disabled Boolean false Whether the item is disabled.
danger Boolean false Display item in danger style.
href String - URL for link items.
target String - Link target attribute.

SubMenu API

Prop Type Default Description
key String - Unique key of submenu (required).
label String - Submenu title.
icon Symbol or Component - Icon displayed before the title.
disabled Boolean false Whether the submenu is disabled.
items (slot) Slot - Child items via with_item, with_submenu, with_group, with_divider.

Menu Group API

Prop Type Default Description
label String - Group title (required).
items (slot) Slot - Child items via with_item.

JavaScript API (element.hakumiMenu)

Prop Type Default Description
toggleCollapsed() Function - Toggle collapsed state of inline menu.
collapse() Function - Collapse the inline menu.
expand() Function - Expand the inline menu.
isCollapsed() Function - Returns true if menu is collapsed.
getSelectedKeys() Function - Returns array of selected item keys.
setSelectedKeys(keys) Function - Set selected items by keys array.
selectItem(key) Function - Select a single item by key.
deselectItem(key) Function - Deselect an item by key.
getOpenKeys() Function - Returns array of open submenu keys.
setOpenKeys(keys) Function - Set open submenus by keys array.
openSubmenu(key) Function - Open a submenu by key.
closeSubmenu(key) Function - Close a submenu by key.
toggleSubmenuByKey(key) Function - Toggle a submenu by key.
closeAllSubmenus() Function - Close all open submenus.
getMode() Function - Returns current mode (horizontal, vertical, inline).