///|
struct MenubarModel {
  active_value : String?
  active_index : Int
  focus_index : Int
  menu : MenuCoreModel
} derive(Eq)

///|
struct MenubarScope {
  id : String
  model : MenubarModel
  counter : Ref[Int]
  focus_claimed : Ref[Bool]
  toggle : @cmd.Emit[(String, Int)]
  close_command : @cmd.Cmd
  toggle_checked : @cmd.Emit[String]
  set_radio : @cmd.Emit[(String, String)]
}

///|
struct MenubarMenuScope {
  menu : MenuScope
  value : String
  index : Int
  focus_index : Int
  focus_claimed : Ref[Bool]
  active_value_set : Bool
}

///|
struct MenubarRadioGroupScope {
  menu : MenuScope
  group : String
}

///|
struct MenubarSubScope {
  menu : MenuScope
  key : String
}

///|
#cfg(target="js")
priv enum MenubarMsg {
  MenubarActivate(String, Int)
  MenubarSwitch(String, Int)
  MenubarToggle(String, Int)
  MenubarClose
  MenubarNative(String, Int, Bool)
  MenubarSetActive(Int)
  MenubarToggleChecked(String)
  MenubarSetRadio(String, String)
  MenubarSetSubmenu(MenuSubmenuChange)
  MenubarSetFocus(Int)
}

///|
const MenubarStyle : String = "display:inline-flex;max-width:100%;min-width:0;flex-wrap:wrap;align-items:center;gap:0.125rem;border:1px solid var(--rui-border,oklch(0.922 0 0));border-radius:calc(var(--rui-radius,0.625rem) - 0.125rem);background:var(--rui-background,oklch(1 0 0));padding:0.25rem;color:var(--rui-foreground,oklch(0.145 0 0));box-shadow:0 1px 2px rgb(0 0 0 / 0.05)"

///|
const MenubarTriggerStyle : String = "height:1.75rem;border:0;background:var(--rui-menu-item-bg,var(--rui-menu-item-base-bg,transparent));padding-inline:0.625rem;color:var(--rui-menu-item-fg,var(--rui-menu-item-base-fg,inherit));box-shadow:none"

///|
const MenubarHoverClickWindowMs : Int = 250

///|
#cfg(target="js")
priv struct MenubarHoverSwitch {
  value : String
  index : Int
  at : Double
}

///|
#cfg(target="js")
priv struct MenubarBinding {
  id : String
  root : @dom.Element
  activate : Ref[(String, Int, Bool) -> Unit]
  native_change : Ref[(String, Int, Bool) -> Unit]
  close : Ref[() -> Unit]
  set_focus : Ref[(Int) -> Unit]
  toggle_contents : Array[@dom.Element]
}

///|
#cfg(target="js")
let menubar_bindings : Map[String, MenubarBinding] = Map([])

///|
#cfg(target="js")
let menubar_hover_switches : Map[String, MenubarHoverSwitch] = Map([])

///|
#cfg(target="js")
fn menubar_now() -> Double {
  if ui_has_window() {
    @dom.window().get_performance().now()
  } else {
    0.0
  }
}

///|
#cfg(target="js")
fn menubar_triggers(binding : MenubarBinding) -> Array[@dom.Element] {
  binding.root
  .query_selector_all("[data-slot=\"menubar-trigger\"]")
  .filter(ui_element_is_enabled)
}

///|
#cfg(target="js")
fn menubar_open_trigger(
  binding : MenubarBinding,
  trigger : @dom.Element,
  focus_content : Bool,
) -> Unit {
  (binding.activate.val)(
    trigger.get_attribute("data-menubar-value").unwrap_or(""),
    ui_parse_int_or(
      trigger.get_attribute("data-menubar-index").unwrap_or(""),
      -1,
    ),
    focus_content,
  )
}

