Tabela
Nesta página
Passa columns e rows e a tabela constrói-se sozinha, cabeçalho incluído. Vai envolvida num contentor com deslocamento horizontal, por isso uma tabela com mais colunas do que um telemóvel mostra desliza sozinha em vez de esticar a página. Exportada como table e como dataTable.
Tabela básica
| Página | Tamanho | Tempo de render |
|---|---|---|
| / | 4,1 kB | 12 ms |
| /docs | 12,7 kB | 31 ms |
| /examples | 9,4 kB | 24 ms |
table({
columns: [
{ key: 'page', header: 'Página' },
{ key: 'size', header: 'Tamanho' },
{ key: 'time', header: 'Tempo de render' },
],
rows: [
{ page: '/', size: '4,1 kB', time: '12 ms' },
{ page: '/docs', size: '12,7 kB', time: '31 ms' },
{ page: '/examples', size: '9,4 kB', time: '24 ms' },
],
})Alinhamento
Os números leem-se melhor alinhados ao fim da sua coluna.
| Página | Bytes | Gzip |
|---|---|---|
| / | 4 112 | 1 204 |
| /docs | 12 704 | 3 910 |
| /examples | 9 388 | 2 744 |
table({
columns: [
{ key: 'page', header: 'Página' },
{ key: 'bytes', header: 'Bytes', align: 'end' },
{ key: 'gzip', header: 'Gzip', align: 'end' },
],
rows: [
{ page: '/', bytes: '4 112', gzip: '1 204' },
{ page: '/docs', bytes: '12 704', gzip: '3 910' },
{ page: '/examples', bytes: '9 388', gzip: '2 744' },
],
})Células à medida
Uma coluna com uma função render recebe a linha inteira e devolve o que deve ficar na célula — um chip, uma ligação, um número formatado.
| Página | Tamanho | Estado |
|---|---|---|
| /docs/routing | 18,2 kB | ok |
| /docs/data | 21,7 kB | ok |
| /docs/islands | 24,1 kB | falhou |
table({
columns: [
{ header: 'Página', render: (row) => link({ href: row.href }, row.page) },
{ key: 'size', header: 'Tamanho', align: 'end' },
{ header: 'Estado', align: 'end', render: (row) =>
chip({ size: 'sm', dot: true, color: row.ok ? 'success' : 'danger' }, row.ok ? 'ok' : 'falhou') },
],
rows: [
{ page: '/docs/routing', href: '/pt/docs/routing', size: '18,2 kB', ok: true },
{ page: '/docs/data', href: '/pt/docs/data', size: '21,7 kB', ok: true },
{ page: '/docs/islands', href: '/pt/docs/islands', size: '24,1 kB', ok: false },
],
})Estilos
striped pinta linhas alternadas, hover realça a linha sob o ponteiro, e dense aperta o espaçamento para uma tabela com muitas linhas.
| Nome | Valor |
|---|---|
| páginas | 169 |
| recursos | 208 |
| total | 9,5 MB |
| Nome | Valor |
|---|---|
| páginas | 169 |
| recursos | 208 |
| total | 9,5 MB |
stack({ gap: 'lg' },
table({
striped: true,
caption: 'às riscas',
columns: [{ key: 'name', header: 'Nome' }, { key: 'value', header: 'Valor', align: 'end' }],
rows: [{ name: 'páginas', value: '169' }, { name: 'recursos', value: '208' }, { name: 'total', value: '9,5 MB' }],
}),
table({
hover: true,
dense: true,
caption: 'com realce e densa',
columns: [{ key: 'name', header: 'Nome' }, { key: 'value', header: 'Valor', align: 'end' }],
rows: [{ name: 'páginas', value: '169' }, { name: 'recursos', value: '208' }, { name: 'total', value: '9,5 MB' }],
}),
)Legenda
Uma legenda dá nome à tabela para quem chega a ela sem o texto à volta — vale a pena sempre que a tabela não esteja logo abaixo de um cabeçalho que já diga o que é.
| Commit | Quando | Páginas |
|---|---|---|
| 94a837a | há 4 minutos | 169 |
| dcfaaae | há 2 horas | 161 |
table({
caption: 'Saída das construções, a mais recente primeiro',
columns: [
{ key: 'commit', header: 'Commit' },
{ key: 'when', header: 'Quando' },
{ key: 'pages', header: 'Páginas', align: 'end' },
],
rows: [
{ commit: '94a837a', when: 'há 4 minutos', pages: '169' },
{ commit: 'dcfaaae', when: 'há 2 horas', pages: '161' },
],
})A partir de dados
As linhas são um array vulgar, por isso costumam ser aquilo que o data() já carregou — sem adaptador pelo meio.
| Artigo | Publicado | Leituras |
|---|---|---|
| Olá mundo | 2026-01-14 | 1.204 |
| Estático primeiro | 2026-02-02 | 890 |
| Sem runtime | 2026-03-19 | 2.317 |
return (() => {
const posts = [
{ title: 'Olá mundo', date: '2026-01-14', reads: 1204 },
{ title: 'Estático primeiro', date: '2026-02-02', reads: 890 },
{ title: 'Sem runtime', date: '2026-03-19', reads: 2317 },
]
return table({
hover: true,
columns: [
{ key: 'title', header: 'Artigo' },
{ key: 'date', header: 'Publicado' },
{ header: 'Leituras', align: 'end', render: (post) => post.reads.toLocaleString('pt') },
],
rows: posts,
})
})()Escrever a marcação à mão
Omite columns e a tabela desenha antes os seus filhos, por isso uma tabela com linha de rodapé ou cabeçalhos agrupados pode ser feita à mão e continuar a receber o estilo e o contentor com deslocamento.
Props
| Prop | Tipo | Predefinição | Descrição |
|---|---|---|---|
columns | TableColumn[] | — | { key, header, align, render } por coluna. Omite para escreveres as linhas à mão. |
rows | object[] | [] | Um objeto por linha. |
caption | Child | — | Uma legenda por cima da tabela. |
striped | boolean | false | Pintar linhas alternadas. |
hover | boolean | false | Realçar a linha sob o ponteiro. |
dense | boolean | false | Espaçamento de célula mais apertado. |