Skip to content
API 风格:

Menu ​

Page navigation. Horizontal / vertical layouts, nested submenus, collapse mode, accordion, keyboard aligned with the APG menu pattern.

Vertical (inline submenus) ​

Vertical inline mode supports keyboard traversal: once a submenu is expanded, ↑/↓ move across boundaries between leaf items, submenu titles and panel items (Home/End jump to the ends), skipping disabled items and items inside collapsed panels.

Vertical
vue
<script setup>
import { ref } from 'vue'
const active = ref('home')
</script>

<template>
  <!-- Vertical -->
  <LhMenu v-model="active">
    <LhMenuItem index="home">Home</LhMenuItem>
    <LhSubMenu index="settings" title="Settings">
      <LhMenuItem index="settings-basic">Basic</LhMenuItem>
      <LhMenuItem index="settings-security">Security</LhMenuItem>
    </LhSubMenu>
    <LhMenuItem index="docs" disabled>Disabled</LhMenuItem>
  </LhMenu>
</template>
vue
<script>
export default {
  data() {
    return { active: 'home' }
  },
}
</script>

<template>
  <!-- Vertical -->
  <LhMenu v-model="active">
    <LhMenuItem index="home">Home</LhMenuItem>
    <LhSubMenu index="settings" title="Settings">
      <LhMenuItem index="settings-basic">Basic</LhMenuItem>
      <LhMenuItem index="settings-security">Security</LhMenuItem>
    </LhSubMenu>
    <LhMenuItem index="docs" disabled>Disabled</LhMenuItem>
  </LhMenu>
</template>

Expansion control ​

default-openeds lists submenus expanded initially; openeds (with v-model:openeds) controls the open set; unique-opened allows only one submenu open at a time. LhSubMenu also accepts disabled.

