Menú de navegación
Componente de navegación de página. Admite disposición horizontal / vertical, submenús anidados, estado colapsado y acordeón; la interacción de teclado sigue el patrón de menú de APG.
Disposición vertical (submenús en línea)
El modo vertical en línea admite recorrido por teclado: tras expandir un submenú, ↑/↓ permite moverse cruzando las fronteras entre «elemento hoja ↔ título del submenú ↔ elementos del panel» (Home/End saltan al primero y al último); los elementos deshabilitados y los de paneles cerrados se omiten automáticamente.
- Inicio
- Ajustes▾
- Ajustes básicos
- Ajustes de seguridad
- Elemento deshabilitado
<script setup>
import { ref } from 'vue'
const active = ref('home')
const active2 = ref('settings2-basic')
</script>
<template>
<!-- Disposición vertical -->
<LhMenu v-model="active">
<LhMenuItem index="home">Inicio</LhMenuItem>
<LhSubMenu index="settings" title="Ajustes">
<LhMenuItem index="settings-basic">Ajustes básicos</LhMenuItem>
<LhMenuItem index="settings-security">Ajustes de seguridad</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="docs" disabled>Elemento deshabilitado</LhMenuItem>
</LhMenu>
</template><script>
export default {
data() {
return {
active: 'home',
active2: 'settings2-basic',
}
},
}
</script>
<template>
<!-- Disposición vertical -->
<LhMenu v-model="active">
<LhMenuItem index="home">Inicio</LhMenuItem>
<LhSubMenu index="settings" title="Ajustes">
<LhMenuItem index="settings-basic">Ajustes básicos</LhMenuItem>
<LhMenuItem index="settings-security">Ajustes de seguridad</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="docs" disabled>Elemento deshabilitado</LhMenuItem>
</LhMenu>
</template>Control de expansión
default-openeds define los submenús desplegados inicialmente; openeds (junto con v-model:openeds) es el conjunto controlado de submenús abiertos; unique-opened permite mantener abierto un solo submenú a la vez. LhSubMenu también admite disabled para deshabilitarlo por completo.
- Ajustes (abierto por defecto)▾
- Ajustes básicos
- Ajustes de seguridad
- Gestión (deshabilitado)▾
- Gestión de usuarios
- Acerca de
<script setup>
import { ref } from 'vue'
const active2 = ref('settings2-basic')
</script>
<template>
<!-- Control de expansión -->
<LhMenu
v-model="active2"
:default-openeds="['settings2']"
unique-opened
style="max-width: 240px"
>
<LhSubMenu index="settings2" title="Ajustes (abierto por defecto)">
<LhMenuItem index="settings2-basic">Ajustes básicos</LhMenuItem>
<LhMenuItem index="settings2-security">Ajustes de seguridad</LhMenuItem>
</LhSubMenu>
<LhSubMenu index="manage" title="Gestión (deshabilitado)" disabled>
<LhMenuItem index="manage-users">Gestión de usuarios</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="about2">Acerca de</LhMenuItem>
</LhMenu>
</template><script>
export default {
data() {
return { active2: 'settings2-basic' }
},
}
</script>
<template>
<!-- Control de expansión -->
<LhMenu
v-model="active2"
:default-openeds="['settings2']"
unique-opened
style="max-width: 240px"
>
<LhSubMenu index="settings2" title="Ajustes (abierto por defecto)">
<LhMenuItem index="settings2-basic">Ajustes básicos</LhMenuItem>
<LhMenuItem index="settings2-security">Ajustes de seguridad</LhMenuItem>
</LhSubMenu>
<LhSubMenu index="manage" title="Gestión (deshabilitado)" disabled>
<LhMenuItem index="manage-users">Gestión de usuarios</LhMenuItem>
</LhSubMenu>
<LhMenuItem index="about2">Acerca de</LhMenuItem>
</LhMenu>
</template>- Ajustes▾
- Ajustes básicos
<script setup lang="ts">
import { ref } from 'vue'
const active2 = ref('settings2-basic')
</script>
<template>
<!-- Conjunto controlado de abiertos -->
<LhMenu v-model="active2" :openeds="['settings2']">
<LhSubMenu index="settings2" title="Ajustes">
<LhMenuItem index="settings2-basic">Ajustes básicos</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template><script>
export default {
data() {
return { active2: 'settings2-basic' }
},
}
</script>
<template>
<!-- Conjunto controlado de abiertos -->
<LhMenu v-model="active2" :openeds="['settings2']">
<LhSubMenu index="settings2" title="Ajustes">
<LhMenuItem index="settings2-basic">Ajustes básicos</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>Disposición horizontal (submenús desplegables)
- Inicio
- Ajustes▾
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('home')
</script>
<template>
<!-- Disposición horizontal -->
<LhMenu v-model="active" mode="horizontal">
<LhMenuItem index="home">Inicio</LhMenuItem>
<LhSubMenu index="settings" title="Ajustes">
<LhMenuItem index="settings-basic">Ajustes básicos</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template><script>
export default {
data() {
return { active: 'home' }
},
}
</script>
<template>
<!-- Disposición horizontal -->
<LhMenu v-model="active" mode="horizontal">
<LhMenuItem index="home">Inicio</LhMenuItem>
<LhSubMenu index="settings" title="Ajustes">
<LhMenuItem index="settings-basic">Ajustes básicos</LhMenuItem>
</LhSubMenu>
</LhMenu>
</template>Estado colapsado y agrupación
- Contenido
- Inicio
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('home')
</script>
<template>
<!-- Colapso + agrupación -->
<LhMenu v-model="active" collapse>
<LhMenuItemGroup title="Contenido">
<LhMenuItem index="home">Inicio</LhMenuItem>
</LhMenuItemGroup>
</LhMenu>
</template><script>
export default {
data() {
return { active: 'home' }
},
}
</script>
<template>
<!-- Colapso + agrupación -->
<LhMenu v-model="active" collapse>
<LhMenuItemGroup title="Contenido">
<LhMenuItem index="home">Inicio</LhMenuItem>
</LhMenuItemGroup>
</LhMenu>
</template>API
LhMenu Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| modelValue | Elemento activo actual (v-model controlado; si no se pasa, se mantiene internamente) | string | — |
| mode | Modo de disposición | "horizontal" | "vertical" | 'vertical' |
| collapse | El modo vertical se colapsa en una barra de iconos (los submenús pasan a paneles desplegables) | boolean | false |
| defaultOpeneds | Claves de los submenús abiertos por defecto (no controlado) | string[] | () => [] |
| openeds | Claves de los submenús abiertos (controlado) | string[] | — |
| uniqueOpened | Acordeón: solo un submenú abierto a la vez | boolean | false |
| sx | Props de maquetación rápida sx | LhSxProps | — |
Eventos
| Evento | Descripción | Parámetro |
|---|---|---|
| update:modelValue | Se dispara al cambiar el elemento activo (v-model) | (value: string) |
| update:openeds | Se dispara al cambiar el conjunto de submenús abiertos (v-model:openeds) | (value: string[]) |
| select | Se dispara al seleccionar un elemento del menú | (index: string, indexPath: string[]) |
| open | Se dispara al abrir un submenú | (index: string, indexPath: string[]) |
| close | Se dispara al cerrar un submenú | (index: string, indexPath: string[]) |
LhMenuItem Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| index | Identificador único (obligatorio) | string | — |
| disabled | Deshabilitado | boolean | false |
| sx | Props de maquetación rápida sx | LhSxProps | — |
Eventos: click(index); slot: default.
LhSubMenu Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| index | Identificador único (obligatorio) | string | — |
| title | Título (también se puede usar el slot title) | string | — |
| disabled | Deshabilitado | boolean | false |
| sx | Props de maquetación rápida sx | LhSxProps | — |
Eventos: select(index, indexPath) (burbujea); slots: title, default (puede anidar más LhSubMenu).
LhMenuItemGroup Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| title | Título del grupo (también se puede usar el slot title) | string | — |
| sx | Props de maquetación rápida sx | LhSxProps | — |
Slots: title, default.
Accesibilidad
- El modo horizontal usa
role="menubar"y el verticalrole="menu"; los elementos sonrole="menuitem"y los gruposrole="group"(el contenedor,role="presentation") - El título del submenú relaciona el panel con
aria-haspopup+aria-expanded+aria-controls - Teclado: Enter/Space/→ abre y enfoca el primer elemento, ← cierra, Esc sale; en el modo vertical en línea, ↑/↓/Home/End recorren en bucle los elementos visibles (elementos hoja, títulos de submenú y elementos de paneles abiertos) cruzando sus fronteras, y omiten automáticamente los deshabilitados y los de paneles cerrados
- La altura de expansión en línea usa CSS
grid-template-rows: 0fr/1fr(cero mediciones JS); los paneles desplegables los posiciona el motor popper (flip/shift/cierre fuera de la ventana)
Definiciones de tipos
Las estructuras de tipos TypeScript que exporta este componente son las siguientes (extraídas automáticamente de packages/components/menu/src/types.ts y del código fuente de @lh-ui/share/core/*; despliega cada entrada para ver la definición completa; la descripción de los atributos está en la tabla de Props de arriba):
LhMenuProps
/** Props del menú */
export interface LhMenuProps {
/** Elemento activo actual (v-model controlado; si no se pasa, el componente lo mantiene internamente) */
modelValue?: string
/** Modo de disposición */
mode?: LhMenuMode
/** El modo vertical se colapsa en una barra de iconos (los submenús pasan a paneles desplegables) */
collapse?: boolean
/** Claves de los submenús abiertos por defecto (no controlado) */
defaultOpeneds?: string[]
/** Claves de los submenús abiertos (controlado) */
openeds?: string[]
/** Acordeón: solo un submenú abierto a la vez */
uniqueOpened?: boolean
/** Props de maquetación rápida sx */
sx?: LhSxProps
}LhMenuItemProps
/** Props del elemento hoja */
export interface LhMenuItemProps {
/** Identificador único (obligatorio) */
index: string
disabled?: boolean
/** Props de maquetación rápida sx */
sx?: LhSxProps
}LhSubMenuProps
/** Props del submenú (anidable de forma recursiva) */
export interface LhSubMenuProps {
/** Identificador único (obligatorio) */
index: string
/** Título (también se puede usar el slot title) */
title?: string
disabled?: boolean
/** Props de maquetación rápida sx */
sx?: LhSxProps
}LhMenuItemGroupProps
/** Props del grupo */
export interface LhMenuItemGroupProps {
/** Título del grupo (también se puede usar el slot title) */
title?: string
/** Props de maquetación rápida sx */
sx?: LhSxProps
}LhMenuMode (de @lh-ui/share/core/menu)
/** Modo de disposición del menú */
export type LhMenuMode = 'horizontal' | 'vertical'