Pular para o conteúdo
// visualizar em
salvo em todas as páginas

DataTable

Tabela de dados montada a partir dos dados e das colunas, com ordenação, seleção de linhas, páginas e estado de carregamento prontos. Para uma tabela fixa escrita à mão, use Table.

Feito com TanStack TablePadrão WAI-ARIA tableComponente clienteCódigo ↗
minimal · light · #3fa34d
#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00
0 de 3 selecionados
selectable
loading

Instalação

Configure o Camaleo uma vez (Instalação) e importe a tabela e o tipo das colunas. Ela roda no cliente.

import { DataTable, type ColumnDef } from "@camaleo/react";

Anatomia

Uma <table> nativa dentro de uma caixa que rola para o lado quando a tabela não cabe, com um rodapé para o status e as páginas. O rodapé só aparece quando a tabela tem seleção ou mais de uma página.

Exemplos

Todo exemplo é um arquivo de verdade que você pode copiar. Todos usam o estilo, o modo e a marca escolhidos na barra acima.

minimal · light · #3fa34d
#4821Padaria EstrelaPagoR$ 1.240,00
#4820Vila Nova DesignPendenteR$ 840,50
#4819Aurora BioTechPagoR$ 3.120,00
Pedido
#4819Aurora BioTech19/10/2026R$ 3.120,00
#4821Padaria Estrela24/10/2026R$ 1.240,00
#4820Vila Nova Design22/10/2026R$ 840,50
#4818Café Serra Azul15/10/2026R$ 420,00

Ordenação

Clique num cabeçalho para ordenar. Números começam pelo maior, texto começa pelo A, e o terceiro clique volta à ordem original. Desligue a ordenação com enableSorting: false onde a ordem não diz nada, como num código.

#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00
1 de 3 selecionados

Seleção de linhas

Use selectable quando a pessoa age sobre várias linhas de uma vez. Dê a cada caixa o nome da linha com selectRowLabel, para o leitor de tela dizer qual pedido ela seleciona, e não "Select row 2".

#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00

Páginas

Quando as linhas passam de uma tela, defina pageSize. Diga quais linhas estão aparecendo em selectionStatus e traduza os botões de página com previousLabel, nextLabel e pageLabel.

#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00

Carregando

Clique em Atualizar. loading troca as linhas por skeletons, mas skeletons não dizem nada ao leitor de tela, então uma mensagem de status avisa quando o carregamento começa e termina.

Nenhum pedido ainda

Os pedidos aparecem aqui assim que um cliente paga no checkout.

Ainda sem linhas

Passe um EmptyState em emptyState. Os cabeçalhos continuam, então a pessoa vê o que a tabela vai mostrar, e a mensagem dá o próximo passo.

Nome do cliente ou número do pedido.

#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00
#4818Café Serra AzulR$ 420,00
#4817Livraria Ponto FinalR$ 2.890,00

Busca

Digite o nome de um cliente. A tabela filtra o que você passa em data, uma linha de status anuncia quantos pedidos batem, e Limpar busca devolve o foco ao campo.

Ações
#4821Padaria EstrelaR$ 1.240,00
#4820Vila Nova DesignR$ 840,50
#4819Aurora BioTechR$ 3.120,00

Ações na linha

Botões só com ícone ganham um nome com a linha, como "Baixar nota fiscal do pedido #4821", porque "Baixar" sozinho é igual em toda linha. O cabeçalho da coluna continua para o leitor de tela com VisuallyHidden.

Em contexto

Uma tabela de dados costuma ser a peça principal de uma página de administração, com ações acima dela. Estes são pedaços inteiros de interface que você pode copiar, no estilo que escolheu.

Pedidos para enviar

#4821Padaria EstrelaPagoR$ 1.240,00
#4820Vila Nova DesignPagoR$ 840,50
#4819Aurora BioTechEnviadoR$ 3.120,00
#4818Café Serra AzulPagoR$ 420,00
0 de 4 selecionados
Pedidos para enviarDataTable · Button · Badge
Aline PradoArquiteta de front-endAtiva
Tiago CostaEngenheiro de DevOpsAtiva
Helena LimaGerente de produtoConvidada
Marcos SilvaAnalista de segurançaSuspensa
1 membro selecionado
Membros da equipeDataTable · Avatar · Badge
Descrição
24/10/2026Mensalidade, Vila Nova DesignReceita+R$ 4.800,00
22/10/2026Hospedagem em nuvemInfraestrutura-R$ 920,40
20/10/2026Licenças de ferramentas de designSoftware-R$ 145,00
18/10/2026Etapa 2, Aurora BioTechReceita+R$ 2.200,00
Movimentação da contaDataTable · Badge

Boas práticas

ProdutoReceita
Plano anualR$ 142.850,00
Plano mensalR$ 38.400,50
Armazenamento extraR$ 2.190,00
FaçaAlinhe números à direita.

Use meta: { align: "end" } nas colunas de números. Os algarismos ficam com a mesma largura, então o maior valor se destaca.

ProdutoReceita
Plano anualR$ 142.850,00
Plano mensalR$ 38.400,50
Armazenamento extraR$ 2.190,00
EviteNúmeros alinhados à esquerda.

Milhares e centenas começam no mesmo lugar, e a pessoa precisa ler cada valor para comparar.