Expansion control
  • vue
    <script setup>
    import { ref } from 'vue'
    const active2 = ref('settings2-basic')
    </script>
    
    <template>
      <!-- Expansion control -->
      <LhMenu
        v-model="active2"
        :default-openeds="['settings2']"
        unique-opened
        style="max-width: 240px"
      >
        <LhSubMenu index="settings2" title="Settings (open by default)">
          <LhMenuItem index="settings2-basic">Basic</LhMenuItem>
        </LhSubMenu>
        <LhSubMenu index="manage" title="Manage (disabled)" disabled>
          <LhMenuItem index="manage-users">Users</LhMenuItem>
        </LhSubMenu>
        <LhMenuItem index="about2">About</LhMenuItem>
      </LhMenu>
    </template>
    vue
    <script>
    export default {
      data() {
        return { active2: 'settings2-basic' }
      },
    }
    </script>
    
    <template>
      <!-- Expansion control -->
      <LhMenu
        v-model="active2"
        :default-openeds="['settings2']"
        unique-opened
        style="max-width: 240px"
      >
        <LhSubMenu index="settings2" title="Settings (open by default)">
          <LhMenuItem index="settings2-basic">Basic</LhMenuItem>
        </LhSubMenu>
        <LhSubMenu index="manage" title="Manage (disabled)" disabled>
          <LhMenuItem index="manage-users">Users</LhMenuItem>
        </LhSubMenu>
        <LhMenuItem index="about2">About</LhMenuItem>
      </LhMenu>
    </template>
    Controlled open set
    vue
    <script setup lang="ts">
    import { ref } from 'vue'
    
    const active2 = ref('settings2-basic')
    </script>
    
    <template>
      <!-- Controlled open set -->
      <LhMenu v-model="active2" :openeds="['settings2']">
        <LhSubMenu index="settings2" title="Settings">
          <LhMenuItem index="settings2-basic">Basic</LhMenuItem>
        </LhSubMenu>
      </LhMenu>
    </template>
    vue
    <script>
    export default {
      data() {
        return { active2: 'settings2-basic' }
      },
    }
    </script>
    
    <template>
      <!-- Controlled open set -->
      <LhMenu v-model="active2" :openeds="['settings2']">
        <LhSubMenu index="settings2" title="Settings">
          <LhMenuItem index="settings2-basic">Basic</LhMenuItem>
        </LhSubMenu>
      </LhMenu>
    </template>

    Horizontal (flyout submenus) ​

    Horizontal
    vue
    <script setup lang="ts">
    import { ref } from 'vue'
    
    const active = ref('home')
    </script>
    
    <template>
      <!-- Horizontal -->
      <LhMenu v-model="active" mode="horizontal">
        <LhMenuItem index="home">Home</LhMenuItem>
        <LhSubMenu index="settings" title="Settings">
          <LhMenuItem index="settings-basic">Basic</LhMenuItem>
        </LhSubMenu>
      </LhMenu>
    </template>
    vue
    <script>
    export default {
      data() {
        return { active: 'home' }
      },
    }
    </script>
    
    <template>
      <!-- Horizontal -->
      <LhMenu v-model="active" mode="horizontal">
        <LhMenuItem index="home">Home</LhMenuItem>
        <LhSubMenu index="settings" title="Settings">
          <LhMenuItem index="settings-basic">Basic</LhMenuItem>
        </LhSubMenu>
      </LhMenu>
    </template>

    Collapse and groups ​

    Collapse + group
    vue
    <script setup lang="ts">
    import { ref } from 'vue'
    
    const active = ref('home')
    </script>
    
    <template>
      <!-- Collapse + group -->
      <LhMenu v-model="active" collapse>
        <LhMenuItemGroup title="Content">
          <LhMenuItem index="home">Home</LhMenuItem>
        </LhMenuItemGroup>
      </LhMenu>
    </template>
    vue
    <script>
    export default {
      data() {
        return { active: 'home' }
      },
    }
    </script>
    
    <template>
      <!-- Collapse + group -->
      <LhMenu v-model="active" collapse>
        <LhMenuItemGroup title="Content">
          <LhMenuItem index="home">Home</LhMenuItem>
        </LhMenuItemGroup>
      </LhMenu>
    </template>

    API ​

    LhMenu Props ​

    AttributeDescriptionTypeDefault
    modelValueActive item (controlled v-model; internal state when omitted)string—
    modeLayout mode"horizontal" | "vertical"'vertical'
    collapseCollapse vertical menu to an icon bar (submenus become flyouts)booleanfalse
    defaultOpenedsOpened submenu keys (uncontrolled)string[]() => []
    openedsOpened submenu keys (controlled)string[]—
    uniqueOpenedAccordion: only one submenu open at a timebooleanfalse
    sxQuick layout propsLhSxProps—

    LhMenu Events ​

    EventDescriptionCallback
    update:modelValueActive item changed (v-model)(value: string) => void
    selectA menu item is activated(index: string, indexPath: string[]) => void
    openA submenu expands(index: string, indexPath: string[]) => void
    closeA submenu collapses(index: string, indexPath: string[]) => void
    update:openedsOpened submenu keys changed (v-model:openeds)(value: string[]) => void

    LhMenuItem Props ​

    AttributeDescriptionTypeDefault
    indexUnique key (required)string—
    disabledDisabledbooleanfalse
    sxQuick layout propsLhSxProps—

    LhMenuItem Events ​

    EventDescriptionCallback
    clickItem is clicked; the menu emits select afterwards(index: string) => void

    Slot: default.

    LhSubMenu Props ​

    AttributeDescriptionTypeDefault
    indexUnique key (required)string—
    titleTitle (or title slot)string—
    disabledDisabledbooleanfalse
    sxQuick layout propsLhSxProps—

    LhSubMenu Events ​

    EventDescriptionCallback
    selectAn item inside the submenu is activated (bubbles from nested items)(index: string, indexPath: string[]) => void

    Slots: title, default (nest LhSubMenu recursively).

    LhMenuItemGroup Props ​

    AttributeDescriptionTypeDefault
    titleGroup title (or title slot)string—
    sxQuick layout propsLhSxProps—

    Slots: title, default.

    Accessibility ​

    Type Definitions ​

    The TypeScript type structures exported by this component (auto-extracted from packages/components/menu/src/types.ts and @lh-ui/share/core/* sources; click each entry to expand; see the Props table above for attribute descriptions):

    LhMenuProps
    ts
    export interface LhMenuProps {
      modelValue?: string
      mode?: LhMenuMode
      collapse?: boolean
      defaultOpeneds?: string[]
      openeds?: string[]
      uniqueOpened?: boolean
      sx?: LhSxProps
    }
    LhMenuItemProps
    ts
    export interface LhMenuItemProps {
      index: string
      disabled?: boolean
      sx?: LhSxProps
    }
    LhSubMenuProps
    ts
    export interface LhSubMenuProps {
      index: string
      title?: string
      disabled?: boolean
      sx?: LhSxProps
    }
    LhMenuItemGroupProps
    ts
    export interface LhMenuItemGroupProps {
      title?: string
      sx?: LhSxProps
    }
    LhMenuMode (from @lh-ui/share/core/menu)
    ts
    export type LhMenuMode = 'horizontal' | 'vertical'