componentes / menu
Menu
Botão de menu suspenso com navegação por setas, busca por digitação, ícones, separadores e itens perigosos.
Como usar
A lista é `role="menu"` com botões `menuitem`. Setas, Home e End movem entre itens (desabilitados são pulados), digitar uma letra salta para um item correspondente, Enter/Espaço seleciona, Esc fecha e devolve o foco ao gatilho. `onSelect` roda no clique e no teclado; chame `event.preventDefault()` nele para manter o menu aberto. Monte com `MenuItem`, `MenuLabel` e `MenuSeparator`.
preview
Menu.tsx
import { Button, Menu, MenuItem, MenuLabel, MenuSeparator } from "vaiperui"; <Menu trigger={<Button variant="outlined">Ações</Button>} label="Ações"> <MenuLabel>Projeto</MenuLabel> <MenuItem icon="✎" onSelect={() => rename()}>Renomear</MenuItem> <MenuItem disabled>Arquivar</MenuItem> <MenuSeparator /> <MenuItem destructive icon="✕">Excluir</MenuItem></Menu>Alinhamento
preview
alinhamento.tsx
<Menu align="start" trigger={<Button>start</Button>}>...</Menu><Menu align="center" trigger={<Button>center</Button>}>...</Menu><Menu align="end" trigger={<Button>end</Button>}>...</Menu>Props
| Prop | Valores | Padrão | Descrição |
|---|---|---|---|
| trigger | ReactElement | nenhum | Botão que abre o menu (precisa de ref, foco e onClick) |
| label | string | nenhum | Nome acessível do menu |
| side / align | top | right | bottom | left / start | center | end | bottom / start | Lado do gatilho e alinhamento |
| open / defaultOpen / onOpenChange | boolean / boolean / (open) => void | nenhum | Estado aberto controlado ou não controlado |
| size | sm | md | lg | md | Tamanho do texto dos itens |
| radius / animation | none | sm | md | lg | full / none | smooth | fast | bounce | lg / fast | Arredondamento e velocidade da transição de entrada |
| MenuItem | onSelect, icon, destructive, disabled | nenhum | Item; `onSelect` roda no clique/teclado e o menu fecha, a menos que seja impedido |
Acessibilidade
- A lista é `role="menu"` nomeada por `label`; cada `MenuItem` é um `button` com `role="menuitem"`.
- O gatilho recebe `aria-haspopup="menu"`, `aria-expanded` e, enquanto aberto, `aria-controls`.
- Ao abrir, o foco vai para o primeiro item habilitado; itens desabilitados são pulados pelas setas.
- A navegação por setas é circular, e digitar letras em até 500ms salta para o próximo item cujo texto começa com elas.
- Selecionar um item fecha o menu e devolve o foco ao gatilho, a menos que `onSelect` chame `event.preventDefault()`.
- `MenuSeparator` é `role="separator"`, `MenuLabel` é `role="presentation"` e os ícones dos itens são `aria-hidden`.
Teclado
| Tecla | Ação |
|---|---|
| ArrowDown | No gatilho fechado, abre o menu; dentro, vai ao próximo item |
| ArrowUp | Vai ao item anterior |
| Home / End | Vai ao primeiro / último item |
| A-Z | Busca por digitação: salta ao item cujo texto começa com as letras digitadas |
| Enter / Space | Ativa o item focado |
| Esc | Fecha o menu e foca o gatilho |
| Tab | Fecha o menu e deixa o foco seguir |
Tenha em mente
- Os itens devem ser ações simples; não é uma barra de menu e não há itens marcáveis (`menuitemcheckbox`/`menuitemradio`) nem submenus.
- Passe `label` para o menu ter nome acessível; o gatilho precisa de texto visível ou do próprio `aria-label`.