Menu
Superfície de menu dropdown (`mk-menu`, `mk-menu-item`, `mk-menu-group`, `mk-menu-header`, `mk-menu-divider`, `mk-menu-trigger`) ancorada a um gatilho externo por id.
O mk-menu é a superfície de menu dropdown do Makuco. Ele se ancora a um gatilho externo pelo id (prop anchor) — o gatilho pode ser qualquer elemento (mk-menu-trigger, mk-button, mk-icon-button ou um <button> nativo). O menu injeta aria-haspopup, aria-expanded e aria-controls no gatilho e anexa os listeners, sem envolvê-lo em um wrapper. Compõe-se de mk-menu (painel), mk-menu-item (item com título e descrição), mk-menu-header (caption de seção), mk-menu-divider (separador) e mk-menu-trigger (pill de conveniência).
Padrão
O mk-menu-trigger recebe um id e o mk-menu aponta para ele via anchor.
import { MkMenu, MkMenuItem, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-default" label="Menu item" />
<MkMenu anchor="menu-default" onMkSelect={(e) => console.log(e.detail.value)}>
<MkMenuItem value="overview" label="Overview" description="Start here for a quick tour" />
<MkMenuItem value="features" label="Features" description="See everything we offer" />
<MkMenuItem value="changelog" label="Changelog" description="Latest updates and releases" />
</MkMenu><mk-menu-trigger id="menu-default" label="Menu item"></mk-menu-trigger>
<mk-menu anchor="menu-default" (mkSelect)="onSelect($event)">
<mk-menu-item value="overview" label="Overview" description="Start here for a quick tour"></mk-menu-item>
<mk-menu-item value="features" label="Features" description="See everything we offer"></mk-menu-item>
<mk-menu-item value="changelog" label="Changelog" description="Latest updates and releases"></mk-menu-item>
</mk-menu>Gatilho customizado
A customização é realmente necessária?
Utilize somente com gatilhos customizados quando não for possível usar mk-menu-trigger. O mk-menu-trigger já implementa o comportamento de acessibilidade e foco esperado, além de fornecer um pill estilizado pronto para uso.
Qualquer elemento com um id pode ser o gatilho. O menu não precisa de mk-menu-trigger — um mk-button, um <button> nativo ou qualquer outro elemento funcionam igualmente, pois o mk-menu injeta aria-haspopup, aria-expanded, aria-controls e os listeners diretamente nele.
import { MkMenu, MkMenuItem, MkButton } from '@db1/makuco-ui-react';
<MkButton id="menu-actions" variant="outlined">Ações</MkButton>
<MkMenu anchor="menu-actions">
<MkMenuItem value="edit" label="Editar" />
<MkMenuItem value="copy" label="Copiar" />
</MkMenu><mk-button id="menu-actions" variant="outlined">Ações</mk-button>
<mk-menu anchor="menu-actions">
<mk-menu-item value="edit" label="Editar"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar"></mk-menu-item>
</mk-menu>Também funciona com um <button> HTML puro, sem nenhum componente Makuco:
import { MkMenu, MkMenuItem } from '@db1/makuco-ui-react';
<button id="menu-native">Ações</button>
<MkMenu anchor="menu-native">
<MkMenuItem value="edit" label="Editar" />
<MkMenuItem value="copy" label="Copiar" />
</MkMenu><button id="menu-native">Ações</button>
<mk-menu anchor="menu-native">
<mk-menu-item value="edit" label="Editar"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar"></mk-menu-item>
</mk-menu>Ícones e descrição
Use icon para um ícone leading e description para um texto secundário abaixo do título.
import { MkMenu, MkMenuItem, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-icons" label="Ações" />
<MkMenu anchor="menu-icons">
<MkMenuItem value="edit" icon="pencil" label="Editar" description="Altere o conteúdo" />
<MkMenuItem value="copy" icon="copy" label="Copiar" description="Duplique o item" />
<MkMenuItem value="share" icon="share-2" label="Compartilhar" description="Envie um link" />
</MkMenu><mk-menu-trigger id="menu-icons" label="Ações"></mk-menu-trigger>
<mk-menu anchor="menu-icons">
<mk-menu-item
value="edit"
icon="pencil"
label="Editar"
description="Altere o conteúdo"
></mk-menu-item>
<mk-menu-item
value="copy"
icon="copy"
label="Copiar"
description="Duplique o item"
></mk-menu-item>
<mk-menu-item
value="share"
icon="share-2"
label="Compartilhar"
description="Envie um link"
></mk-menu-item>
</mk-menu>Cabeçalho e separador
Use mk-menu-header para rotular uma seção (caption + divisor sutil abaixo) e mk-menu-divider para um separador autônomo entre grupos.
import { MkMenu, MkMenuItem, MkMenuHeader, MkMenuDivider, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-header" label="Navegação" />
<MkMenu anchor="menu-header">
<MkMenuHeader label="Navigation" />
<MkMenuItem value="overview" label="Overview" description="Start here for a quick tour" />
<MkMenuItem value="features" label="Features" description="See everything we offer" />
<MkMenuDivider />
<MkMenuItem value="changelog" label="Changelog" description="Latest updates and releases" />
</MkMenu><mk-menu-trigger id="menu-header" label="Navegação"></mk-menu-trigger>
<mk-menu anchor="menu-header">
<mk-menu-header label="Navigation"></mk-menu-header>
<mk-menu-item value="overview" label="Overview" description="Start here for a quick tour"></mk-menu-item>
<mk-menu-item value="features" label="Features" description="See everything we offer"></mk-menu-item>
<mk-menu-divider></mk-menu-divider>
<mk-menu-item value="changelog" label="Changelog" description="Latest updates and releases"></mk-menu-item>
</mk-menu>Agrupamento
mk-menu-group agrupa itens num role="group" com nome acessível (label). É só semântica: não há rótulo visível, divisor nem mudança de layout, e os itens do grupo continuam na navegação por teclado do menu. Use para nomear um conjunto de itens; para um título visível entre seções, use mk-menu-header.
<MkMenu anchor="menu-grouped">
<MkMenuItem value="open" label="Abrir" />
<MkMenuGroup label="Exportar">
<MkMenuItem value="pdf" label="PDF" />
<MkMenuItem value="csv" label="CSV" />
</MkMenuGroup>
</MkMenu><mk-menu anchor="menu-grouped">
<mk-menu-item value="open" label="Abrir"></mk-menu-item>
<mk-menu-group label="Exportar">
<mk-menu-item value="pdf" label="PDF"></mk-menu-item>
<mk-menu-item value="csv" label="CSV"></mk-menu-item>
</mk-menu-group>
</mk-menu>Seleção
selectionMode no mk-menu define como os itens marcam uma escolha: "none" (padrão) mantém o comportamento de ação; "single" faz dos itens opções excludentes (menuitemradio); "multiple" faz deles opções independentes (menuitemcheckbox). O menu repassa o modo aos itens, e o item marcado mostra um tique à direita, no lugar do chevron, com a largura sempre reservada, de modo que o texto não se desloca.
O estado marcado é a prop selected do item e fica com quem usa o menu: alterne selected no evento mkSelect. O menu não marca nem desmarca sozinho. Com selectionMode="multiple" o menu não fecha ao selecionar, independentemente de closeOnSelect, e o foco permanece no item ativado. Em single e none, closeOnSelect vale como sempre. Itens com triggerFor (submenu) não participam da seleção.
Envolva as opções em mk-menu-group com label: o padrão ARIA pede que os itens menuitemradio fiquem num grupo com nome.
const [visible, setVisible] = useState(['name', 'role']);
const toggle = (value: string) =>
setVisible((current) =>
current.includes(value) ? current.filter((v) => v !== value) : [...current, value]);
<MkMenuTrigger id="menu-columns" label="Colunas" />
<MkMenu anchor="menu-columns" selectionMode="multiple" onMkSelect={(e) => toggle(e.detail.value)}>
<MkMenuGroup label="Colunas visíveis">
<MkMenuItem value="name" label="Nome" selected={visible.includes('name')} />
<MkMenuItem value="role" label="Cargo" selected={visible.includes('role')} />
<MkMenuItem value="status" label="Status" selected={visible.includes('status')} />
</MkMenuGroup>
</MkMenu><mk-menu-trigger id="menu-columns" label="Colunas"></mk-menu-trigger>
<mk-menu anchor="menu-columns" selectionMode="multiple" (mkSelect)="toggle($event.detail.value)">
<mk-menu-group label="Colunas visíveis">
<mk-menu-item value="name" label="Nome" [selected]="visible.includes('name')"></mk-menu-item>
<mk-menu-item value="role" label="Cargo" [selected]="visible.includes('role')"></mk-menu-item>
<mk-menu-item value="status" label="Status" [selected]="visible.includes('status')"></mk-menu-item>
</mk-menu-group>
</mk-menu>Tamanhos
O painel tem três larguras: sm (200px), md (280px, padrão) e lg (360px).
import { MkMenu, MkMenuItem, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-sm" label="sm" />
<MkMenu anchor="menu-sm" size="sm">
<MkMenuItem value="edit" label="Editar" />
<MkMenuItem value="copy" label="Copiar" />
</MkMenu>
<MkMenuTrigger id="menu-md" label="md" />
<MkMenu anchor="menu-md" size="md">
<MkMenuItem value="edit" label="Editar" />
<MkMenuItem value="copy" label="Copiar" />
</MkMenu>
<MkMenuTrigger id="menu-lg" label="lg" />
<MkMenu anchor="menu-lg" size="lg">
<MkMenuItem value="edit" label="Editar" />
<MkMenuItem value="copy" label="Copiar" />
</MkMenu><mk-menu-trigger id="menu-sm" label="sm"></mk-menu-trigger>
<mk-menu anchor="menu-sm" size="sm">
<mk-menu-item value="edit" label="Editar"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar"></mk-menu-item>
</mk-menu>
<mk-menu-trigger id="menu-md" label="md"></mk-menu-trigger>
<mk-menu anchor="menu-md" size="md">
<mk-menu-item value="edit" label="Editar"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar"></mk-menu-item>
</mk-menu>
<mk-menu-trigger id="menu-lg" label="lg"></mk-menu-trigger>
<mk-menu anchor="menu-lg" size="lg">
<mk-menu-item value="edit" label="Editar"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar"></mk-menu-item>
</mk-menu>Intenção do item
kind aceita default, error, success, warning, info e brand. Use error para ações destrutivas/irreversíveis. O valor danger é um alias de error mantido por compatibilidade e será removido em uma versão futura.
import { MkMenu, MkMenuItem, MkMenuDivider, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-kinds" label="Mais opções" />
<MkMenu anchor="menu-kinds">
<MkMenuItem value="edit" icon="pencil" label="Editar" />
<MkMenuItem value="approve" icon="circle-check" label="Aprovar" kind="success" />
<MkMenuItem value="review" icon="triangle-alert" label="Revisar" kind="warning" />
<MkMenuItem value="details" icon="info" label="Ver detalhes" kind="info" />
<MkMenuItem value="upgrade" icon="sparkles" label="Fazer upgrade" kind="brand" />
<MkMenuDivider />
<MkMenuItem value="delete" icon="trash-2" kind="error" label="Excluir permanentemente" />
</MkMenu><mk-menu-trigger id="menu-kinds" label="Mais opções"></mk-menu-trigger>
<mk-menu anchor="menu-kinds">
<mk-menu-item value="edit" icon="pencil" label="Editar"></mk-menu-item>
<mk-menu-item value="approve" icon="circle-check" label="Aprovar" kind="success"></mk-menu-item>
<mk-menu-item value="review" icon="triangle-alert" label="Revisar" kind="warning"></mk-menu-item>
<mk-menu-item value="details" icon="info" label="Ver detalhes" kind="info"></mk-menu-item>
<mk-menu-item value="upgrade" icon="sparkles" label="Fazer upgrade" kind="brand"></mk-menu-item>
<mk-menu-divider></mk-menu-divider>
<mk-menu-item
value="delete"
icon="trash-2"
kind="error"
label="Excluir permanentemente"
></mk-menu-item>
</mk-menu>Abertura por hover
Defina open-on="hover" para abrir ao passar o mouse. Há uma ponte de intenção entre gatilho e painel para evitar fechamentos acidentais; em dispositivos sem hover a interação degrada para clique, e o teclado sempre abre o menu.
import { MkMenu, MkMenuItem, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-hover" label="Passe o mouse" />
<MkMenu anchor="menu-hover" openOn="hover">
<MkMenuItem value="edit" label="Editar" description="Altere o conteúdo" />
<MkMenuItem value="copy" label="Copiar" description="Duplique o item" />
</MkMenu><mk-menu-trigger id="menu-hover" label="Passe o mouse"></mk-menu-trigger>
<mk-menu anchor="menu-hover" open-on="hover">
<mk-menu-item value="edit" label="Editar" description="Altere o conteúdo"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar" description="Duplique o item"></mk-menu-item>
</mk-menu>Submenu
Aponte um mk-menu-item para outro mk-menu com trigger-for (id). O item exibe um chevron à direita e abre o submenu ao ser ativado ou com ArrowRight.
import { MkMenu, MkMenuItem, MkMenuDivider, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-sub" label="Ações" />
<MkMenu anchor="menu-sub">
<MkMenuItem value="edit" label="Editar" icon="pencil" />
<MkMenuItem value="copy" label="Copiar" icon="copy" />
<MkMenuItem label="Mover para" icon="folder-open" triggerFor="submenu-move" />
<MkMenuDivider />
<MkMenuItem value="delete" label="Excluir" icon="trash-2" kind="error" />
</MkMenu>
<MkMenu id="submenu-move" size="sm" placement="right">
<MkMenuItem value="folder-a" label="Pasta A" icon="folder" />
<MkMenuItem value="folder-b" label="Pasta B" icon="folder" />
</MkMenu><mk-menu-trigger id="menu-sub" label="Ações"></mk-menu-trigger>
<mk-menu anchor="menu-sub">
<mk-menu-item value="edit" label="Editar" icon="pencil"></mk-menu-item>
<mk-menu-item value="copy" label="Copiar" icon="copy"></mk-menu-item>
<mk-menu-item label="Mover para" icon="folder-open" trigger-for="submenu-move"></mk-menu-item>
<mk-menu-divider></mk-menu-divider>
<mk-menu-item value="delete" label="Excluir" icon="trash-2" kind="error"></mk-menu-item>
</mk-menu>
<mk-menu id="submenu-move" size="sm" placement="right">
<mk-menu-item value="folder-a" label="Pasta A" icon="folder"></mk-menu-item>
<mk-menu-item value="folder-b" label="Pasta B" icon="folder"></mk-menu-item>
</mk-menu>Como link
Defina href em mk-menu-item para renderizar como <a>.
import { MkMenu, MkMenuItem, MkMenuTrigger } from '@db1/makuco-ui-react';
<MkMenuTrigger id="menu-link" label="Navegar" />
<MkMenu anchor="menu-link">
<MkMenuItem value="home" icon="house" label="Início" href="#home" />
<MkMenuItem value="docs" icon="book-open" label="Documentação" href="/docs" />
<MkMenuItem value="settings" icon="settings" label="Configurações" href="#settings" />
</MkMenu><mk-menu-trigger id="menu-link" label="Navegar"></mk-menu-trigger>
<mk-menu anchor="menu-link">
<mk-menu-item value="home" icon="house" label="Início" href="#home"></mk-menu-item>
<mk-menu-item value="docs" icon="book-open" label="Documentação" href="/docs"></mk-menu-item>
<mk-menu-item value="settings" icon="settings" label="Configurações" href="#settings"></mk-menu-item>
</mk-menu>Props — mk-menu
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
anchor | string | — | Id do elemento gatilho. Resolvido via |
open | boolean | false | Controla a visibilidade. Refletido como atributo; ativa o modo controlado. |
openOn | "click" | "hover" | "click" | Gatilho de abertura. Em hover, degrada para clique em telas sem hover. |
size | "sm" | "md" | "lg" | "md" | Largura do painel: 200 / 280 / 360 px. |
placement | "bottom-start" | "bottom-end" | "top-start" | "top-end" | "left" | "right" | "bottom-start" | Posicionamento do painel em relação ao gatilho. |
selectionMode | "none" | "single" | "multiple" | "none" | Modo de seleção dos itens. "single" e "multiple" fazem dos itens menuitemradio e menuitemcheckbox, com tique à direita no item selected. Com "multiple" o menu não fecha ao selecionar. |
closeOnSelect | boolean | true | Fecha o menu ao selecionar um item. |
disabled | boolean | false | Impede a abertura do menu. |
Props — mk-menu-item
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
value | string | — | Valor emitido em mkClick e no mkSelect do menu pai. |
label | string | — | Título do item. Alternativa ao slot padrão. |
description | string | — | Texto secundário exibido abaixo do título. |
icon | IconName | — | Ícone leading. |
kind | "default" | "error" | "success" | "warning" | "info" | "brand" | "danger" | "default" | Intenção visual. Use |
href | string | — | Quando preenchido, renderiza o item como <a>. |
selected | boolean | false | Marca o item como selecionado visualmente. Fora de um mk-menu com selectionMode, vira aria-current="true"; dentro de um, é o estado marcado (aria-checked, com tique à direita), controlado por quem usa o menu. |
disabled | boolean | false | Desabilita o item. |
triggerFor | string | — | Id de um mk-menu aberto como submenu. Exibe um chevron à direita. |
Props — mk-menu-trigger
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
label | string | — | Texto do gatilho. Alternativa ao slot padrão. |
selected | boolean | false | Refletido pelo mk-menu quando aberto — gira o chevron. |
disabled | boolean | false | Desabilita o gatilho, impedindo a abertura. |
Props — mk-menu-group
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
label | string | — | Nome acessível do grupo (aria-label). Recomendado: sem ele o grupo é anunciado sem nome. |
Props — mk-menu-header
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
label | string | — | Rótulo da seção (caption). Alternativa ao slot padrão. |
Eventos
| Evento | Componente | Payload | Descrição |
|---|---|---|---|
mkOpen | mk-menu | void | Emitido quando o menu abre. |
mkClose | mk-menu | void | Emitido quando o menu fecha. |
mkSelect | mk-menu | { value: string } | Emitido quando um item é selecionado. |
mkClick | mk-menu-item | { value: string } | Emitido quando o item é ativado diretamente. |
Slots
| Componente | Slot | Descrição |
|---|---|---|
mk-menu | (default) | Itens do menu: mk-menu-item, mk-menu-group, mk-menu-header, mk-menu-divider. |
mk-menu-group | (default) | Itens (mk-menu-item) do grupo. |
mk-menu-item | (default) | Conteúdo do título quando label não é fornecido. |
mk-menu-header | (default) | Conteúdo do rótulo quando label não é fornecido. |
mk-menu-trigger | (default) | Conteúdo do gatilho quando label não é fornecido. |
Acessibilidade
- O painel tem
role="menu"; cada item temrole="menuitem"earia-disabledquando desabilitado. mk-menu-dividerusarole="separator".mk-menu-groupusarole="group", com o nome vindo delabel(aria-label).- Com
selectionModesingleoumultiple, os itens usamrole="menuitemradio"ou"menuitemcheckbox"comaria-checked; fora da seleção, o item comselectedusaaria-current="true". O tique é decorativo (aria-hidden), e o estado marcado é anunciado poraria-checked. - O gatilho recebe
aria-haspopup="menu",aria-controlsearia-expandedautomaticamente, sincronizados com o estado aberto. - O foco real fica no item atual; ao fechar, retorna ao gatilho.
- Com o foco no gatilho e o menu aberto, setas,
Home,End,EscapeeTabseguem a navegação do menu. - O teclado sempre abre o menu, mesmo com
open-on="hover".
| Tecla | Comportamento |
|---|---|
Enter / Space | No gatilho, abre o menu e leva o foco ao primeiro item. No item em foco, ativa o item. |
ArrowDown / ArrowUp | Navega entre os itens habilitados. No gatilho com o menu fechado, ArrowDown abre no primeiro item e ArrowUp no último. |
ArrowRight | Abre o submenu do item em foco (quando há trigger-for). |
Home / End | Move o foco para o primeiro/último item. |
Escape | Fecha o menu e devolve o foco ao gatilho. |
Tab | Fecha o menu e segue o fluxo de foco normal. |
| Caractere | Typeahead: move o foco para o próximo item cujo título começa com o caractere digitado. |