Menubar
La barra de menús de una app: Archivo, Editar, Ver. Un DropdownMenu por título, coordinados.
import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, … } from "sebs7n-ui/menubar"Ejemplos
El editor de informes
Tab entra una sola vez a la barra; ← → cambian de título y, con un menú abierto, pasar al de al lado lo abre solo. Los atajos de la derecha son el motivo de que el menubar exista: se abre una vez para descubrirlos.
import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "sebs7n-ui/menubar"
import { useState } from "react"
function Editor() {
const [tema, setTema] = useState("sistema")
return (
<Menubar>
<MenubarMenu>
<MenubarTrigger>Archivo</MenubarTrigger>
<MenubarContent>
<MenubarItem>
Nuevo informe
<MenubarShortcut>⌘N</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Abrir…
<MenubarShortcut>⌘O</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Guardar
<MenubarShortcut>⌘S</MenubarShortcut>
</MenubarItem>
<MenubarSub>
<MenubarSubTrigger>Exportar</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem>PDF</MenubarItem>
<MenubarItem>CSV</MenubarItem>
<MenubarItem>Planilla de cálculo</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem variant="destructive">
Descartar borrador…
<MenubarShortcut>⌘⌫</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Editar</MenubarTrigger>
<MenubarContent>
<MenubarItem>
Deshacer
<MenubarShortcut>⌘Z</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Rehacer
<MenubarShortcut>⌘⇧Z</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarItem>
Buscar y reemplazar
<MenubarShortcut>⌘F</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Ver</MenubarTrigger>
<MenubarContent>
<MenubarGroup>
<MenubarLabel>Paneles</MenubarLabel>
<MenubarCheckboxItem defaultChecked>
Barra lateral
<MenubarShortcut>⌘B</MenubarShortcut>
</MenubarCheckboxItem>
<MenubarCheckboxItem>Notas al pie</MenubarCheckboxItem>
</MenubarGroup>
<MenubarSeparator />
<MenubarGroup>
<MenubarLabel>Tema</MenubarLabel>
<MenubarRadioGroup onValueChange={setTema} value={tema}>
<MenubarRadioItem value="claro">Claro</MenubarRadioItem>
<MenubarRadioItem value="oscuro">Oscuro</MenubarRadioItem>
<MenubarRadioItem value="sistema">Sistema</MenubarRadioItem>
</MenubarRadioGroup>
</MenubarGroup>
</MenubarContent>
</MenubarMenu>
</Menubar>
)
}Un título deshabilitado
Cuando un menú entero no aplica al documento abierto, se apaga el título en vez de sacarlo: una barra que cambia de ancho según el archivo obliga a buscar de nuevo cada vez.
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from "sebs7n-ui/menubar"
function Deshabilitado() {
return (
<Menubar>
<MenubarMenu>
<MenubarTrigger>Archivo</MenubarTrigger>
<MenubarContent>
<MenubarItem>Nuevo informe</MenubarItem>
<MenubarItem>Abrir…</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu disabled>
<MenubarTrigger>Tabla</MenubarTrigger>
<MenubarContent>
<MenubarItem>Insertar fila</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Ayuda</MenubarTrigger>
<MenubarContent>
<MenubarItem>Atajos de teclado</MenubarItem>
<MenubarItem>Documentación</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
)
}Props
Generadas del TypeScript del paquete. Las propias del componente, más las heredadas del primitivo que tienen algo que explicar —marcadas «heredada de Base UI»—. El resto está en la línea «hereda de».
Menubar
Hereda las props de Menubar.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
loopFocus | boolean | — | Heredada de Base UI. Si al pasar del último título se vuelve al primero. |
modal | boolean | — | Heredada de Base UI. Con true (el default), mientras hay un menú abierto el resto de la página no recibe clicks. |
MenubarCheckboxItem
Hereda las props de Menu.CheckboxItem.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
inset | boolean | — | Corre el texto a la canaleta del tilde (pl-7) para que alinee con los CheckboxItem y RadioItem del mismo menú. En un menú sin tildes no hace falta. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarContent
Hereda las props de Menu.Popup y Menu.Positioner.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
align | "center" | "end" | "start" | "start" | Cómo se alinea el panel sobre el eje transversal. |
alignOffset | number | OffsetFunction | 0 | Corrimiento en píxeles sobre el eje de alineación. |
side | "left" | "right" | "top" | "bottom" | "inline-end" | "inline-start" | "bottom" | De qué lado del ancla se abre el panel. |
sideOffset | number | OffsetFunction | 6 | Distancia en píxeles entre el ancla y el panel. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarGroup
Hereda las props de Menu.Group.
Sin props propias: pasa todo al primitivo.
MenubarItem
Hereda las props de Menu.Item.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
external | boolean | — | Lleva a otro sitio: texto en el acento y ↗ al final. |
inset | boolean | — | Alinea el texto con el de los ítems que llevan ícono. |
variant | "default" | "destructive" | "default" | destructive: texto e ícono en rojo, para la acción que borra. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarLabel
Hereda las props de Menu.GroupLabel.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
inset | boolean | — | Corre el texto a la canaleta del tilde (pl-7) para que alinee con los CheckboxItem y RadioItem del mismo menú. En un menú sin tildes no hace falta. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarMenu
Hereda las props de Menu.Root.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
actionsRef | React.RefObject<MenuRoot.Actions | null> | — | Heredada de Base UI. Ref con las acciones imperativas de Base UI (unmount()), para desmontarlo sin esperar la animación de salida. |
defaultOpen | boolean | — | Heredada de Base UI. Si arranca abierto. Es la versión no controlada de open. |
disabled | boolean | — | Heredada de Base UI. Apaga la interacción y lo marca con data-disabled, que es el atributo del que cuelgan los estilos de apagado. |
loopFocus | boolean | — | Heredada de Base UI. Si al pasar del último elemento el foco vuelve al primero. |
onOpenChange | ((open: boolean, eventDetails: MenuRoot.ChangeEventDetails) => void) | — | Heredada de Base UI. Se llama con el estado nuevo cada vez que se abre o se cierra. |
open | boolean | — | Heredada de Base UI. Si está abierto. Pasarla lo vuelve controlado: sin onOpenChange ya no se cierra solo. |
MenubarRadioGroup
Hereda las props de Menu.RadioGroup.
Sin props propias: pasa todo al primitivo.
MenubarRadioItem
Hereda las props de Menu.RadioItem.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
inset | boolean | — | Corre el texto a la canaleta del tilde (pl-7) para que alinee con los CheckboxItem y RadioItem del mismo menú. En un menú sin tildes no hace falta. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarSeparator
Hereda las props de Menu.Separator.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarShortcut
Hereda las props de <span>.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarSub
Hereda las props de Menu.SubmenuRoot.
Sin props propias: pasa todo al primitivo.
MenubarSubContent
Hereda las props de Menu.Popup y Menu.Positioner.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
align | "center" | "end" | "start" | "start" | Cómo se alinea el panel sobre el eje transversal. |
alignOffset | number | OffsetFunction | -5 | Corrimiento en píxeles sobre el eje de alineación. |
side | "left" | "right" | "top" | "bottom" | "inline-end" | "inline-start" | "inline-end" | De qué lado del ancla se abre el panel. |
sideOffset | number | OffsetFunction | 2 | Distancia en píxeles entre el ancla y el panel. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarSubTrigger
Hereda las props de Menu.SubmenuTrigger.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
inset | boolean | — | Corre el texto a la canaleta del tilde (pl-7) para que alinee con los CheckboxItem y RadioItem del mismo menú. En un menú sin tildes no hace falta. |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
MenubarTrigger
Hereda las props de Menu.Trigger.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
Teclado
- Tab
- Entra a la barra y sale. Los títulos son una sola parada de tabulación.
- ← →
- Cambia de título. Con un menú abierto, abre el del título al que llegás.
- Home · End
- Primer y último título.
- Enter · Espacio · ↓
- Abre el menú del título enfocado.
- ↑ ↓
- Recorre los ítems del menú abierto.
- → ←
- Entra y sale de un submenú.
- Escribir
- Salta al ítem que empieza con esas letras.
- Enter
- Ejecuta y cierra.
- Escape
- Cierra el menú y devuelve el foco a su título.
- Pasar el mouse
- Con un menú abierto, pasar por otro título lo abre sin click.
Accesibilidad
- Base UI emite
role="menubar"conaria-orientation, y cada menú es elrole="menu"del sistema: el lector anuncia «barra de menús, N elementos». - El recorrido es roving tabindex: la barra entera ocupa una parada de Tab, no una por título.
- Un
MenubarMenu disableddeja el título en la barra y apagado, en vez de sacarlo: una barra que cambia de ancho según el documento obliga a buscar de nuevo cada vez. MenubarShortcutes decorativo: elkeydownlo registra la app. En un check, el atajo va antes del tilde, que ocupa la columna de la derecha.
Reglas de uso
- Casi ninguna web necesita un menubar. Es para apps con decenas de comandos y ninguna otra superficie donde meterlos: un editor, una planilla, una herramienta de diseño.
- Si los ítems son secciones del sitio, lo que querés es `NavigationMenu`. Un menubar usado para navegación esconde atrás de tres menús lo que una barra de links mostraba de entrada.
- Si es un solo grupo de acciones, es un `DropdownMenu` suelto. Una barra de un título no es una barra.
- Sin fondo ni borde propios: vive dentro del header de la app y hereda su superficie.
- Los atajos son la mitad del trabajo: el menú se abre una vez para descubrir el comando y después se usa el teclado para siempre. Un menubar sin
MenubarShortcutdesperdicia el componente.