Menu do botão direito
O menu de ações que aparece onde a pessoa clicou. É o mesmo menu suspenso —
mesma marcação, mesmos itens, mesmo teclado —, só que aberto pelo botão direito e ancorado no ponto do clique.
Numa lista, os itens costumam mudar conforme a linha: por isso items também aceita uma função.
Clique com o botão direito numa linha. Pelo teclado, chegue de Tab e aperte a tecla de menu ou Shift+F10.
| Cliente | Vencimento | Valor |
|---|---|---|
| Padaria Pão Quente | 12/09/2026 | 12400 |
| Oficina Duas Rodas | 03/07/2026 | 3890.5 |
| Marcenaria Horizonte | 28/11/2026 | 760 |
Como usar
A área é quem escuta o botão direito; match diz qual pedaço dela é o alvo. O alvo vai para
items, e é dele que saem as ações daquela linha.
new Tucano.ContextMenu('#contratos', {
match: 'tbody tr',
items: (row) => [
{ label: row.dataset.name },
{ text: 'Editar', shortcut: '⌘E', onClick: () => editar(row.dataset.id) },
{ text: 'Duplicar', onClick: () => duplicar(row.dataset.id) },
{ separator: true },
{ text: 'Excluir', variant: 'danger', onClick: () => excluir(row.dataset.id) },
],
});Sem match, o alvo é a área inteira — o caminho para um cartão ou um painel com um menu só. Fora de um
alvo, o menu do navegador continua aparecendo: um menu de ações que não sabe sobre o que age é pior que nenhum.
O menu do navegador continua a um Shift de distância
Shift + botão direito mostra o menu do próprio navegador, em qualquer lugar da área. Quem precisa de "abrir em nova aba", do corretor ortográfico ou de inspecionar a página não fica sem — e não há como tirar isso de alguém.
Exemplos
Área inteira, sem match
Um cartão com as mesmas ações em qualquer ponto dele.
Contrato 4821
Clique com o botão direito em qualquer lugar deste cartão.
Menu escrito no template
Quando é o servidor quem sabe o que a pessoa pode fazer, como no menu suspenso.
Nota fiscal 118
Botão direito aqui abre o menu do template.
<table id="contratos" data-tuc-contextmenu="#acoes-linha" data-match="tbody tr">
{% for obj in page_obj %}
<tr tabindex="0" data-id="{{ obj.pk }}">…</tr>
{% endfor %}
</table>
<div class="tuc-dropdown" id="acoes-linha" hidden>
<button type="button" class="tuc-dropdown__item">
<span class="tuc-dropdown__text">Editar</span>
</button>
</div>Com o painel do template, os itens são os mesmos para toda linha: quem precisa saber qual foi clicada lê
menu.target dentro do onclick, ou usa items como função.
Teclado e acessibilidade
O painel é o mesmo do menu suspenso: role="menu", itens como menuitem, foco
dentro do menu e devolvido a quem o tinha antes. Aberto pelo botão direito, nenhum item nasce destacado — como no
menu do sistema, a primeira seta é que destaca o primeiro. Aberto pelo teclado, o primeiro item já vem destacado,
porque quem apertou a tecla de menu já quer andar pelos itens.
| Tecla | Onde | Ação |
|---|---|---|
Tecla de menu, Shift+F10 | Alvo com foco | Abre o menu ancorado no alvo |
↑ ↓ | Menu aberto | Anda pelos itens, dando a volta |
Home End | Menu aberto | Primeiro e último item |
Enter Espaço | Item | Escolhe e fecha |
Esc | Menu aberto | Fecha e devolve o foco |
Shift + botão direito | Área | Deixa passar o menu do navegador |
O alvo precisa receber foco
A tecla de menu e o Shift+F10 abrem a partir de quem tem o foco. Numa tabela, ponha tabindex="0" nas linhas — sem isso, o que só existe no menu do botão direito fica inalcançável para quem não usa mouse. No celular, o toque longo abre o menu no Android; no iPhone, o Safari não avisa a página, então nenhuma ação pode existir só aqui.
API
Gerada do código a cada build — se algo não está aqui, não existe.
[data-tuc-contextmenu]new Tucano.ContextMenu(alvo, opcoes)data-match data-placement data-tuc-contextmenuopenAt closeOpções
| Opção | Padrão | Para quê |
|---|---|---|
placement | 'bottom-start' | |
items | null | array como o do Dropdown, ou (alvo) => array |
match | null | seletor do alvo dentro da area; sem ele, a area inteira |
closeOnPick | true | |
onOpen | null | (alvo, instancia) — para marcar a linha clicada, por exemplo |
panel | null | painel ja escrito no template, no lugar de `items` |