Skip to main content

Table

Function Table 

Source
pub fn Table(props: TableProps) -> impl IntoView
Expand description

Semantic table shell for static or server-rendered data rows and columns.

Compose explicit header, body, row, and cell parts you control. Reach for DataTable when you need built-in sort, filter, row selection, pagination, or virtualization — it renders through these parts internally.

§When to use

  • Static or lightly interactive tabular content with full control over markup - Small-to-medium row counts, server-rendered lists, summary/report tables - Paginated lists and admin grids where you own sorting/filtering in app code

§When to use DataTable instead

Reach for DataTable when you need a built-in data engine: client-side sort, filter, row selection, pagination, or feature flags such as virtualization and column pinning. [DataTable] renders through these Table parts internally — they are not competing engines. Rule of thumb: start with Table; adopt DataTable only when interactive data features justify the heavier API.

§Usage

  1. Wrap everything in Table. 2. Add a [TableHeader] with one [TableRow] of [TableHeaderCell] labels. 3. Add a [TableBody] with one [TableRow] per data record. 4. Wrap cell content in [TableCell] → [TableCellLayout] for truncation.

§Best Practices

§Do’s

  • Compose header, body, rows, and cells explicitly * Use [TableCellLayout] with truncate=true in narrow columns * Keep header labels in [TableHeaderCell], data in [TableCell]

§Don’ts

  • Do not use tables for page layout — prefer crate::Flex or crate::Grid * Do not skip [TableHeader] when columns have semantic meaning

§Examples

§Simple semantic table

Minimal header plus one body row—the starting point before adding pagination or row actions.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout};
view! {
    <div data-testid="table-preview">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell>"Name"</TableHeaderCell>
                    <TableHeaderCell>"Role"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout><span data-testid="table-cell-name">"Ada"</span></TableCellLayout></TableCell>
                    <TableCell><TableCellLayout><span data-testid="table-cell-role">"Admin"</span></TableCellLayout></TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Full compound (3 columns, 2 rows)

Full compound structure with header labels, body rows, cells, and layout wrappers for admin grids.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout};
view! {
    <div data-testid="table-compound">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell>"Name"</TableHeaderCell>
                    <TableHeaderCell>"Role"</TableHeaderCell>
                    <TableHeaderCell>"Status"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"Ada Lovelace"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"Admin"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"Active"</TableCellLayout></TableCell>
                </TableRow>
                <TableRow>
                    <TableCell><TableCellLayout>"Grace Hopper"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"Editor"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"Active"</TableCellLayout></TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Multiple body rows

Multiple body rows with a single column—useful for simple ordered lists.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout};
view! {
    <div data-testid="table-rows">
        <Table>
            <TableHeader>
                <TableRow><TableHeaderCell>"ID"</TableHeaderCell></TableRow>
            </TableHeader>
            <TableBody>
                <TableRow><TableCell><TableCellLayout><span data-testid="table-row-id-1">"1"</span></TableCellLayout></TableCell></TableRow>
                <TableRow><TableCell><TableCellLayout><span data-testid="table-row-id-2">"2"</span></TableCellLayout></TableCell></TableRow>
                <TableRow><TableCell><TableCellLayout><span data-testid="table-row-id-3">"3"</span></TableCellLayout></TableCell></TableRow>
            </TableBody>
        </Table>
    </div>
}

§Truncated long text

truncate=true ellipsizes long text in narrow columns without breaking table layout.

use crate::{Table, TableBody, TableRow, TableCell, TableCellLayout, TableCellLayoutConfig};
view! {
    <div data-testid="table-truncate" style="max-width: 200px;">
        <Table>
            <TableBody>
                <TableRow>
                    <TableCell>
                        <TableCellLayout config=TableCellLayoutConfig { truncate: true }>
                            <span data-testid="table-truncate-text">"Long description that truncates in narrow columns"</span>
                        </TableCellLayout>
                    </TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Resizable columns

Drag header edges to resize columns; min/max width keep columns within a usable range.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout, TableHeaderCellConfig};
view! {
    <div data-testid="table-resizable">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell config=TableHeaderCellConfig::resizable(80.0, 240.0)>
                        "Name"
                    </TableHeaderCell>
                    <TableHeaderCell config=TableHeaderCellConfig::resizable(60.0, 180.0)>
                        "Role"
                    </TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"Ada Lovelace"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"Admin"</TableCellLayout></TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Theme tokens

Header borders and row dividers inherit stroke tokens from the Orbital theme provider.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout};
view! {
    <div data-testid="table-theme">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell>"Column"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"Themed row"</TableCellLayout></TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Status badges in cells

Compose Badge inside [TableCellLayout] for status columns.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout, Badge, BadgeAppearance, BadgeColor};
view! {
    <div data-testid="table-badges">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell>"Name"</TableHeaderCell>
                    <TableHeaderCell>"Status"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"Ada"</TableCellLayout></TableCell>
                    <TableCell>
                        <TableCellLayout>
                            <Badge appearance=BadgeAppearance::Filled color=BadgeColor::Success>
                                <span data-testid="table-badge-active">"Active"</span>
                            </Badge>
                        </TableCellLayout>
                    </TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Wide resizable admin grid

Three resizable columns with distinct min/max constraints for dense admin tables.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout, TableHeaderCellConfig};
view! {
    <div data-testid="table-resizable-wide">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell config=TableHeaderCellConfig::resizable(120.0, 300.0)>"A"</TableHeaderCell>
                    <TableHeaderCell config=TableHeaderCellConfig::resizable(120.0, 300.0)>"B"</TableHeaderCell>
                    <TableHeaderCell config=TableHeaderCellConfig::resizable(120.0, 300.0)>"C"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"1"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"2"</TableCellLayout></TableCell>
                    <TableCell><TableCellLayout>"3"</TableCellLayout></TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Row actions with Button

Interactive controls inside cells for edit/delete row actions.

use crate::{Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableCellLayout, Button, ButtonAppearance};
view! {
    <div data-testid="table-actions">
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHeaderCell>"Name"</TableHeaderCell>
                    <TableHeaderCell>"Actions"</TableHeaderCell>
                </TableRow>
            </TableHeader>
            <TableBody>
                <TableRow>
                    <TableCell><TableCellLayout>"Ada"</TableCellLayout></TableCell>
                    <TableCell>
                        <TableCellLayout>
                            <span data-testid="table-action-edit"><Button appearance=ButtonAppearance::Subtle>"Edit"</Button></span>
                        </TableCellLayout>
                    </TableCell>
                </TableRow>
            </TableBody>
        </Table>
    </div>
}

§Required Props

  • children: Children
    • Table sections: [TableHeader] and/or [TableBody] with nested rows and cells.

§Optional Props