Tabela de dados
Tabela de largura total com borda inferior por linha, realce apagado no hover e célula de 16 px. Só estrutura — nenhum comportamento.
usa o TAB-01
O código
tabela.css + markup.html
/* ===== tabela.css ================================================================== */
/* TAB-01 · Tabela de dados — reescrita dos primitivos do shadcn/ui.
Largura total, borda inferior por linha, última sem borda, realce apagado no hover,
célula de 16 px. Só estrutura e estilo: nenhum comportamento.
Variante de duas colunas sem cabeçalho (rótulo à esquerda, valor à direita) e a
.c-lista-linhas, que é o mesmo desenho sem <table>, para lista de itens. */
.c-tabela {
--c-tab-linha: rgba(235, 235, 235, .12);
--c-tab-tinta: #ebebeb;
--c-tab-tinta-2: #a8a8a8;
--c-tab-realce: rgba(235, 235, 235, .04);
width: 100%;
border-collapse: collapse;
caption-side: bottom;
font-size: .875rem;
}
.c-tabela tr { border-bottom: 1px solid var(--c-tab-linha); transition: background-color .2s ease; }
.c-tabela tbody tr:last-child { border-bottom: 0; }
.c-tabela tr:hover { background-color: var(--c-tab-realce); }
.c-tabela th, .c-tabela td { padding: 16px 0; vertical-align: middle; }
.c-tabela th { text-align: left; font-weight: 500; color: var(--c-tab-tinta-2); }
.c-tabela td { text-align: right; font-weight: 500; color: var(--c-tab-tinta); }
.c-tabela caption { padding-top: 12px; color: var(--c-tab-tinta-2); font-size: .8rem; text-align: left; }
/* com cabeçalho de coluna: o <thead> ganha o papel de rótulo e o <td> volta à esquerda */
.c-tabela--colunas td { text-align: left; }
.c-tabela--colunas thead tr { border-bottom: 1px solid var(--c-tab-linha); }
/* o mesmo desenho sem <table>: lista de itens em linhas finas */
.c-lista-linhas {
--c-tab-linha: rgba(235, 235, 235, .12);
--c-tab-tinta: #ebebeb;
margin: 0; padding: 0; list-style: none; font-size: .875rem;
}
.c-lista-linhas li { padding: 16px 0; border-bottom: 1px solid var(--c-tab-linha); font-weight: 500; color: var(--c-tab-tinta); }
.c-lista-linhas li:last-child { border-bottom: 0; }
/* ===== markup.html ================================================================= */
<!-- TAB-01 · Tabela de duas colunas sem cabeçalho: rótulo à esquerda, valor à direita.
É a variante que a OCTA usa; para tabela com cabeçalho, some .c-tabela--colunas e um <thead>. -->
<table class="c-tabela">
<caption>Medidas conferidas no local.</caption>
<tbody>
<tr><th scope="row">Área</th><td>30 m²</td></tr>
<tr><th scope="row">Pé-direito</th><td>4 m</td></tr>
<tr><th scope="row">Capacidade</th><td>até 8 pessoas</td></tr>
<tr><th scope="row">Piso</th><td>cimento queimado</td></tr>
</tbody>
</table>
<!-- o mesmo desenho, sem tabela -->
<ul class="c-lista-linhas">
<li>Ciclorama branco de 5 m</li>
<li>Dois softboxes com tripé</li>
<li>Rebatedor 5 em 1</li>
</ul>
01-tabela.tsx
/* ===== 01-tabela.tsx =============================================================== */
import * as React from 'react';
import { cn } from '@/lib/utils';
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className='relative w-full overflow-auto'>
<table
ref={ref}
className={cn('w-full caption-bottom text-sm', className)}
{...props}
/>
</div>
));
Table.displayName = 'Table';
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />
));
TableHeader.displayName = 'TableHeader';
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn('[&_tr:last-child]:border-0', className)}
{...props}
/>
));
TableBody.displayName = 'TableBody';
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
className
)}
{...props}
/>
));
TableFooter.displayName = 'TableFooter';
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
className
)}
{...props}
/>
));
TableRow.displayName = 'TableRow';
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
className
)}
{...props}
/>
));
TableHead.displayName = 'TableHead';
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', className)}
{...props}
/>
));
TableCell.displayName = 'TableCell';
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn('mt-4 text-sm text-muted-foreground', className)}
{...props}
/>
));
TableCaption.displayName = 'TableCaption';
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
};
Já rodou em
- trento-pedro · home v3 — seção “O espaço”: a ficha e a lista de equipamentos, dentro da GAV-01
Exige
- react
- cn (clsx + tailwind-merge)
- tokens de tema do shadcn (muted, muted-foreground, border)
Como se configura
--c-tab-linha--c-tab-tinta--c-tab-tinta-2--c-tab-realce
A ficha
O que o 21st.dev entregou
Dependências: react, cn (@/lib/utils — clsx + tailwind-merge), Tailwind com os tokens de tema do shadcn (muted, muted-foreground, border).
O que entrega: só a estrutura e o estilo base — nenhum comportamento.
- Invólucro com rolagem horizontal (
relative w-full overflow-auto). - Tabela
w-full, textotext-sm(0,875rem), legenda embaixo. - Cabeçalho:
thcomh-12(3rem),px-4, alinhado à esquerda, peso médio, cor apagada. - Linhas com borda inferior e fundo apagado no hover; a última linha do corpo sem borda.
- Célula
p-4(1rem).
Vale o código, não o exemplo do Canva (Rafa, 14/09). O que o código NÃO traz: o exemplo que o Rafa pôs ao lado no Canva (colunas Member e Role, avatar redondo, nome com e-mail embaixo, selo à direita — Admin escuro, os outros claros) é o demo do 21st.dev, montado com esses primitivos. O markup do demo não veio; o visual está só no print do Canva.
Para a Trento:
- Os tokens do shadcn viram tokens da Trento:
border→--tr-linha,muted/50→--tr-superficie,muted-foreground→--tr-tinta-2. A seção 3 fica sobre fundo claro. - O hover de linha não existe no celular.
- Falta decidir as colunas — uma, como a lista do Canva ("Área de 30 m²"), ou duas (pergunta no documento da v3).
O que a adaptação da OCTA mudou
- Duas colunas sem cabeçalho, valor alinhado à direita
- Padding lateral zero — o respiro vem do contêiner
Lacunas do original
- Só estrutura e estilo base — sem ordenação, sem paginação, sem seleção de linha
- O realce de hover não existe no celular
- O demo do 21st (coluna Member/Role, avatar, selo) não veio no código: só os primitivos