///|
#cfg(target="js")
fn menubar_focus_menu_index(
  binding : MenubarBinding,
  index : Int,
  last : Bool,
  attempt : Int,
  stable_frames : Int,
) -> Unit {
  guard ui_element_by_id(binding.id) is Some(live_root) else { return }
  let content = ui_find_element(
    live_root.query_selector_all("[data-slot=\"menubar-content\"]"),
    node => {
      ui_parse_int_or(
        node.get_attribute("data-menubar-index").unwrap_or(""),
        -1,
      ) ==
      index &&
      menu_element_is_visible(node)
    },
  )
  let target = if content is Some(content) {
    let items = content
      .query_selector_all("[data-menu-index]")
      .filter(item => {
        menu_element_is_visible(item) &&
        item.closest("[role=\"menu\"]") is Some(owner) &&
        owner.is_same_node(content.as_node())
      })
    if last {
      items.get(items.length() - 1)
    } else {
      items.get(0)
    }
  } else {
    None
  }
  if target is Some(target) {
    ui_focus_element_without_scroll(target)
    let focused = @dom.document().get_active_element() is Some(active) &&
      active.is_same_node(target.as_node())
    let next_stable_frames = if focused { stable_frames + 1 } else { 0 }
    if next_stable_frames < 3 && attempt < 20 {
      menu_request_frame(() => {
        menubar_focus_menu_index(
          binding,
          index,
          last,
          attempt + 1,
          next_stable_frames,
        )
      })
    }
  } else if attempt < 20 {
    menu_request_frame(() => {
      menubar_focus_menu_index(binding, index, last, attempt + 1, 0)
    })
  }
}

///|
#cfg(target="js")
fn menubar_handle_keydown(
  binding : MenubarBinding,
  event : @dom.KeyboardEvent,
) -> Unit {
  if event.get_default_prevented() {
    return
  }
  guard event.target().to_element() is Some(target) else { return }
  let trigger = target.closest("[data-slot=\"menubar-trigger\"]")
  let content = target.closest("[data-slot=\"menubar-content\"]")
  let rtl = ui_element_is_rtl(binding.root)
  let forward_key = if rtl { "ArrowLeft" } else { "ArrowRight" }
  let backward_key = if rtl { "ArrowRight" } else { "ArrowLeft" }
  let key = event.key()
  if trigger is None &&
    content is Some(content) &&
    (key == "ArrowRight" || key == "ArrowLeft") {
    let menu_item = target.closest("[data-menu-index]")
    if key == forward_key &&
      menu_item is Some(menu_item) &&
      menu_item.get_attribute("data-submenu-key").unwrap_or("") != "" {
      return
    }
    if key == backward_key &&
      menu_item is Some(menu_item) &&
      menu_item.closest("[data-submenu-owner]") is Some(_) {
      return
    }
    let triggers = menubar_triggers(binding)
    if triggers.length() == 0 {
      return
    }
    let index = ui_parse_int_or(
      content.get_attribute("data-menubar-index").unwrap_or(""),
      0,
    )
    let mut current = 0
    for item_index, item in triggers {
      if ui_parse_int_or(
          item.get_attribute("data-menubar-index").unwrap_or(""),
          -1,
        ) ==
        index {
        current = item_index
      }
    }
    let next_position = if key == forward_key {
      (current + 1) % triggers.length()
    } else if current == 0 {
      triggers.length() - 1
    } else {
      current - 1
    }
    if triggers.get(next_position) is Some(next) {
      event.prevent_default()
      ui_focus_element_without_scroll(next)
      menubar_open_trigger(binding, next, true)
    }
    return
  }
  guard trigger is Some(trigger) else { return }
  menubar_hover_switches.remove(binding.id)
  let triggers = menubar_triggers(binding)
  if triggers.length() == 0 {
    return
  }
  let mut current = 0
  for item_index, item in triggers {
    if item.is_same_node(trigger.as_node()) {
      current = item_index
    }
  }
  let mut next : @dom.Element? = None
  if key == forward_key {
    next = triggers.get((current + 1) % triggers.length())
  } else if key == backward_key {
    next = triggers.get(
      if current == 0 {
        triggers.length() - 1
      } else {
        current - 1
      },
    )
  } else if key == "Home" {
    next = triggers.get(0)
  } else if key == "End" {
    next = triggers.get(triggers.length() - 1)
  }
  if key == "ArrowDown" || key == "ArrowUp" {
    event.prevent_default()
    menubar_open_trigger(binding, trigger, false)
    menubar_focus_menu_index(
      binding,
      ui_parse_int_or(
        trigger.get_attribute("data-menubar-index").unwrap_or(""),
        -1,
      ),
      key == "ArrowUp",
      0,
      0,
    )
    return
  }
  if key == "Escape" {
    event.prevent_default()
    (binding.close.val)()
    ui_focus_element(trigger)
    return
  }
  if next is Some(next) {
    event.prevent_default()
    ui_focus_element(next)
    if binding.root.get_attribute("data-state").unwrap_or("") == "open" {
      menubar_open_trigger(binding, next, false)
    }
  }
}

