Markdown:
Components

MenuSub

A submenu trigger that opens a nested menu list inside a parent menu.

Usage

Use inside MenuList to trigger a nested MenuList.

Svelte
<MenuList>
  <MenuSub label="More">
    <MenuList />
  </MenuSub>
</MenuList>

Anatomy

The class attribute values represent part names. Other attributes represent their corresponding props.

Svelte
<div class="whole" role="none">
  <button class="main" {...rest} id type="button" role="menuitem" tabindex="-1" aria-haspopup="menu" aria-expanded aria-disabled style>{label}</button>
  <div class="middle" role="none" popover="manual" style>{children}</div>
</div>

Provides MenuContainerContext to its nested MenuList, labels that submenu from the trigger, opens on click, hover, Enter, Space, and the forward arrow for the parent menu orientation, and closes one level on Escape or the back arrow. Hover uses a per-level safe triangle while moving toward the submenu. Hover-opening focuses the submenu's first enabled item through MenuList's existing open effect.

Props

NameTypeDefaultDescription
children*Snippet-Must render the submenu's MenuList; receives the variant as its argument
label*string / Snippet-Trigger content; a snippet receives the variant as its argument
openbooleanfalseBindable open state; observable, not a positioning control
disabledbooleanfalseSets aria-disabled, skips menu navigation, and prevents opening
attachAttachment-Svelte attachment on the trigger
elementHTMLButtonElement-Bindable trigger element
stylingSVSClass-Styling override
variantSVSVariantNEUTRALSubmenu variant

* required. Other button attributes are passed to the trigger via rest props; class is merged onto the trigger.

Styling

To learn more, see Styling.

Variant Management

No automatic switching. Inside a MenuList, variant and styling fall back to the parent menu's via context.

Default Class Name

svs-menu-sub

Behavior

Provides MenuContainerContext to its nested MenuList and labels that submenu from the trigger. It opens on click, hover, Enter, Space, and the forward arrow for the parent menu's orientation, and closes one level on Escape or the back arrow.

Hover uses a per-level safe triangle while the pointer moves toward the submenu. Hover-opening focuses the submenu's first enabled item through MenuList's existing open effect.

Accessibility

Keyboard Interactions

KeyDescription
Enter / SpaceToggles the submenu
ArrowRight / ArrowDownOpens the submenu; ArrowRight in a vertical menu, ArrowDown in a horizontal one
ArrowLeft / ArrowUpCloses the submenu and returns focus to the trigger; ArrowLeft in a vertical menu, ArrowUp in a horizontal one
EscapeCloses the submenu, returning focus to the trigger

For item navigation and type-ahead, see MenuList.

ARIA Roles and Attributes

The component applies these automatically:

  • Trigger (main <button>): role="menuitem", tabindex="-1", aria-haspopup="menu", aria-expanded, and aria-disabled when disabled.
  • Wrappers (whole and middle): role="none".
  • Submenu: named from the trigger.

Menu navigation and roving focus are owned by the parent and nested MenuList components.

Exports

Types

TypeScript
interface MenuSubProps extends Omit<HTMLButtonAttributes, "children" | "type" | "role" | "disabled"> {
  children: Snippet<[string]>; // Snippet<[variant]>; must render the submenu's MenuList
  label: string | Snippet<[string]>; // Snippet<[variant]>; trigger content
  open?: boolean; // bindable (false); to observe state, not to control
  disabled?: boolean; // (false) -> aria-disabled; skipped in nav; non-openable
  attach?: Attachment<HTMLButtonElement>;
  element?: HTMLButtonElement; // bindable; the trigger
  styling?: SVSClass;
  variant?: SVSVariant; // (VARIANT.NEUTRAL)
  // other HTMLButtonAttributes are passed to the trigger via ...rest; `class` is merged onto the trigger
  // id, type, role, tabindex, aria-haspopup, aria-expanded, aria-disabled, style, and handlers are component-owned
}
type MenuSubReqdProps = "children" | "label";
type MenuSubBindProps = "open" | "element";

Others

No additional exports are available.

Examples

The example code uses Tailwind CSS along with SVSClass.

Basic

With Interactive Variant

Preset for Demo
Enter variant as you like