Menu

Menús desplegables y de contexto anidados componibles.

La primitiva Menu es un componente de menú desplegable modular de navegación y selector de opciones que soporta accesibilidad por teclado, submenús anidados, indexación de búsqueda y casillas de verificación de selección.

Inicio RápidoLink

Compón un menú desplegable de acciones totalmente accesible:

tsx
import { Menu, Button } from 'boltdocs/primitives'

export default function FileActions() {
  return (
    <Menu.Trigger placement="bottom start">
      <Button className="px-4 py-2 bg-primary-500 text-white rounded-lg">
        Acciones
      </Button>
      <Menu className="p-1 bg-surface border border-subtle rounded-lg shadow-lg w-48 flex flex-col gap-0.5">
        <Menu.Item
          onAction={() => alert('¡Nuevo documento creado!')}
          className="px-3 py-1.5 text-xs text-body hover:bg-soft rounded cursor-default"
        >
          Nuevo Archivo
        </Menu.Item>
        <Menu.Item
          onAction={() => alert('¡Documento copiado!')}
          className="px-3 py-1.5 text-xs text-body hover:bg-soft rounded cursor-default"
        >
          Duplicar Archivo
        </Menu.Item>
        <Menu.Separator className="border-t border-subtle my-1" />
        <Menu.Item
          onAction={() => alert('¡Documento eliminado!')}
          className="px-3 py-1.5 text-xs text-danger-500 hover:bg-danger-500/10 rounded cursor-default"
        >
          Eliminar Archivo
        </Menu.Item>
      </Menu>
    </Menu.Trigger>
  )
}

Subcomponentes ComponiblesLink

Compón menús de selección enriquecidos y árboles de diseño anidados usando los siguientes espacios de nombres:

ComponenteEtiqueta HTMLDescripciónProps
Menu.Root / Menu<div> (menu)Envoltorio que contiene el viewport de la lista de elementos del menú.MenuProps
Menu.TriggerEnvoltorioEnvuelve el botón Trigger y la superposición emergente del menú.MenuTriggerProps
Menu.SubTriggerEnvoltorioEnvuelve elementos de disparador padre y capas de submenú hijo anidadas.SubmenuTriggerProps
Menu.Item<div> (menuitem)Un elemento clickeable individual dentro de la lista de selección del menú.MenuItemProps
Menu.Section<div>Agrupa una colección de elementos bajo una etiqueta de sección específica.MenuSectionProps
Menu.Separator<hr>Separador visual que divide categorías de opciones.SeparatorProps

Props del ComponenteLink

Hereda las configuraciones estándar de MenuProps de React Aria:

PropiedadTipoPredeterminadoDescripción
onAction(key: Key) => voidundefinedCallback invocado cuando cualquier elemento no deshabilitado es clickeado/seleccionado.
classNamestringundefinedClases CSS personalizadas.

Hereda MenuTriggerProps de React Aria más:

PropiedadTipoPredeterminadoDescripción
placement'bottom' | 'top' | 'left' | 'right' | 'start' | 'end''bottom'Posición de alineación relativa al disparador.

Hereda MenuItemProps estándar de React Aria (por ejemplo, isDisabled, onAction):

PropiedadTipoPredeterminadoDescripción
textValuestringundefinedValor de texto equivalente que coincide con el elemento para autocompletado de búsqueda por teclado.
PropiedadTipoPredeterminadoDescripción
titlestringundefinedTexto del encabezado de la etiqueta de sección.

Personalización y estadosLink

Menu está construido sobre el Menu de React Aria, por lo que aporta el manejo de la interacción (navegación por teclado, selección, submenús) sin visuales. El estilo vive en el tema: el Menu.Root y cada Menu.Item aceptan un className como función de renderizado, y RAC refleja los estados de selección y foco en cada elemento como atributos data-* para apuntar desde CSS.

Estado / SlotMecanismo
className de Menu.Item (función)Recibe { isHovered, isFocused, isFocusVisible, isPressed, isSelected, isDisabled }
children de Menu.Item (función)Recibe { selectionMode, isSelected, hasSubmenu }
data-selectedPresente en el elemento cuando está seleccionado (modo de selección con casillas)
data-focused / data-focus-visiblePresentes en elementos enfocados por teclado
data-hovered / data-pressedEstados de interacción con el puntero
data-disabledPresente en elementos deshabilitados
className de Menu.Root (función)Recibe { isEmpty }

Tailwind v4:

tsx
<Menu.Item
  className={({ isSelected, isFocused }) =>
    `px-3 py-1.5 text-xs rounded cursor-default ${
      isSelected
        ? 'bg-primary-500/10 text-primary-400'
        : isFocused
          ? 'bg-soft text-body'
          : 'text-body'
    }`
  }
>
  Opción de Alternar
</Menu.Item>
Last updated on October 18, 2026

Was this page helpful?