///|
#cfg(target="js")
fn menubar_bind_content_toggles(binding : MenubarBinding) -> Unit {
  for
    content in binding.root.query_selector_all(
      "[data-slot=\"menubar-content\"]",
    ) {
    let mut already_bound = false
    for current in binding.toggle_contents {
      if current.is_same_node(content.as_node()) {
        already_bound = true
      }
    }
    if !already_bound {
      binding.toggle_contents.push(content)
      content.add_event_listener("toggle", _ => {
        (binding.native_change.val)(
          content.get_attribute("data-menubar-value").unwrap_or(""),
          ui_parse_int_or(
            content.get_attribute("data-menubar-index").unwrap_or(""),
            -1,
          ),
          content.matches(":popover-open"),
        )
      })
    }
  }
}

///|
#cfg(target="js")
fn bind_menubar(
  id : String,
  activate : (String, Int, Bool) -> Unit,
  native_change : (String, Int, Bool) -> Unit,
  close : () -> Unit,
  set_focus : (Int) -> Unit,
) -> Unit {
  guard ui_element_by_id(id) is Some(root) else { return }
  if menubar_bindings.get(id) is Some(existing) &&
    existing.root.is_same_node(root.as_node()) {
    existing.activate.val = activate
    existing.native_change.val = native_change
    existing.close.val = close
    existing.set_focus.val = set_focus
    menubar_bind_content_toggles(existing)
    return
  }
  let binding : MenubarBinding = {
    id,
    root,
    activate: Ref(activate),
    native_change: Ref(native_change),
    close: Ref(close),
    set_focus: Ref(set_focus),
    toggle_contents: [],
  }
  menubar_bindings[id] = binding
  menubar_bind_content_toggles(binding)
  root.add_event_listener("focusin", event => {
    guard event.target().to_element() is Some(target) else { return }
    guard target.closest("[data-slot=\"menubar-trigger\"]") is Some(trigger) &&
      ui_element_is_enabled(trigger) else {
      return
    }
    let index = ui_parse_int_or(
      trigger.get_attribute("data-menubar-index").unwrap_or(""),
      -1,
    )
    for item in menubar_triggers(binding) {
      ui_set_element_tab_index(
        item,
        if item.is_same_node(trigger.as_node()) {
          0
        } else {
          -1
        },
      )
    }
    if index >= 0 {
      (binding.set_focus.val)(index)
    }
  })
  root.add_event_listener("pointermove", event => {
    if binding.root.get_attribute("data-state").unwrap_or("") != "open" {
      return
    }
    guard event.target().to_element() is Some(target) else { return }
    guard target.closest("[data-slot=\"menubar-trigger\"]") is Some(trigger) &&
      ui_element_is_enabled(trigger) else {
      return
    }
    if trigger.get_attribute("data-state").unwrap_or("") != "open" {
      menubar_hover_switches[id] = {
        value: trigger.get_attribute("data-menubar-value").unwrap_or(""),
        index: ui_parse_int_or(
          trigger.get_attribute("data-menubar-index").unwrap_or(""),
          -1,
        ),
        at: if event.get_time_stamp() > 0.0 {
          event.get_time_stamp()
        } else {
          menubar_now()
        },
      }
    }
    let needs_focus = @dom.document().get_active_element() is None ||
      !@dom.document()
      .get_active_element()
      .unwrap()
      .is_same_node(trigger.as_node())
    if needs_focus {
      ui_focus_element_without_scroll(trigger)
    }
    menubar_open_trigger(binding, trigger, false)
  })
  root.add_event_listener("keydown", event => {
    if event.to_keyboard_event() is Some(keyboard_event) {
      menubar_handle_keydown(binding, keyboard_event)
    }
  })
}

///|
#cfg(target="js")
fn consume_menubar_hover_switch(
  id : String,
  value : String,
  index : Int,
  max_age_ms : Int,
) -> Bool {
  let switched = menubar_hover_switches.get(id)
  menubar_hover_switches.remove(id)
  guard switched is Some(switched) else { return false }
  let age = menubar_now() - switched.at
  switched.value == value &&
  switched.index == index &&
  age >= 0.0 &&
  age <= max_age_ms.to_double()
}

