Skip to contents

Menubar

A menu bar providing commands and options for your application.

import { mergeProps } from 'base-ui-solid/merge-props';
import type { JSX } from '@solidjs/web';
import { Menubar } from 'base-ui-solid/menubar';
import { Menu } from 'base-ui-solid/menu';
import styles from './index.module.css';

export default function ExampleMenubar() {
  return (
    <Menubar class={styles.Menubar}>
      <Menu.Root>
        <Menu.Trigger class={styles.MenuTrigger}>File</Menu.Trigger>
        <Menu.Portal>
          <Menu.Positioner class={styles.MenuPositioner} sideOffset={4}>
            <Menu.Popup class={styles.MenuPopup}>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                New
              </Menu.Item>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Open
              </Menu.Item>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Save
              </Menu.Item>

              <Menu.SubmenuRoot>
                <Menu.SubmenuTrigger class={styles.SubmenuTrigger}>
                  Export
                  <CaretRightIcon />
                </Menu.SubmenuTrigger>
                <Menu.Portal>
                  <Menu.Positioner class={styles.MenuPositioner} sideOffset={-4} alignOffset={-4}>
                    <Menu.Popup class={styles.MenuPopup}>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        PDF
                      </Menu.Item>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        PNG
                      </Menu.Item>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        SVG
                      </Menu.Item>
                    </Menu.Popup>
                  </Menu.Positioner>
                </Menu.Portal>
              </Menu.SubmenuRoot>

              <Menu.Separator class={styles.MenuSeparator} />
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Print
              </Menu.Item>
            </Menu.Popup>
          </Menu.Positioner>
        </Menu.Portal>
      </Menu.Root>

      <Menu.Root>
        <Menu.Trigger class={styles.MenuTrigger}>Edit</Menu.Trigger>
        <Menu.Portal>
          <Menu.Positioner class={styles.MenuPositioner} sideOffset={4}>
            <Menu.Popup class={styles.MenuPopup}>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Cut
              </Menu.Item>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Copy
              </Menu.Item>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Paste
              </Menu.Item>
            </Menu.Popup>
          </Menu.Positioner>
        </Menu.Portal>
      </Menu.Root>

      <Menu.Root>
        <Menu.Trigger class={styles.MenuTrigger}>View</Menu.Trigger>
        <Menu.Portal>
          <Menu.Positioner class={styles.MenuPositioner} sideOffset={4}>
            <Menu.Popup class={styles.MenuPopup}>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Zoom In
              </Menu.Item>
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Zoom Out
              </Menu.Item>

              <Menu.SubmenuRoot>
                <Menu.SubmenuTrigger class={styles.SubmenuTrigger}>
                  Layout
                  <CaretRightIcon />
                </Menu.SubmenuTrigger>
                <Menu.Portal>
                  <Menu.Positioner class={styles.MenuPositioner} sideOffset={-4} alignOffset={-4}>
                    <Menu.Popup class={styles.MenuPopup}>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        Single Page
                      </Menu.Item>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        Two Pages
                      </Menu.Item>
                      <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                        Continuous
                      </Menu.Item>
                    </Menu.Popup>
                  </Menu.Positioner>
                </Menu.Portal>
              </Menu.SubmenuRoot>

              <Menu.Separator class={styles.MenuSeparator} />
              <Menu.Item class={styles.MenuItem} onClick={handleClick}>
                Full Screen
              </Menu.Item>
            </Menu.Popup>
          </Menu.Positioner>
        </Menu.Portal>
      </Menu.Root>

      <Menu.Root disabled>
        <Menu.Trigger class={styles.MenuTrigger}>Help</Menu.Trigger>
      </Menu.Root>
    </Menubar>
  );
}

function handleClick(event: MouseEvent) {
  // eslint-disable-next-line no-console
  console.log(`${(event.currentTarget as HTMLElement).textContent} clicked`);
}

function CaretRightIcon(props: JSX.IntrinsicElements['svg']) {
  return (
    <svg
      width="16"
      height="16"
      viewBox="0 0 16 16"
      fill="currentColor"
      {...(mergeProps<JSX.IntrinsicElements['svg']>(
        { style: { display: 'block' } },
        props,
      ) as JSX.IntrinsicElements['svg'])}
    >
      <path d="M6 12V4l4.5 4z" />
    </svg>
  );
}

Anatomy

Import the component and assemble its parts:

Anatomy
import { Menubar } from 'base-ui-solid/menubar';
import { Menu } from 'base-ui-solid/menu';

<Menubar>
  <Menu.Root>
    <Menu.Trigger />
    <Menu.Portal>
      <Menu.Backdrop />
      <Menu.Positioner>
        <Menu.Popup>
          <Menu.Arrow />
          <Menu.Item />
          <Menu.LinkItem />
          <Menu.Separator />

          <Menu.SubmenuRoot>
            <Menu.SubmenuTrigger />
          </Menu.SubmenuRoot>

          <Menu.Group>
            <Menu.GroupLabel />
          </Menu.Group>

          <Menu.RadioGroup>
            <Menu.RadioItem>
              <Menu.RadioItemIndicator />
            </Menu.RadioItem>
          </Menu.RadioGroup>

          <Menu.CheckboxItem>
            <Menu.CheckboxItemIndicator />
          </Menu.CheckboxItem>

          <Menu.Viewport />
        </Menu.Popup>
      </Menu.Positioner>
    </Menu.Portal>
  </Menu.Root>
</Menubar>;

API reference

Prop
Type
Default
loopFocusbooleantrue
Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.boolean
modalbooleantrue
Whether the menubar is modal.boolean
disabledbooleanfalse
Whether the whole menubar is disabled.boolean
orientationMenuRoot.Orientation'horizontal'
The orientation of the menubar.MenuRoot.Orientation
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Determines the orientation of the menubar.'horizontal' | 'vertical'
data-has-submenu-open-—
Present when any submenu within the menubar is open.-
data-modal-—
Present when the corresponding menubar is modal.-
Attribute
Description
data-orientation
Determines the orientation of the menubar.
data-has-submenu-open
Present when any submenu within the menubar is open.
data-modal
Present when the corresponding menubar is modal.
Menubar.State
type MenubarState = {
  /** The orientation of the menubar. */
  orientation: MenuRoot.Orientation;
  /** Whether the menubar is modal. */
  modal: boolean;
  /** Whether any submenu within the menubar is open. */
  hasSubmenuOpen: boolean;
};