Data Table
A table built from rows of data and its ui-column children. Each column is a real header cell, and the table renders a row per item with one cell per column, so it reads as a table before JavaScript and to a screen reader. The header stays in view while the rows scroll; frozen on a column and frozen-rows on the table keep columns and leading rows in view too. Give the table a bounded height to scroll its rows. For a table written by hand, use Table.
Orders table
A captioned table with a column per field and figures set along the end of each row.
| Customer | Items | Total |
|---|---|---|
| Ada Park | 3 | $124.00 |
| Ben Ortiz | 1 | $18.50 |
| Chen Wu | 5 | $302.10 |
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-data-table/ui-data-table.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-column/ui-column.html"
>
<ui-data-table
caption="Orders"
rows="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<ui-column
field="customer"
header="Customer"
></ui-column>
<ui-column
field="items"
header="Items"
align="end"
></ui-column>
<ui-column
field="total"
header="Total"
align="end"
></ui-column>
</ui-data-table><script setup>
import { UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<template>
<UiDataTable
caption="Orders"
:rows="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>
</template>import { UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>;
}/** @jsxImportSource preact */
import { UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>;
}<script>
import { UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>import { Component } from "@angular/core";
import { UiColumn, UiDataTable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDataTable, UiColumn],
template: `
<div
ui-data-table
[caption]="'Orders'"
[rows]="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<th
ui-column
[field]="'customer'"
[header]="'Customer'"
></th>
<th
ui-column
[field]="'items'"
[header]="'Items'"
[align]="'end'"
></th>
<th
ui-column
[field]="'total'"
[header]="'Total'"
[align]="'end'"
></th>
</div>
`,
})
export default class Example {}Columns as markup
Each ui-column names the row field it shows and its header. align="end" sets a column of figures along the end of the row.
| Customer | Items | Total |
|---|---|---|
| Ada Park | 3 | $124.00 |
| Ben Ortiz | 1 | $18.50 |
| Chen Wu | 5 | $302.10 |
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-data-table/ui-data-table.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-column/ui-column.html"
>
<ui-data-table
caption="Orders"
rows="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<ui-column
field="customer"
header="Customer"
></ui-column>
<ui-column
field="items"
header="Items"
align="end"
></ui-column>
<ui-column
field="total"
header="Total"
align="end"
></ui-column>
</ui-data-table><script setup>
import { UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<template>
<UiDataTable
caption="Orders"
:rows="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>
</template>import { UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>;
}/** @jsxImportSource preact */
import { UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>;
}<script>
import { UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<UiDataTable
caption="Orders"
rows={[{"id":1,"customer":"Ada Park","items":3,"total":"$124.00"},{"id":2,"customer":"Ben Ortiz","items":1,"total":"$18.50"},{"id":3,"customer":"Chen Wu","items":5,"total":"$302.10"}]}
>
<UiColumn
field="customer"
header="Customer"
/>
<UiColumn
field="items"
header="Items"
align="end"
/>
<UiColumn
field="total"
header="Total"
align="end"
/>
</UiDataTable>import { Component } from "@angular/core";
import { UiColumn, UiDataTable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDataTable, UiColumn],
template: `
<div
ui-data-table
[caption]="'Orders'"
[rows]="[{ id: 1, customer: 'Ada Park', items: 3, total: '$124.00' }, { id: 2, customer: 'Ben Ortiz', items: 1, total: '$18.50' }, { id: 3, customer: 'Chen Wu', items: 5, total: '$302.10' }]"
>
<th
ui-column
[field]="'customer'"
[header]="'Customer'"
></th>
<th
ui-column
[field]="'items'"
[header]="'Items'"
[align]="'end'"
></th>
<th
ui-column
[field]="'total'"
[header]="'Total'"
[align]="'end'"
></th>
</div>
`,
})
export default class Example {}Cell content
A column's cell template renders once per row and reads the row as $row. A header slot replaces the header text with markup.
| Name | Role | Active |
|---|---|---|
| Ada Park | Design | Active |
| Ben Ortiz | Engineering | Away |
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-data-table/ui-data-table.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-column/ui-column.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-badge/ui-badge.html"
>
<ui-data-table
caption="Team"
rows="[{ id: 1, name: 'Ada Park', role: 'Design', active: true }, { id: 2, name: 'Ben Ortiz', role: 'Engineering', active: false }]"
>
<ui-column
field="name"
header="Name"
></ui-column>
<ui-column
field="role"
header="Role"
></ui-column>
<ui-column>
<abbr
slot="header"
title="Signed in this week"
>Active</abbr>
<template
slot="cell"
>
<ui-badge
from:tone="$row.active ? 'success' : 'neutral'"
>{$row.active ? 'Active' : 'Away'}</ui-badge>
</template>
</ui-column>
</ui-data-table><script setup>
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<template>
<UiDataTable
caption="Team"
:rows="[{ id: 1, name: 'Ada Park', role: 'Design', active: true }, { id: 2, name: 'Ben Ortiz', role: 'Engineering', active: false }]"
>
<UiColumn
field="name"
header="Name"
/>
<UiColumn
field="role"
header="Role"
/>
<UiColumn>
<template #header>
<abbr
title="Signed in this week"
>Active</abbr>
</template>
<template #cell>
<UiBadge
from:tone="$row.active ? 'success' : 'neutral'"
>{$row.active ? 'Active' : 'Away'}</UiBadge>
</template>
</UiColumn>
</UiDataTable>
</template>import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Team"
rows={[{"id":1,"name":"Ada Park","role":"Design","active":true},{"id":2,"name":"Ben Ortiz","role":"Engineering","active":false}]}
>
<UiColumn
field="name"
header="Name"
/>
<UiColumn
field="role"
header="Role"
/>
<UiColumn
slots={{
header: <abbr
title="Signed in this week"
>Active</abbr>,
cell: <UiBadge
from:tone="$row.active ? 'success' : 'neutral'"
>{"{"}$row.active ? 'Active' : 'Away'{"}"}</UiBadge>,
}}
>{" "}{" "}{" "}</UiColumn>
</UiDataTable>;
}/** @jsxImportSource preact */
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Team"
rows={[{"id":1,"name":"Ada Park","role":"Design","active":true},{"id":2,"name":"Ben Ortiz","role":"Engineering","active":false}]}
>
<UiColumn
field="name"
header="Name"
/>
<UiColumn
field="role"
header="Role"
/>
<UiColumn
slots={{
header: <abbr
title="Signed in this week"
>Active</abbr>,
cell: <UiBadge
from:tone="$row.active ? 'success' : 'neutral'"
>{"{"}$row.active ? 'Active' : 'Away'{"}"}</UiBadge>,
}}
>{" "}{" "}{" "}</UiColumn>
</UiDataTable>;
}<script>
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
{#snippet header()}
<abbr
title="Signed in this week"
>Active</abbr>
{/snippet}
{#snippet cell()}
<UiBadge
from:tone="$row.active ? 'success' : 'neutral'"
>{'{'}$row.active ? 'Active' : 'Away'}</UiBadge>
{/snippet}
<UiDataTable
caption="Team"
rows={[{"id":1,"name":"Ada Park","role":"Design","active":true},{"id":2,"name":"Ben Ortiz","role":"Engineering","active":false}]}
>
<UiColumn
field="name"
header="Name"
/>
<UiColumn
field="role"
header="Role"
/>
<UiColumn
slots={{ header, cell }}
> </UiColumn>
</UiDataTable>import { Component } from "@angular/core";
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDataTable, UiColumn, UiBadge],
template: `
<div
ui-data-table
[caption]="'Team'"
[rows]="[{ id: 1, name: 'Ada Park', role: 'Design', active: true }, { id: 2, name: 'Ben Ortiz', role: 'Engineering', active: false }]"
>
<th
ui-column
[field]="'name'"
[header]="'Name'"
></th>
<th
ui-column
[field]="'role'"
[header]="'Role'"
></th>
<th
ui-column
>
<ng-container ngProjectAs="[slot='header']">
<abbr
title="Signed in this week"
>Active</abbr>
</ng-container>
<ng-container ngProjectAs="[slot='cell']">
<span
ui-badge
from:tone="$row.active ? 'success' : 'neutral'"
>{$row.active ? 'Active' : 'Away'}</span>
</ng-container>
</th>
</div>
`,
})
export default class Example {}Frozen columns and rows
The header stays in view while the rows scroll. frozen="start" or frozen="end" keeps a column in view while the table scrolls sideways, and frozen-rows keeps leading rows beneath the header. A Stack with a height bounds the table here, so its rows scroll.
| Region | First quarter | Second quarter | Third quarter | Fourth quarter | Total |
|---|---|---|---|---|---|
| All regions | 4210 | 4630 | 4980 | 5410 | 19230 |
| North | 1020 | 1130 | 1210 | 1340 | 4700 |
| South | 980 | 1040 | 1150 | 1260 | 4430 |
| East | 1110 | 1250 | 1320 | 1430 | 5110 |
| West | 1100 | 1210 | 1300 | 1380 | 4990 |
| Central | 640 | 700 | 760 | 820 | 2920 |
| Coastal | 590 | 650 | 700 | 760 | 2700 |
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-data-table/ui-data-table.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-column/ui-column.html"
>
<ui-stack
height="224"
>
<ui-data-table
caption="Regional sales"
frozen-rows="1"
rows="[{ id: 0, region: 'All regions', q1: 4210, q2: 4630, q3: 4980, q4: 5410, total: 19230 }, { id: 1, region: 'North', q1: 1020, q2: 1130, q3: 1210, q4: 1340, total: 4700 }, { id: 2, region: 'South', q1: 980, q2: 1040, q3: 1150, q4: 1260, total: 4430 }, { id: 3, region: 'East', q1: 1110, q2: 1250, q3: 1320, q4: 1430, total: 5110 }, { id: 4, region: 'West', q1: 1100, q2: 1210, q3: 1300, q4: 1380, total: 4990 }, { id: 5, region: 'Central', q1: 640, q2: 700, q3: 760, q4: 820, total: 2920 }, { id: 6, region: 'Coastal', q1: 590, q2: 650, q3: 700, q4: 760, total: 2700 }]"
>
<ui-column
field="region"
header="Region"
frozen="start"
width="9rem"
></ui-column>
<ui-column
field="q1"
header="First quarter"
align="end"
width="10rem"
></ui-column>
<ui-column
field="q2"
header="Second quarter"
align="end"
width="10rem"
></ui-column>
<ui-column
field="q3"
header="Third quarter"
align="end"
width="10rem"
></ui-column>
<ui-column
field="q4"
header="Fourth quarter"
align="end"
width="10rem"
></ui-column>
<ui-column
field="total"
header="Total"
align="end"
frozen="end"
width="7rem"
></ui-column>
</ui-data-table>
</ui-stack><script setup>
import { UiColumn, UiDataTable, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
:height="224"
>
<UiDataTable
caption="Regional sales"
:frozen-rows="1"
:rows="[{ id: 0, region: 'All regions', q1: 4210, q2: 4630, q3: 4980, q4: 5410, total: 19230 }, { id: 1, region: 'North', q1: 1020, q2: 1130, q3: 1210, q4: 1340, total: 4700 }, { id: 2, region: 'South', q1: 980, q2: 1040, q3: 1150, q4: 1260, total: 4430 }, { id: 3, region: 'East', q1: 1110, q2: 1250, q3: 1320, q4: 1430, total: 5110 }, { id: 4, region: 'West', q1: 1100, q2: 1210, q3: 1300, q4: 1380, total: 4990 }, { id: 5, region: 'Central', q1: 640, q2: 700, q3: 760, q4: 820, total: 2920 }, { id: 6, region: 'Coastal', q1: 590, q2: 650, q3: 700, q4: 760, total: 2700 }]"
>
<UiColumn
field="region"
header="Region"
frozen="start"
width="9rem"
/>
<UiColumn
field="q1"
header="First quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q2"
header="Second quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q3"
header="Third quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q4"
header="Fourth quarter"
align="end"
width="10rem"
/>
<UiColumn
field="total"
header="Total"
align="end"
frozen="end"
width="7rem"
/>
</UiDataTable>
</UiStack>
</template>import { UiColumn, UiDataTable, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
height={224}
>
<UiDataTable
caption="Regional sales"
frozenRows={1}
rows={[{"id":0,"region":"All regions","q1":4210,"q2":4630,"q3":4980,"q4":5410,"total":19230},{"id":1,"region":"North","q1":1020,"q2":1130,"q3":1210,"q4":1340,"total":4700},{"id":2,"region":"South","q1":980,"q2":1040,"q3":1150,"q4":1260,"total":4430},{"id":3,"region":"East","q1":1110,"q2":1250,"q3":1320,"q4":1430,"total":5110},{"id":4,"region":"West","q1":1100,"q2":1210,"q3":1300,"q4":1380,"total":4990},{"id":5,"region":"Central","q1":640,"q2":700,"q3":760,"q4":820,"total":2920},{"id":6,"region":"Coastal","q1":590,"q2":650,"q3":700,"q4":760,"total":2700}]}
>
<UiColumn
field="region"
header="Region"
frozen="start"
width="9rem"
/>
<UiColumn
field="q1"
header="First quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q2"
header="Second quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q3"
header="Third quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q4"
header="Fourth quarter"
align="end"
width="10rem"
/>
<UiColumn
field="total"
header="Total"
align="end"
frozen="end"
width="7rem"
/>
</UiDataTable>
</UiStack>;
}/** @jsxImportSource preact */
import { UiColumn, UiDataTable, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
height={224}
>
<UiDataTable
caption="Regional sales"
frozenRows={1}
rows={[{"id":0,"region":"All regions","q1":4210,"q2":4630,"q3":4980,"q4":5410,"total":19230},{"id":1,"region":"North","q1":1020,"q2":1130,"q3":1210,"q4":1340,"total":4700},{"id":2,"region":"South","q1":980,"q2":1040,"q3":1150,"q4":1260,"total":4430},{"id":3,"region":"East","q1":1110,"q2":1250,"q3":1320,"q4":1430,"total":5110},{"id":4,"region":"West","q1":1100,"q2":1210,"q3":1300,"q4":1380,"total":4990},{"id":5,"region":"Central","q1":640,"q2":700,"q3":760,"q4":820,"total":2920},{"id":6,"region":"Coastal","q1":590,"q2":650,"q3":700,"q4":760,"total":2700}]}
>
<UiColumn
field="region"
header="Region"
frozen="start"
width="9rem"
/>
<UiColumn
field="q1"
header="First quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q2"
header="Second quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q3"
header="Third quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q4"
header="Fourth quarter"
align="end"
width="10rem"
/>
<UiColumn
field="total"
header="Total"
align="end"
frozen="end"
width="7rem"
/>
</UiDataTable>
</UiStack>;
}<script>
import { UiColumn, UiDataTable, UiStack } from "@threadlabs/looma";
</script>
<UiStack
height={224}
>
<UiDataTable
caption="Regional sales"
frozenRows={1}
rows={[{"id":0,"region":"All regions","q1":4210,"q2":4630,"q3":4980,"q4":5410,"total":19230},{"id":1,"region":"North","q1":1020,"q2":1130,"q3":1210,"q4":1340,"total":4700},{"id":2,"region":"South","q1":980,"q2":1040,"q3":1150,"q4":1260,"total":4430},{"id":3,"region":"East","q1":1110,"q2":1250,"q3":1320,"q4":1430,"total":5110},{"id":4,"region":"West","q1":1100,"q2":1210,"q3":1300,"q4":1380,"total":4990},{"id":5,"region":"Central","q1":640,"q2":700,"q3":760,"q4":820,"total":2920},{"id":6,"region":"Coastal","q1":590,"q2":650,"q3":700,"q4":760,"total":2700}]}
>
<UiColumn
field="region"
header="Region"
frozen="start"
width="9rem"
/>
<UiColumn
field="q1"
header="First quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q2"
header="Second quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q3"
header="Third quarter"
align="end"
width="10rem"
/>
<UiColumn
field="q4"
header="Fourth quarter"
align="end"
width="10rem"
/>
<UiColumn
field="total"
header="Total"
align="end"
frozen="end"
width="7rem"
/>
</UiDataTable>
</UiStack>import { Component } from "@angular/core";
import { UiColumn, UiDataTable, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiDataTable, UiColumn],
template: `
<div
ui-stack
[height]="224"
>
<div
ui-data-table
[caption]="'Regional sales'"
[frozenRows]="1"
[rows]="[{ id: 0, region: 'All regions', q1: 4210, q2: 4630, q3: 4980, q4: 5410, total: 19230 }, { id: 1, region: 'North', q1: 1020, q2: 1130, q3: 1210, q4: 1340, total: 4700 }, { id: 2, region: 'South', q1: 980, q2: 1040, q3: 1150, q4: 1260, total: 4430 }, { id: 3, region: 'East', q1: 1110, q2: 1250, q3: 1320, q4: 1430, total: 5110 }, { id: 4, region: 'West', q1: 1100, q2: 1210, q3: 1300, q4: 1380, total: 4990 }, { id: 5, region: 'Central', q1: 640, q2: 700, q3: 760, q4: 820, total: 2920 }, { id: 6, region: 'Coastal', q1: 590, q2: 650, q3: 700, q4: 760, total: 2700 }]"
>
<th
ui-column
[field]="'region'"
[header]="'Region'"
[frozen]="'start'"
[width]="'9rem'"
></th>
<th
ui-column
[field]="'q1'"
[header]="'First quarter'"
[align]="'end'"
[width]="'10rem'"
></th>
<th
ui-column
[field]="'q2'"
[header]="'Second quarter'"
[align]="'end'"
[width]="'10rem'"
></th>
<th
ui-column
[field]="'q3'"
[header]="'Third quarter'"
[align]="'end'"
[width]="'10rem'"
></th>
<th
ui-column
[field]="'q4'"
[header]="'Fourth quarter'"
[align]="'end'"
[width]="'10rem'"
></th>
<th
ui-column
[field]="'total'"
[header]="'Total'"
[align]="'end'"
[frozen]="'end'"
[width]="'7rem'"
></th>
</div>
</div>
`,
})
export default class Example {}Field, header and cell content
A column shows its field of each row under its header, or its cell template, which reads the row as $row.
| Task | Hours | Status |
|---|---|---|
| Draft the brief | 3 | Done |
| Review the layout | 1 | Open |
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-data-table/ui-data-table.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-column/ui-column.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-badge/ui-badge.html"
>
<ui-data-table
caption="Tasks"
rows="[{ id: 1, task: 'Draft the brief', hours: 3, done: true }, { id: 2, task: 'Review the layout', hours: 1, done: false }]"
>
<ui-column
field="task"
header="Task"
></ui-column>
<ui-column
field="hours"
header="Hours"
align="end"
></ui-column>
<ui-column
header="Status"
>
<template
slot="cell"
>
<ui-badge
from:tone="$row.done ? 'success' : 'neutral'"
>{$row.done ? 'Done' : 'Open'}</ui-badge>
</template>
</ui-column>
</ui-data-table><script setup>
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
<template>
<UiDataTable
caption="Tasks"
:rows="[{ id: 1, task: 'Draft the brief', hours: 3, done: true }, { id: 2, task: 'Review the layout', hours: 1, done: false }]"
>
<UiColumn
field="task"
header="Task"
/>
<UiColumn
field="hours"
header="Hours"
align="end"
/>
<UiColumn
header="Status"
>
<template #cell>
<UiBadge
from:tone="$row.done ? 'success' : 'neutral'"
>{$row.done ? 'Done' : 'Open'}</UiBadge>
</template>
</UiColumn>
</UiDataTable>
</template>import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Tasks"
rows={[{"id":1,"task":"Draft the brief","hours":3,"done":true},{"id":2,"task":"Review the layout","hours":1,"done":false}]}
>
<UiColumn
field="task"
header="Task"
/>
<UiColumn
field="hours"
header="Hours"
align="end"
/>
<UiColumn
header="Status"
slots={{
cell: <UiBadge
from:tone="$row.done ? 'success' : 'neutral'"
>{"{"}$row.done ? 'Done' : 'Open'{"}"}</UiBadge>,
}}
>{" "}{" "}</UiColumn>
</UiDataTable>;
}/** @jsxImportSource preact */
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
export default function Example() {
return <UiDataTable
caption="Tasks"
rows={[{"id":1,"task":"Draft the brief","hours":3,"done":true},{"id":2,"task":"Review the layout","hours":1,"done":false}]}
>
<UiColumn
field="task"
header="Task"
/>
<UiColumn
field="hours"
header="Hours"
align="end"
/>
<UiColumn
header="Status"
slots={{
cell: <UiBadge
from:tone="$row.done ? 'success' : 'neutral'"
>{"{"}$row.done ? 'Done' : 'Open'{"}"}</UiBadge>,
}}
>{" "}{" "}</UiColumn>
</UiDataTable>;
}<script>
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
</script>
{#snippet cell()}
<UiBadge
from:tone="$row.done ? 'success' : 'neutral'"
>{'{'}$row.done ? 'Done' : 'Open'}</UiBadge>
{/snippet}
<UiDataTable
caption="Tasks"
rows={[{"id":1,"task":"Draft the brief","hours":3,"done":true},{"id":2,"task":"Review the layout","hours":1,"done":false}]}
>
<UiColumn
field="task"
header="Task"
/>
<UiColumn
field="hours"
header="Hours"
align="end"
/>
<UiColumn
header="Status"
slots={{ cell }}
> </UiColumn>
</UiDataTable>import { Component } from "@angular/core";
import { UiBadge, UiColumn, UiDataTable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDataTable, UiColumn, UiBadge],
template: `
<div
ui-data-table
[caption]="'Tasks'"
[rows]="[{ id: 1, task: 'Draft the brief', hours: 3, done: true }, { id: 2, task: 'Review the layout', hours: 1, done: false }]"
>
<th
ui-column
[field]="'task'"
[header]="'Task'"
></th>
<th
ui-column
[field]="'hours'"
[header]="'Hours'"
[align]="'end'"
></th>
<th
ui-column
[header]="'Status'"
>
<ng-container ngProjectAs="[slot='cell']">
<span
ui-badge
from:tone="$row.done ? 'success' : 'neutral'"
>{$row.done ? 'Done' : 'Open'}</span>
</ng-container>
</th>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
caption | Names the table. A screen reader announces it with the table, and it names the scrolling region. | caption | string | — | — |
density | How tall each row is. comfortable fits a control of the standard height; compact fits a small one, for long tables to scan. | density | keyword | comfortable | comfortable, compact |
frozen-rows | How many leading rows stay in view beneath the header while the rows scroll. Frozen rows suit totals or a pinned item. | frozenRows | integer | 0 | — |
row-key | The row field that identifies each row, so a row keeps its cells, and the state of any control in them, when the rows change order. | rowKey | string | id | — |
rows | One entry per table row. Each column shows its field of the row, or its own cell content. | rows | list(object) | [] | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
caption | string | — | — |
density | "comfortable" | "compact" | comfortable | comfortable, compact |
frozenRows | number | 0 | — |
rowKey | string | id | — |
rows | readonly ({ readonly [name: string]: unknown })[] | [] | — |
Events
No events.
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
No component tokens.
Shared tokens
| Token | Fallback |
|---|---|
--ui-border-divider | — |
--ui-border-subtle | — |
--ui-border-width | — |
--ui-control-size | — |
--ui-control-size-sm | — |
--ui-focus-ring | — |
--ui-focus-width | — |
--ui-font-medium | — |
--ui-font-size-sm | — |
--ui-line-height | — |
--ui-space-0-5 | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-surface | — |
--ui-text-primary | — |
--ui-text-secondary | — |
Column API
One column of a ui-data-table. Its root is the column's header cell. The table shows the column's field of each row, or the column's cell content, which reads the row as $row.
Package: @threadlabs/looma · Native root: th
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
align | Where the header and every cell set their content along the row, such as end for a column of figures. | align | keyword | start | start, center, end |
field | The row field each cell shows when the column gives no cell content. | field | string | — | — |
frozen | Keeps the column in view while the table scrolls sideways. start holds it at the inline start edge, beside any frozen columns before it; end holds it at the inline end edge, beside any frozen columns after it. | frozen | keyword | none | none, start, end |
header | The header text. Content in the header slot replaces it, for markup such as an abbreviation. | header | string | — | — |
width | The column's width as a CSS length, such as 12rem. The column sizes to its content when it is not set. | width | string | — | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
align | "start" | "center" | "end" | start | start, center, end |
field | string | — | — |
frozen | "none" | "start" | "end" | none | none, start, end |
header | string | — | — |
width | string | — | — |
Events
No events.
Slots
| Name | Purpose |
|---|---|
header | Named content for the header region. |
cell | Named content for the cell region. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
No component tokens.
Shared tokens
| Token | Fallback |
|---|---|
--ui-border-divider | — |
--ui-border-width | — |
--ui-font-medium | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-surface | — |
--ui-text-muted | — |