///|
#cfg(target="js")
fn menubar_should_toggle(
  id : String,
  active_value : String?,
  value : String,
  index : Int,
) -> Bool {
  let hover_switched = consume_menubar_hover_switch(
    id,
    value,
    index,
    MenubarHoverClickWindowMs,
  )
  active_value != Some(value) || !hover_switched
}

///|
#cfg(target="js")
fn focus_menubar_content(id : String, index : Int) -> Bool {
  guard ui_element_by_id(id) is Some(root) else { return false }
  guard ui_find_element(
      root.query_selector_all("[data-slot=\"menubar-content\"]"),
      node => {
        ui_parse_int_or(
          node.get_attribute("data-menubar-index").unwrap_or(""),
          -1,
        ) ==
        index &&
        menu_element_is_visible(node)
      },
    )
    is Some(content) &&
    content.get_attribute("data-state").unwrap_or("") == "open" else {
    return false
  }
  let target = ui_find_element(
    content.query_selector_all("[data-menu-index]"),
    node => {
      if !menu_element_is_visible(node) {
        false
      } else if node.closest("[role=\"menu\"]") is Some(owner) {
        owner.is_same_node(content.as_node())
      } else {
        false
      }
    },
  )
  guard target is Some(target) else { return false }
  let document = @dom.document()
  if document.get_active_element() is None ||
    !document.get_active_element().unwrap().is_same_node(target.as_node()) {
    ui_focus_element_without_scroll(target)
  }
  document.get_active_element() is Some(active) &&
  active.is_same_node(target.as_node())
}

///|
#cfg(target="js")
fn menubar_focus_content_cmd(id : String, index : Int) -> @cmd.Cmd {
  @cmd.custom_cmd(kind=@cmd.AfterRender, _ => {
    ui_after_ready("menubar-focus-content:" + id, () => {
      focus_menubar_content(id, index)
    })
  })
}

///|
#cfg(target="js")
fn menubar_bind_cmd(
  id : String,
  activate : @cmd.Emit[(String, Int)],
  switch_activate : @cmd.Emit[(String, Int)],
  native_change : @cmd.Emit[(String, Int, Bool)],
  close_command : @cmd.Cmd,
  set_focus : @cmd.Emit[Int],
) -> @cmd.Cmd {
  @cmd.custom_cmd(kind=@cmd.AfterRender, scheduler => {
    ui_after_mount(
      id,
      () => {
        bind_menubar(
          id,
          (value, index, focus_content) => {
            scheduler.add(
              if focus_content {
                switch_activate((value, index))
              } else {
                activate((value, index))
              },
            )
          },
          (value, index, open) => {
            scheduler.add(native_change((value, index, open)))
          },
          () => scheduler.add(close_command),
          index => scheduler.add(set_focus(index)),
        )
      },
      purpose="menubar-bind",
    )
  })
}

///|
fn menubar_content_id(id : String, index : Int) -> String {
  id + "-content-\{index}"
}

///|
fn menubar_trigger_id(id : String, index : Int) -> String {
  id + "-trigger-\{index}"
}

///|
fn menubar_scope(
  id : String,
  model : MenubarModel,
  toggle : @cmd.Emit[(String, Int)],
  close_command : @cmd.Cmd,
  toggle_checked : @cmd.Emit[String],
  set_radio : @cmd.Emit[(String, String)],
) -> MenubarScope {
  {
    id,
    model,
    counter: Ref(0),
    focus_claimed: Ref(false),
    toggle,
    close_command,
    toggle_checked,
    set_radio,
  }
}

///|
fn menubar_change_command(
  id : String,
  current : MenubarModel,
  value : String?,
  index : Int,
) -> @cmd.Cmd {
  let hide_previous = if current.active_index >= 0 &&
    current.active_value != value {
    floating_set_open_cmd(menubar_content_id(id, current.active_index), false)
  } else {
    @cmd.none
  }
  @cmd.batch([
    hide_previous,
    if value is Some(_) {
      floating_set_open_cmd(menubar_content_id(id, index), true)
    } else {
      @cmd.none
    },
    menu_position_submenus_cmd(id + "-root"),
  ])
}

