Menu ナビゲーションメニュー
ページナビゲーションコンポーネント。水平 / 垂直レイアウト、ネストしたサブメニュー、折りたたみ状態、アコーディオンに対応し、キーボード操作は APG の menu pattern に準拠しています。
垂直レイアウト(インラインサブメニュー)
垂直インラインモードはキーボードのトラバーサルに対応しています:サブメニューを展開したあと ↑/↓ で「葉項目 ↔ サブメニュー見出し ↔ パネル内項目」の境界を越えて移動でき(Home/End で先頭・末尾へジャンプ)、無効な項目と折りたたまれたパネル内の項目は自動的にスキップされます。
垂直レイアウト
- ホーム
- 設定▾
- 基本設定
- セキュリティ設定
- 無効な項目
vue
<script setup>
import { ref } from 'vue'
const active = ref('home')
const active2 = ref('settings2-basic')
</script>
<template>
<!-- 垂直レイアウト -->
<LhMenu v-model="active">
<LhMenuItem index="home">ホーム</LhMenuItem>
<LhSubMenu index="settings" title="設定">
<LhMenuItem index="settings-basic">基本設定</LhMenuItem>
<LhMenuItem index="settings-security">セキュリティ設定</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="docs" disabled>無効な項目</LhMenuItem>
</LhMenu>
</template>vue
<script>
export default {
data() {
return {
active: 'home',
active2: 'settings2-basic',
}
},
}
</script>
<template>
<!-- 垂直レイアウト -->
<LhMenu v-model="active">
<LhMenuItem index="home">ホーム</LhMenuItem>
<LhSubMenu index="settings" title="設定">
<LhMenuItem index="settings-basic">基本設定</LhMenuItem>
<LhMenuItem index="settings-security">セキュリティ設定</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="docs" disabled>無効な項目</LhMenuItem>
</LhMenu>
</template>展開制御
default-openeds は初期展開するサブメニュー、openeds(v-model:openeds と併用)は制御された展開集合、unique-opened は同時に展開できるサブメニューを 1 つに制限します。LhSubMenu は disabled で全体を無効化することもできます。
展開制御
- 設定(デフォルト展開)▾
- 基本設定
- セキュリティ設定
- 管理(無効)▾
- ユーザー管理
- 概要
vue
<script setup>
import { ref } from 'vue'
const active2 = ref('settings2-basic')
</script>
<template>
<!-- 展開制御 -->
<LhMenu
v-model="active2"
:default-openeds="['settings2']"
unique-opened
style="max-width: 240px"
>
<LhSubMenu index="settings2" title="設定(デフォルト展開)">
<LhMenuItem index="settings2-basic">基本設定</LhMenuItem>
<LhMenuItem index="settings2-security">セキュリティ設定</LhMenuItem>
</LhSubMenu>
<LhSubMenu index="manage" title="管理(無効)" disabled>
<LhMenuItem index="manage-users">ユーザー管理</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="about2">概要</LhMenuItem>
</LhMenu>
</template>vue
<script>
export default {
data() {
return { active2: 'settings2-basic' }
},
}
</script>
<template>
<!-- 展開制御 -->
<LhMenu
v-model="active2"
:default-openeds="['settings2']"
unique-opened
style="max-width: 240px"
>
<LhSubMenu index="settings2" title="設定(デフォルト展開)">
<LhMenuItem index="settings2-basic">基本設定</LhMenuItem>
<LhMenuItem index="settings2-security">セキュリティ設定</LhMenuItem>
</LhSubMenu>
<LhSubMenu index="manage" title="管理(無効)" disabled>
<LhMenuItem index="manage-users">ユーザー管理</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="about2">概要</LhMenuItem>
</LhMenu>
</template>制御された展開集合
- 設定▾
- 基本設定
vue
<script setup lang="ts">
import { ref } from 'vue'
const active2 = ref('settings2-basic')
</script>
<template>
<!-- 制御された展開集合 -->
<LhMenu v-model="active2" :openeds="['settings2']">
<LhSubMenu index="settings2" title="設定">
<LhMenuItem index="settings2-basic">基本設定</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>vue
<script>
export default {
data() {
return { active2: 'settings2-basic' }
},
}
</script>
<template>
<!-- 制御された展開集合 -->
<LhMenu v-model="active2" :openeds="['settings2']">
<LhSubMenu index="settings2" title="設定">
<LhMenuItem index="settings2-basic">基本設定</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>水平レイアウト(フライアウトサブメニュー)
水平レイアウト
- ホーム
- 設定▾
vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('home')
</script>
<template>
<!-- 水平レイアウト -->
<LhMenu v-model="active" mode="horizontal">
<LhMenuItem index="home">ホーム</LhMenuItem>
<LhSubMenu index="settings" title="設定">
<LhMenuItem index="settings-basic">基本設定</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>vue
<script>
export default {
data() {
return { active: 'home' }
},
}
</script>
<template>
<!-- 水平レイアウト -->
<LhMenu v-model="active" mode="horizontal">
<LhMenuItem index="home">ホーム</LhMenuItem>
<LhSubMenu index="settings" title="設定">
<LhMenuItem index="settings-basic">基本設定</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>折りたたみとグループ分け
折りたたみ + グループ
- コンテンツ
- ホーム
vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('home')
</script>
<template>
<!-- 折りたたみ + グループ -->
<LhMenu v-model="active" collapse>
<LhMenuItemGroup title="コンテンツ">
<LhMenuItem index="home">ホーム</LhMenuItem>
</LhMenuItemGroup>
</LhMenu>
</template>vue
<script>
export default {
data() {
return { active: 'home' }
},
}
</script>
<template>
<!-- 折りたたみ + グループ -->
<LhMenu v-model="active" collapse>
<LhMenuItemGroup title="コンテンツ">
<LhMenuItem index="home">ホーム</LhMenuItem>
</LhMenuItemGroup>
</LhMenu>
</template>API
LhMenu Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| modelValue | 現在のアクティブ項目(制御された v-model;未指定時は内部で管理) | string | — |
| mode | レイアウトモード | "horizontal" | "vertical" | 'vertical' |
| collapse | 垂直モードをアイコンバーに折りたたむ(サブメニューはフライアウトパネルになる) | boolean | false |
| defaultOpeneds | デフォルトで展開されるサブメニューキー(非制御) | string[] | () => [] |
| openeds | 制御された展開サブメニューキー | string[] | — |
| uniqueOpened | アコーディオン:同時に展開できるサブメニューは 1 つのみ | boolean | false |
| sx | sx クイックレイアウトプロパティ | LhSxProps | — |
Events
| イベント名 | 説明 | コールバック引数 |
|---|---|---|
| update:modelValue | アクティブ項目が変化したときに発生(v-model) | (value: string) |
| update:openeds | 展開サブメニュー集合が変化したときに発生(v-model:openeds) | (value: string[]) |
| select | メニュー項目が選択されたときに発生 | (index: string, indexPath: string[]) |
| open | サブメニューが展開されたときに発生 | (index: string, indexPath: string[]) |
| close | サブメニューが折りたたまれたときに発生 | (index: string, indexPath: string[]) |
LhMenuItem Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| index | 一意識別子(必須) | string | — |
| disabled | 無効 | boolean | false |
| sx | sx クイックレイアウトプロパティ | LhSxProps | — |
イベント:click(index);スロット:default。
LhSubMenu Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| index | 一意識別子(必須) | string | — |
| title | 見出し(title スロットでも可) | string | — |
| disabled | 無効 | boolean | false |
| sx | sx クイックレイアウトプロパティ | LhSxProps | — |
イベント:select(index, indexPath)(バブリング);スロット:title、default(さらに LhSubMenu をネスト可能)。
LhMenuItemGroup Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| title | グループ見出し(title スロットでも可) | string | — |
| sx | sx クイックレイアウトプロパティ | LhSxProps | — |
スロット:title、default。
アクセシビリティ
- 水平は
role="menubar"、垂直はrole="menu";項目はrole="menuitem"、グループはrole="group"(コンテナはrole="presentation") - サブメニュー見出しは
aria-haspopup+aria-expanded+aria-controlsでパネルと紐付け - キーボード:Enter/Space/→ で展開して先頭項目にフォーカス、← で折りたたみ、Esc で閉じる;垂直インラインモードでは ↑/↓/Home/End が可視項目(葉項目、サブメニュー見出し、展開されたパネル内項目)の間を境界越えにトラバースしループする。無効な項目と折りたたまれたパネル内の項目は自動的にスキップ
- インライン展開の高さには CSS
grid-template-rows: 0fr/1frを使用(JS による高さ測定ゼロ);フライアウトパネルは popper エンジンが配置(flip/shift/ビポート外での折りたたみ)
型定義
本コンポーネントが外部にエクスポートする TypeScript 型構造は以下のとおりです(packages/components/menu/src/types.ts および @lh-ui/share/core/* ソースから自動抽出。各エントリをクリックすると完全な定義を確認できます。プロパティの説明は上記の Props 表を参照してください):
LhMenuProps
ts
/** メニュー props */
export interface LhMenuProps {
/** 現在のアクティブ項目(制御された v-model;未指定時はコンポーネント内部で管理) */
modelValue?: string
/** レイアウトモード */
mode?: LhMenuMode
/** 垂直モードをアイコンバーに折りたたむ(サブメニューはフライアウトパネルになる) */
collapse?: boolean
/** デフォルトで展開されるサブメニューキー(非制御) */
defaultOpeneds?: string[]
/** 制御された展開サブメニューキー */
openeds?: string[]
/** アコーディオン:同時に展開できるサブメニューは 1 つのみ */
uniqueOpened?: boolean
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhMenuItemProps
ts
/** 葉項目 props */
export interface LhMenuItemProps {
/** 一意識別子(必須) */
index: string
disabled?: boolean
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhSubMenuProps
ts
/** サブメニュー props(再帰的にネスト可能) */
export interface LhSubMenuProps {
/** 一意識別子(必須) */
index: string
/** 見出し(title スロットでも可) */
title?: string
disabled?: boolean
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhMenuItemGroupProps
ts
/** グループ props */
export interface LhMenuItemGroupProps {
/** グループ見出し(title スロットでも可) */
title?: string
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhMenuMode (@lh-ui/share/core/menu から)
ts
/** メニューレイアウトモード */
export type LhMenuMode = 'horizontal' | 'vertical'