Tema
BaseRowActions
As ações de uma linha de tabela, numa linha só, alinhadas à direita. Com poucas ações, aparecem lado a lado; com muitas, a primeira fica à vista e o resto vai para o menu "Mais ações".
Última ação: Nenhuma ação escolhida ainda.
Uso
- Use na última coluna de uma tabela, para as ações que valem para aquela linha: ver, lançar reforço, excluir.
- As ações ficam numa linha só, sem quebrar, alinhadas à direita. Cada uma é um
BaseButtonpequeno do tipoghost. - Até 3 ações ficam lado a lado.
- Com mais de 3 ações, a primeira fica à vista e as outras vão para o menu "Mais ações".
- Em janelas abaixo de 1600 px, duas ou mais ações com texto já não cabem ao lado dos dados: a primeira fica à vista e o resto vai para o menu. Ação só com ícone (
iconOnly) não conta como texto. - Ponha primeiro a ação que a pessoa mais usa, porque é a que sempre fica à vista.
- Dê a cada ação um
ariaLabelque cite o registro ("Lançar reforço na NE 2026NE000123"), para a lista de botões da página não repetir "Reforço" em todas as linhas. E passelabelcom o registro, para o botão do menu ter nome único. - Para uma ação só com ícone, o
ariaLabel(ou olabel) vira a dica do mouse e o nome para o leitor de tela. Use só com ícone que todo mundo reconhece, como a lixeira. - O componente é só a linha de ações. Dentro do
BaseDataTable, ponha no slotactions.
Anatomia
- Ações à vista: botões
ghostpequenos, com ícone opcional antes do texto. - Botão "Mais ações": três pontos, só aparece quando alguma ação foi para o menu.
- Menu: painel com as ações que não coube, aberto abaixo do botão e alinhado ao fim dele.
Dentro da tabela
vue
<BaseDataTable :columns="columns" :rows="rows" row-key="code" label="Contratos de obra">
<template #actions="{ row }">
<BaseRowActions :actions="actionsOf(row)" :label="`contrato ${row.code}`" />
</template>
</BaseDataTable>Faça e não faça
| Faça | Não faça |
|---|---|
| Ponha a ação mais usada primeiro. | Esconder no menu a ação que a pessoa usa em quase toda linha. |
Cite o registro no ariaLabel: "Excluir a NE 2026NE000123". | Repetir "Excluir" em todas as linhas. |
Use iconOnly só em ação conhecida, como a lixeira. | Pôr só ícone em todas as ações e obrigar a pessoa a adivinhar. |
| Deixe a ação destrutiva por último e peça confirmação. | Excluir direto, sem confirmar. |
Estilo
| Propriedade | Token |
|---|---|
| Botões | BaseButton com kind="ghost" e size="sm" |
| Espaço entre botões | --tj-space-1 |
| Fundo do menu | --tj-layer-01 |
| Borda do menu | --tj-border-subtle-02 (1 px) |
| Raio do menu | --tj-radius-md |
| Sombra do menu | --tj-shadow-2 |
| Espaço interno do menu | --tj-space-1 |
O menu fica fixo na janela e é desenhado no fim do <body>, para a borda da tabela não cortar. Ele fecha ao rolar a página ou mudar o tamanho da janela, porque não acompanha a linha.
Código
vue
<script setup lang="ts">
import { BaseRowActions, type RowAction } from '@lab-inovacao-tjes/design-system'
const actions: RowAction[] = [
{ label: 'Ver', icon: 'eye', ariaLabel: 'Ver a NE 2026NE000123', onSelect: () => open('2026NE000123') },
{ label: 'Reforço', icon: 'plus-circle', ariaLabel: 'Lançar reforço na NE 2026NE000123', onSelect: () => reinforce('2026NE000123') },
{ label: 'Excluir', icon: 'trash', ariaLabel: 'Excluir a NE 2026NE000123', iconOnly: true, onSelect: () => remove('2026NE000123') },
]
</script>
<template>
<BaseRowActions :actions="actions" label="NE 2026NE000123" />
</template>Propriedades
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
actions | readonly RowAction[] | obrigatória | Lista das ações da linha. Cada uma tem label, onSelect e, se quiser, icon, ariaLabel e iconOnly |
label | string | — | Registro da linha, usado no nome do botão "Mais ações de NE 2026NE000123" |
Cada item de actions (RowAction):
| Campo | Tipo | O que faz |
|---|---|---|
label | string | Texto da ação. Obrigatório. |
onSelect | () => void | Chamada quando a pessoa aciona a ação. Obrigatório. |
icon | string | Nome do ícone do Bootstrap Icons, sem bi-. |
ariaLabel | string | Nome para o leitor de tela, que cita o registro. Sem ele, vale o label. |
iconOnly | boolean | Mostra só o ícone quando a ação está à vista. No menu, o texto sempre aparece. |
Acessibilidade
- Cada ação à vista é um
<button>nativo e entra na ordem do Tab, na ordem da lista. - O botão "Mais ações" segue o padrão de botão de menu do WAI-ARIA APG: tem
aria-haspopup="menu",aria-expandede, com o menu aberto,aria-controls. O nome dele cita o registro quando hálabel: "Mais ações de NE 2026NE000123". - O menu tem
role="menu"e cada ação,role="menuitem", com o nome doariaLabel. - Ao abrir, o foco vai para a primeira ação do menu. Ao escolher uma ação ou fechar com Esc, o foco volta ao botão "Mais ações", para não cair no início da página.
- Tab fecha o menu e devolve o foco ao botão, e um clique fora também fecha.
- O menu não prende o foco: ele fecha antes que o foco saia dele.
- Testado com axe com as ações à vista, com o menu fechado e com o menu aberto.
Teclado:
| Tecla | O que faz |
|---|---|
| Tab | Passa de uma ação à vista para a outra e para o botão "Mais ações". Com o menu aberto, fecha o menu e devolve o foco ao botão. |
| Enter ou Espaço | Aciona a ação com o foco; no botão "Mais ações", abre o menu. |
| Seta para baixo | No botão "Mais ações", abre o menu. No menu, vai para a ação seguinte e, na última, volta à primeira. |
| Seta para cima | No menu, vai para a ação anterior e, na primeira, vai à última. |
| Home ou End | No menu, vai para a primeira ou para a última ação. |
| Esc | Fecha o menu e devolve o foco ao botão "Mais ações". |