///|
#cfg(target="js")
pub fn menubar(
  id~ : String,
  default_value? : String,
  default_checked_values? : Array[String] = [],
  default_radio_values? : Array[(String, String)] = [],
  on_value_change? : @cmd.Emit[String?],
  aria_label? : String = "Application menu",
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarScope) -> @html.Html,
) -> @rabbita.Val[@html.Html] {
  let initial : MenubarModel = {
    active_value: default_value,
    active_index: if default_value is Some(_) {
      0
    } else {
      -1
    },
    focus_index: -1,
    menu: menu_core_model(
      default_value is Some(_),
      default_checked_values,
      default_radio_values,
    ),
  }
  let (model, emit) = @rabbita.create_state_with_init(
    init=emit => {
      let set_active = emit.map(index => MenubarSetActive(index))
      let set_submenu = emit.map(value => MenubarSetSubmenu(value))
      (
        initial,
        @cmd.batch([
          menubar_bind_cmd(
            id + "-root",
            emit.map(pair => MenubarActivate(pair.0, pair.1)),
            emit.map(pair => MenubarSwitch(pair.0, pair.1)),
            emit.map(tuple => MenubarNative(tuple.0, tuple.1, tuple.2)),
            emit(MenubarClose),
            emit.map(index => MenubarSetFocus(index)),
          ),
          menu_bind_surface_cmd(
            id + "-root",
            set_active,
            emit(MenubarClose),
            set_submenu,
          ),
          match default_value {
            Some(value) =>
              menu_open_marked_cmd(
                id + "-root",
                "menubar-content",
                emit.map(index => MenubarNative(value, index, true)),
              )
            None => @cmd.none
          },
        ]),
      )
    },
    update=(emit, msg, current) => {
      match msg {
        MenubarActivate(value, index) =>
          if current.active_value == Some(value) {
            (current, @cmd.none)
          } else {
            let next = {
              active_value: Some(value),
              active_index: index,
              focus_index: index,
              menu: { ..current.menu, open: true, active: -1, submenus: [] },
            }
            (
              next,
              @cmd.batch([
                menubar_change_command(id, current, Some(value), index),
                if on_value_change is Some(notify) {
                  notify(Some(value))
                } else {
                  @cmd.none
                },
              ]),
            )
          }
        MenubarSwitch(value, index) => {
          let next = {
            active_value: Some(value),
            active_index: index,
            focus_index: index,
            menu: { ..current.menu, open: true, active: -1, submenus: [] },
          }
          (
            next,
            @cmd.batch([
              menubar_change_command(id, current, Some(value), index),
              menubar_focus_content_cmd(id + "-root", index),
              if on_value_change is Some(notify) {
                notify(Some(value))
              } else {
                @cmd.none
              },
            ]),
          )
        }
        MenubarToggle(value, index) =>
          if !menubar_should_toggle(
              id + "-root",
              current.active_value,
              value,
              index,
            ) {
            (current, @cmd.none)
          } else if current.active_value == Some(value) {
            (
              {
                active_value: None,
                active_index: -1,
                focus_index: index,
                menu: { ..current.menu, open: false, submenus: [] },
              },
              @cmd.batch([
                floating_set_open_cmd(menubar_content_id(id, index), false),
                menu_position_submenus_cmd(id + "-root"),
                if on_value_change is Some(notify) {
                  notify(None)
                } else {
                  @cmd.none
                },
              ]),
            )
          } else {
            let next = {
              active_value: Some(value),
              active_index: index,
              focus_index: index,
              menu: { ..current.menu, open: true, active: -1, submenus: [] },
            }
            (
              next,
              @cmd.batch([
                menubar_change_command(id, current, Some(value), index),
                menu_focus_first_cmd(
                  id + "-root",
                  emit.map(active => MenubarSetActive(active)),
                ),
                if on_value_change is Some(notify) {
                  notify(Some(value))
                } else {
                  @cmd.none
                },
              ]),
            )
          }
        MenubarClose =>
          if current.active_value is Some(_) {
            (
              {
                active_value: None,
                active_index: -1,
                focus_index: current.active_index,
                menu: { ..current.menu, open: false, submenus: [] },
              },
              @cmd.batch([
                floating_set_open_cmd(
                  menubar_content_id(id, current.active_index),
                  false,
                ),
                menu_position_submenus_cmd(id + "-root"),
                ui_focus_id(menubar_trigger_id(id, current.active_index)),
                if on_value_change is Some(notify) {
                  notify(None)
                } else {
                  @cmd.none
                },
              ]),
            )
          } else {
            (current, @cmd.none)
          }
        MenubarNative(value, index, open) =>
          if open {
            if current.active_value == Some(value) &&
              current.active_index == index {
              (current, @cmd.none)
            } else {
              (
                {
                  active_value: Some(value),
                  active_index: index,
                  focus_index: index,
                  menu: { ..current.menu, open: true },
                },
                @cmd.none,
              )
            }
          } else if current.active_value == Some(value) {
            (
              {
                active_value: None,
                active_index: -1,
                focus_index: index,
                menu: { ..current.menu, open: false, submenus: [] },
              },
              @cmd.batch([
                menu_position_submenus_cmd(id + "-root"),
                if on_value_change is Some(notify) {
                  notify(None)
                } else {
                  @cmd.none
                },
              ]),
            )
          } else {
            (current, @cmd.none)
          }
        MenubarSetActive(index) =>
          if current.menu.active == index {
            (current, @cmd.none)
          } else {
            (
              { ..current, menu: { ..current.menu, active: index } },
              menu_focus_item_cmd(
                id + "-root",
                index,
                content_id=menubar_content_id(id, current.active_index),
              ),
            )
          }
        MenubarToggleChecked(value) =>
          (
            {
              ..current,
              menu: {
                ..current.menu,
                checked: menu_toggle_value(current.menu.checked, value),
              },
            },
            @cmd.none,
          )
        MenubarSetRadio(group, value) =>
          (
            {
              ..current,
              menu: {
                ..current.menu,
                radios: menu_set_radio_value(current.menu.radios, group, value),
              },
            },
            @cmd.none,
          )
        MenubarSetSubmenu(change) => {
          let submenus = menu_update_submenus(current.menu.submenus, change)
          if submenus == current.menu.submenus {
            (current, @cmd.none)
          } else {
            (
              { ..current, menu: { ..current.menu, submenus, } },
              menu_position_submenus_cmd(id + "-root"),
            )
          }
        }
        MenubarSetFocus(index) => ({ ..current, focus_index: index }, @cmd.none)
      }
    },
  )
  model.view(model => {
    let scope = menubar_scope(
      id,
      model,
      emit.map(pair => MenubarToggle(pair.0, pair.1)),
      emit(MenubarClose),
      emit.map(value => MenubarToggleChecked(value)),
      emit.map(pair => MenubarSetRadio(pair.0, pair.1)),
    )
    let element_attrs = menu_state_attrs(
        attrs,
        "menubar",
        model.active_value is Some(_),
      )
      .role("menubar")
      .aria_orientation("horizontal")
    ignore(element_attrs.aria_label(aria_label))
    if model.active_value is Some(value) {
      ignore(element_attrs.data_set("value", value))
    }
    @html.div(
      style=ui_styles(
        [UiBoxSizing, UiFontSans, UiTextRendering, MenubarStyle],
        style,
      ),
      id=id + "-root",
      class?,
      title?,
      attrs=element_attrs,
      children(scope),
    )
  })
}