E-mailTelefone
Padaria Estrelacompras@estrela.com.br(11) 3456-7821
Café Serra Azulpedidos@serraazul.com.br(31) 2233-4410
FaçaOrdene só as colunas que as pessoas ordenam.

Aqui só o nome ordena. Menos botões no cabeçalho são menos paradas de Tab antes dos dados.

Padaria Estrelacompras@estrela.com.br(11) 3456-7821
Café Serra Azulpedidos@serraazul.com.br(31) 2233-4410
EviteUm botão de ordenar em toda coluna.

Toda coluna com accessor ordena por padrão. Ninguém ordena por telefone, e cada botão a mais é mais uma parada para quem usa teclado.

Props

PropriedadeTipoPadrãoDescrição
data*TData[]—Os registros, um por linha.
columns*ColumnDef<TData, any>[]—As colunas, no formato do TanStack Table. Colunas com accessor ordenam, a não ser que tenham enableSorting: false; meta: { align: "end" } alinha números à direita.
captionstring"Data table"Dá nome à tabela (aria-label) e, quando ela não cabe, à área de rolagem. Diga o que são as linhas.
getRowId((originalRow: TData, index: number) => string)—Devolve um id estável para cada linha. A seleção usa esse id; sem ele, as linhas são identificadas pela posição.
selectablebooleanfalseMostra uma caixa de seleção em cada linha e uma no cabeçalho para selecionar todas.
rowSelectionRowSelectionState—Linhas selecionadas, controladas por você: um objeto { [id]: true }.
defaultRowSelectionRowSelectionState{}Linhas selecionadas no começo, quando a tabela controla a seleção.
onRowSelectionChangeOnChangeFn<RowSelectionState>—Chamada quando a seleção muda.
sortingSortingState—Ordenação controlada por você: uma lista de { id, desc }.
defaultSortingSortingState[]Ordenação inicial, quando a tabela controla a ordem.
onSortingChangeOnChangeFn<SortingState>—Chamada quando a ordenação muda.
pageSizenumber—Linhas por página. Sem ele, todas as linhas aparecem numa página só.
pageCountnumber—Total de páginas, para paginação no servidor.
pagenumber—Página atual controlada por você, começando em 1. Sem ela, a tabela guarda a página sozinha.
onPageChange((page: number) => void)—Chamada com a nova página quando a pessoa troca de página.
loadingbooleanfalseTroca as linhas por skeletons enquanto os dados carregam.
loadingRowsnumber4Quantas linhas de skeleton mostrar.
emptyStateReactNode"No records found."O que mostrar quando não há linhas e nada está carregando.
selectAllLabelstring"Select all rows"Nome acessível da caixa de seleção do cabeçalho.
selectRowLabel((row: TData, index: number) => string)"Select row {n}"Nome acessível da caixa de cada linha. Inclua algo que identifique a linha. O índice conta a partir da primeira linha da página atual.
selectionStatus((selectedCount: number, totalCount: number) => ReactNode)"{selected} of {total} selected"Texto do status no rodapé, a partir das contagens de selecionadas e do total. Aparece sempre que o rodapé aparece, inclusive numa tabela paginada sem selectable.
totalRowsnumber—Total de registros, para o status quando a paginação é no servidor.
paginationLabelstring"Table pagination"Nome acessível da navegação de páginas.
previousLabelReactNode"Previous"Texto ou ícone do botão de página anterior.
nextLabelReactNode"Next"Texto ou ícone do botão de próxima página.
pageLabel((page: number) => string)"Page {n}"Nome acessível de cada botão de página.

Ela também aceita os atributos de uma <div>, como aria-busy e style. As colunas são ColumnDefs do TanStack: accessorKey ou accessorFn, header, cell, enableSorting e meta.align.

Styling hooks

Mude o visual sem copiar o componente: use os atributos ou defina os tokens num elemento pai, num estilo ou na própria tabela.

Atributos

data-alignstart · end, nos cabeçalhos e células
data-sortedasc · desc, no botão de ordenar
data-selectednuma linha selecionada
data-selection-cellno cabeçalho e nas células das caixas de seleção
data-loadingnas linhas de skeleton
data-emptyna linha vazia (data-empty-cell na célula)

Tokens que ele lê

Cor

--cml-accent--cml-accent-text--cml-border--cml-border-control--cml-card-border--cml-card-shadow--cml-fg--cml-fg-secondary--cml-focus-offset--cml-focus-ring--cml-focus-width--cml-surface-raised--cml-table-head-fg--cml-table-row-selected-fg

Forma e tamanho

--cml-border-width--cml-radius-control-sm--cml-radius-popover

Tipografia e movimento

--cml-font-label

Só deste componente

--cml-corner-shape--cml-table-head-tracking--cml-table-head-transform

Acessibilidade

TabPassa pelos botões de ordenar, pelas caixas de seleção, pelos controles nas células e pelos botões de página. Quando a tabela não cabe, a área de rolagem é uma parada a mais.
Enter / EspaçoNum botão de ordenar, ordena por aquela coluna, depois inverte, depois volta ao original. Num botão de página, vai para aquela página.
EspaçoMarca ou desmarca a caixa da linha com foco, ou todas as linhas pela caixa do cabeçalho.
← / →Rolam a tabela larga para o lado enquanto a área de rolagem está com o foco.

Relacionados

Esta página foi útil? · Editar esta página no GitHub