///|
#cfg(not(target="js"))
pub fn menubar(
  id~ : String,
  default_value? : String,
  default_checked_values? : Array[String] = [],
  default_radio_values? : Array[(String, String)] = [],
  on_value_change? : @cmd.Emit[String?],
  aria_label? : String = "Application menu",
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarScope) -> @html.Html,
) -> @rabbita.Val[@html.Html] {
  ignore(on_value_change)
  let model : MenubarModel = {
    active_value: default_value,
    active_index: if default_value is Some(_) {
      0
    } else {
      -1
    },
    focus_index: -1,
    menu: menu_core_model(
      default_value is Some(_),
      default_checked_values,
      default_radio_values,
    ),
  }
  let scope = menubar_scope(
    id,
    model,
    menu_noop_emit(),
    @cmd.none,
    menu_noop_emit(),
    menu_noop_emit(),
  )
  let element_attrs = menu_state_attrs(
      attrs,
      "menubar",
      default_value is Some(_),
    )
    .role("menubar")
    .aria_orientation("horizontal")
  ignore(element_attrs.aria_label(aria_label))
  @rabbita.Val::constant(
    @html.div(
      style=ui_styles(
        [UiBoxSizing, UiFontSans, UiTextRendering, MenubarStyle],
        style,
      ),
      id=id + "-root",
      class?,
      title?,
      attrs=element_attrs,
      children(scope),
    ),
  )
}

///|
/// Explicit Root spelling matching the compound-component API.
pub fn menubar_root(
  id~ : String,
  default_value? : String,
  default_checked_values? : Array[String] = [],
  default_radio_values? : Array[(String, String)] = [],
  on_value_change? : @cmd.Emit[String?],
  aria_label? : String = "Application menu",
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarScope) -> @html.Html,
) -> @rabbita.Val[@html.Html] {
  menubar(
    id~,
    default_value?,
    default_checked_values~,
    default_radio_values~,
    on_value_change?,
    aria_label~,
    class?,
    title?,
    attrs?,
    style~,
    children,
  )
}

///|
/// Zero-DOM Portal adapter for shadcn-compatible compound composition.
/// Menubar Content is promoted by native Popover, so children remain directly
/// composable without an extra element or a portal registration phase.
pub fn menubar_portal(children : Array[@html.Html]) -> @html.Html {
  @html.fragment(children)
}

///|
pub fn[C : @html.IsChildren] menubar_menu(
  scope : MenubarScope,
  value~ : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarMenuScope) -> C,
) -> @html.Html {
  let index = scope.counter.val
  scope.counter.val += 1
  let open = scope.model.active_value == Some(value)
  let menu_model = { ..scope.model.menu, open, }
  let menu : MenuScope = {
    id: scope.id,
    content_id: menubar_content_id(scope.id, index),
    trigger_id: menubar_trigger_id(scope.id, index),
    model: menu_model,
    counter: Ref(0),
    close_command: scope.close_command,
    toggle_command: (scope.toggle)((value, index)),
    toggle_checked: scope.toggle_checked,
    set_radio: scope.set_radio,
  }
  @html.div(
    style=ui_styles([UiBoxSizing, "display:contents"], style),
    attrs=menu_state_attrs(attrs, "menubar-menu", open)
      .data_set("value", value)
      .data_set("menubar-index", "\{index}"),
    children({
      menu,
      value,
      index,
      focus_index: scope.model.focus_index,
      focus_claimed: scope.focus_claimed,
      active_value_set: scope.model.active_value is Some(_),
    }),
  )
}

///|
pub fn[C : @html.IsChildren] menubar_trigger(
  scope : MenubarMenuScope,
  disabled? : Bool = false,
  aria_label? : String,
  on_click? : @cmd.Cmd,
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  let preferred = if scope.active_value_set {
    scope.menu.model.open
  } else if scope.focus_index >= 0 {
    scope.focus_index == scope.index
  } else {
    !scope.focus_claimed.val
  }
  let tab_stop = !disabled && preferred
  if tab_stop {
    scope.focus_claimed.val = true
  }
  let trigger_attrs = ui_attrs(attrs)
    .data_set("menubar-value", scope.value)
    .data_set("menubar-index", "\{scope.index}")
    .role("menuitem")
    .tabindex(if tab_stop { 0 } else { -1 })
  menu_trigger_button(
    "menubar-trigger",
    scope.menu,
    Ghost,
    Sm,
    disabled,
    aria_label,
    on_click,
    class,
    title,
    Some(trigger_attrs),
    [
      MenubarTriggerStyle,
      if scope.menu.model.open {
        "--rui-menu-item-base-bg:var(--rui-accent,oklch(0.97 0 0));--rui-menu-item-base-fg:var(--rui-accent-foreground,oklch(0.205 0 0))"
      } else {
        ""
      },
    ] +
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_content(
  scope : MenubarMenuScope,
  side_offset? : Int = 8,
  align_offset? : Int = 0,
  aria_label? : String,
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  let content_attrs = ui_attrs(attrs)
    .data_set("menubar-value", scope.value)
    .data_set("menubar-index", "\{scope.index}")
    .data_set("restore-focus", "false")
  menu_content_surface(
    "menubar-content",
    scope.menu,
    Bottom,
    Start,
    side_offset,
    align_offset,
    aria_label,
    class,
    title,
    Some(content_attrs),
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_group(
  aria_label? : String,
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_group_surface(
    "menubar-group", aria_label, class, title, attrs, style, children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_item(
  scope : MenubarMenuScope,
  disabled? : Bool = false,
  inset? : Bool = false,
  destructive? : Bool = false,
  close_on_select? : Bool = true,
  on_select? : @cmd.Cmd,
  aria_label? : String,
  class? : String,
  title? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_item_surface(
    "menubar-item",
    scope.menu,
    "menuitem",
    None,
    MenuIndicatorInlineStart,
    disabled,
    inset,
    destructive,
    None,
    close_on_select,
    None,
    on_select,
    aria_label,
    class,
    title,
    attrs,
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_checkbox_item(
  scope : MenubarMenuScope,
  value~ : String,
  disabled? : Bool = false,
  close_on_select? : Bool = false,
  on_checked_change? : @cmd.Emit[Bool],
  on_select? : @cmd.Cmd,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  let checked = menu_contains(scope.menu.model.checked, value)
  let notify = if on_checked_change is Some(notify) {
    notify(!checked)
  } else {
    @cmd.none
  }
  menu_item_surface(
    "menubar-checkbox-item",
    scope.menu,
    "menuitemcheckbox",
    Some(checked),
    MenuIndicatorInlineEnd,
    disabled,
    false,
    false,
    None,
    close_on_select,
    Some(@cmd.batch([notify, (scope.menu.toggle_checked)(value)])),
    on_select,
    None,
    None,
    None,
    attrs,
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_radio_group(
  scope : MenubarMenuScope,
  value~ : String,
  aria_label? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarRadioGroupScope) -> C,
) -> @html.Html {
  menu_group_surface(
    "menubar-radio-group",
    aria_label,
    None,
    None,
    attrs,
    style,
    children({ menu: scope.menu, group: value }),
  )
}

///|
pub fn[C : @html.IsChildren] menubar_radio_item(
  scope : MenubarRadioGroupScope,
  value~ : String,
  disabled? : Bool = false,
  close_on_select? : Bool = false,
  on_value_change? : @cmd.Emit[String],
  on_select? : @cmd.Cmd,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  let checked = menu_radio_value(scope.menu.model.radios, scope.group) ==
    Some(value)
  let notify = if on_value_change is Some(notify) {
    notify(value)
  } else {
    @cmd.none
  }
  menu_item_surface(
    "menubar-radio-item",
    scope.menu,
    "menuitemradio",
    Some(checked),
    MenuIndicatorInlineEnd,
    disabled,
    false,
    false,
    None,
    close_on_select,
    Some(@cmd.batch([notify, (scope.menu.set_radio)((scope.group, value))])),
    on_select,
    None,
    None,
    None,
    attrs,
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_label(
  inset? : Bool = false,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_label_surface("menubar-label", inset, None, None, attrs, style, children)
}

///|
pub fn menubar_separator(
  attrs? : @html.Attrs,
  style? : Array[String] = [],
) -> @html.Html {
  menu_separator_surface("menubar-separator", None, attrs, style)
}

///|
pub fn[C : @html.IsChildren] menubar_shortcut(
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_shortcut_surface("menubar-shortcut", None, None, attrs, style, children)
}

///|
pub fn[C : @html.IsChildren] menubar_sub(
  scope : MenubarMenuScope,
  value~ : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : (MenubarSubScope) -> C,
) -> @html.Html {
  let key = menu_submenu_key(scope.menu, value)
  let open = menu_submenu_open(scope.menu.model.submenus, key)
  menu_sub_root_surface(
    "menubar-sub",
    open,
    attrs,
    style,
    children({ menu: scope.menu, key }),
  )
}

///|
pub fn[C : @html.IsChildren] menubar_sub_trigger(
  scope : MenubarSubScope,
  disabled? : Bool = false,
  inset? : Bool = false,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_item_surface(
    "menubar-sub-trigger",
    scope.menu,
    "menuitem",
    None,
    MenuIndicatorInlineStart,
    disabled,
    inset,
    false,
    Some(scope.key),
    false,
    None,
    None,
    None,
    None,
    None,
    attrs,
    style,
    children,
  )
}

///|
pub fn[C : @html.IsChildren] menubar_sub_content(
  scope : MenubarSubScope,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  children : C,
) -> @html.Html {
  menu_sub_content_surface(
    "menubar-sub-content",
    scope.key,
    menu_submenu_open(scope.menu.model.submenus, scope.key),
    None,
    None,
    attrs,
    style,
    children,
  )
}