Pricing

Table handbook

v2.7.1 · @snowui-design-system/components

License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.

Overview

Render structured data as a semantic table with responsive column widths, local horizontal scrolling, and loading display. Compose headers and cells freely.

When to use it

Use Table for plain structured display by composing TableHeader, TableBody, TableRow, TableHead, and TableCell. Use DataTable when search, sorting, selection, action columns, or pagination are required.

  • Maintain the legal table hierarchy through TableHeader / TableBody / TableRow, etc.

  • columnWidths saves the column width, columnId aligns with the same column; data query, selection and paging are handed over to DataTable.

Quick start

This example shows the recommended basic composition. See the sections below for more cases and composition limits.

<script lang="ts">	import { Table, Chip, Button, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@snowui-design-system/components';	const invoices = [	  { id: "INV-1048", customer: "Linear", status: "Paid", amount: "$240.00", note: "Design system subscription" },	  { id: "INV-1047", customer: "Figma", status: "Paid", amount: "$120.00", note: "Additional seats for the product team" },	  { id: "INV-1046", customer: "Notion", status: "Pending", amount: "$360.00", note: "Annual subscription, awaiting approval" },	  { id: "INV-1045", customer: "Vercel", status: "Paid", amount: "$180.00", note: "Component library subscription" },	  { id: "INV-1044", customer: "Framer", status: "Overdue", amount: "$90.00", note: "Payment reminder sent" },	];</script> <Table ariaLabel="Sample invoices">  <TableHeader>    <TableRow>      <TableHead columnId="invoice">Invoice</TableHead>      <TableHead columnId="customer">Customer</TableHead>      <TableHead columnId="status">Status</TableHead>      <TableHead columnId="amount" align="end">Amount</TableHead>    </TableRow>  </TableHeader>  <TableBody>    {#each invoices as invoice (invoice.id)}      <TableRow rowId={invoice.id}>        <TableCell columnId="invoice">{invoice.id}</TableCell>        <TableCell columnId="customer">{invoice.customer}</TableCell>        <TableCell columnId="status"><Chip variant="background" style={`color: ${invoice.status === "Paid" ? "var(--secondary-green)" : invoice.status === "Pending" ? "var(--secondary-orange)" : "var(--secondary-red)"};`}>{invoice.status}</Chip></TableCell>        <TableCell columnId="amount" align="end">{invoice.amount}</TableCell>      </TableRow>    {/each}  </TableBody></Table>

API

Keyword Type Default Description
columnWidths Record<string, number> {} Controlled column width, can bind:
horizontalScroll boolean true (inheritance DataTable) By default, keep all the columns and scroll horizontally; when false, hide the hidden columns from right to left first, and scroll the bottom when the retention column is still too wide.
roleLayout TableRoleLayout DataTable configuration or "auto" Auto switches between resident column and hover overlay according to space; explicit column / overlay fixed layout.
minWidth number | string — Explicitly expand the minimum width of the table; when not set, it is automatically summarized by each column min-content + Cell padding, and the overflow is handled by the built-in local horizontal viewport of Table.
ariaLabel string — The table’s business accessible name, kept exactly as supplied. The horizontal scroll region appends a localized scroll hint in the current LocaleProvider; without a name, it uses a localized generic label.
loadingSpinnerSize ResourceSize 16 When the existing data continues to be loaded, the size of the Spinner in the middle at the end of the table
onColumnWidthsChange (widths: Record<string, number>) => void — A complete snapshot after dragging the column width
children Snippet — Semantic table content, no parameters; combination TableHeader / TableBody, data management is provided by the outer layer DataTable.

See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.

Usage boundaries and details

Pass column headings through TableHead’s children slot. Text, icons, and non-interactive components may be combined. Give icon-only headings an accessible name, and do not nest interactive controls in sortable headings. See TableHead icon and component headings.

The boundary between Table and DataTable

Ordinary Table is a pure data display component: it is only responsible for rendering table headers and data rows with native table semantics. Ordinary tables do not provide loading more, checkbox selection column, button operation column, sorting, filtering, paging or search.

When any of the above data management or operation capabilities appear, use DataTable:

Ability Table DataTable
Table header and data line display ✓ ✓
Load more — ✓
Checkbox selection column — ✓
Button operation column — ✓
Sorting and filtering — ✓
Paging — ✓
Search / TableToolbar — ✓

Initial Skeleton rows and Spinner while loading existing data are Table’s display protocol. Table does not fetch data, load more, or paginate; callers set those states directly or through DataTable.

Layout model

Main layout model: composite management layout.

Structure:

  • Root Frame (table boundary and overlay scrollbar host)

    • Horizontal viewport (focusable local scrolling area)

      • Native table (Native table layout)

      • TableHeader / TableBody(thead / tbody)

        • TableRow(tr)

          • TableHead / TableCell(th / td)

Local layout source: Root Frame does not declare row / column, and does not enable general slot arrangement; table and each semantic sub-item explicitly close Auto Layout to maintain the native table layout of the browser. The sorting button inside TableHead and the optional content row of Indicator and TableCell belong to the local layout of each subcomponent.

Padding attribution: Table root layer and native table do not produce padding; TableHead / TableCell are responsible for padding respectively. The left and right padding of ordinary, selection and actions cells flows between 4px → 12px according to the table's own available width and content requirements: narrow containers converge to 4px on each side, so that the minimum visual spacing of adjacent columns is 8px; wide containers restore 12px on each side; leave at least 8px on the left and right white space on the outer edge of the table and the role floating layer. The upper and lower padding remains 8px; the registered Head/Cell padding override can still be taken over as a whole.

Gap attribution: There is no general gap between the native table columns, and the visual spacing comes from Cell padding; the gap of TableCell composite content is controlled by TableCell itself.

Inherent minimum width: When columnWidths / minWidth is not declared, the native table-layout:auto automatically forms the minimum width of the whole table with the min-content width of each column, and at least fills the host. The automatic lower limit of ordinary line-breakable cells with "the longest unbreakable word / fragment + cell left and right padding" as the column will not split the identifier word by word. The whole line of lines={1} / nowrap content is an unbreakable fragment, resulting in a more conservative lower column limit. Any explicit columnWidths, drag column width or fixed width belongs to the active overlay of the caller, and the column is handled according to the truncation rules of TableCell / TableHead.

Ordinary Table does not provide checkbox selection column or button operation column. TableHead/TableCell as="selection|actions" is only activated in DataTable Context; the selection status, role layout and batch operations are all held by DataTable.

TableHead of ordinary Table does not allow dragging to modify the column width by default; resizable is explicitly passed when necessary. The ordinary column of DataTable can be dragged by default, and the explicit resizable={false} can be closed. This default ability is only responsible for column width, and will not allow ordinary Table to automatically have data sorting rules.

In the DataTable selection role, the fully selected Checkbox of TableHead and the row Checkbox of TableCell use calc(var(--size-4) + 0.0625rem) by default, that is, 17×17px. The additional 0.0625rem is a special case of Table visual center registered by StyleSpec.md §2.2.2 (source code reference: specs/maintainers/StyleSpec.md). It does not borrow any border Token and does not change the 16px default value of the Checkbox component itself; it can be overwritten by --snowui-table-selection-checkbox-size-override.

The first loading column protocol: TableHead explicitly registers the column structure through Table Context; TableBody generates real tr / td Skeleton rows according to the structure when loading takes effect. The first loading only consumes the column registration inside the same semantic table; the responsive layout is also measured by the native table grid owned by the Table private controller. DataTable can provide the status of "first load and rows is empty" and the normalized pageSize through the same context inherited; independent Table can also be explicitly enabled by TableBody; rowCount is passed when the amount of data is known, and when it is unknown, it is estimated according to the visible height of the external container. For details, please refer to the TableBody document.

There is a data loading protocol: when loading or refreshing takes effect and there is currently a visible data row, TableBody retains the business line and adds a real tr / td loading line at the end; the cell crosses the header column of the registered form through colspan, and the internal reuses SnowUI general <Spinner size={16} /> and is horizontally and vertically centered in the 40px line. Table loading Spinner defaults to 16×16px, which can be set uniformly through Table's loadingSpinnerSize.

Spinner body is created internally by TableBody, and does not require pages to be handwritten in Demo or business templates. The page provides real request functions, and select the manual button to call DataTableRenderState.loadMore() or declare loadMoreMode="auto"; DataTable is internally responsible for automatic observation, request throttling, concurrent protection, merging data one by one, hasMore, Spinner timing and new rows.

The automatic loading of DataTable is responsible for its internal table tail sentinel. The page only needs to declare loadMoreMode="auto" and the data source; by default, the bottom of the table needs to cross the bottom of the nearest vertical scrolling area, and then continue to roll down 80px to trigger, with continuous requests at least 500ms intervals. Table / DataTable still does not create a vertical scrolling container, nor does it change the vertical scrolling attribution of the outer ScrollArea or page.

DataTable submits a visible row every time it receives a piece of data, and allows the ordinary TableCell of the corresponding row to enter the Frame Appear state through Table Context, explicitly executing pure opacity: 0 → 1 dynamic effect, without generating size scaling. The selection / actions role Cell does not consume the internal dynamic effect, so as to avoid the row-level opacity multiplied by the control's own hover opacity, causing the Checkbox / actions to be temporarily invisible. The Spinner is immediately hidden when the first new line begins to appear; the subsequent data appears one by one according to the display interval of the internal configuration of DataTable, and each action effect overlaps with each other. When the display interval is 0, the same batch of local data is submitted in the same round of updates. TableRow / TableCell explicitly passed whileAppear still takes precedence over internal kinetic effects.

At the first start of incremental loading, Table will measure the natural width of the ordinary data column of the current header before requesting data submission, and lock the columns that have not been explicitly set by columnWidths to this width. The wider content in the subsequent new rows is only truncated within the existing column width, and the native table-layout:auto is no longer allowed to redistribute all column widths and drive the existing rows to move left and right. Automatic locking is performed only once and maintained until the current Table is destroyed; the external columnWidths and the user's dragging column width always take priority.

Role column layout: the default roleLayout="auto" is determined by permanent or floating layer according to the width. When explicitly roleLayout="column", selection/actions participates in the column width of the table as an ordinary narrow column; when roleLayout="overlay", the role cell still retains the legal table DOM, but its own width is zero and sticky to the left and right edges of the table, and the content floats above the table row with the overlay block. The cover block uses horizontal overlapping blur strip in the opposite left and right directions to soften the rear content: selection is transparent from left to right, actions are transparent from right to left; blur layer is permanent, and the control itself fades in and out independently to avoid rebuilding the blur layer when hovering.

Selection and overlay layout in DataTable

This section covers behavior coordinated by DataTable. Set roleOverlayLayers, roleOverlayBlurMode, roleOverlayUniformFeather, and selectedRowIds on the outer DataTable. Explicit Table roleLayout and horizontalScroll take precedence.

The data line selection of roleLayout="overlay" adopts a two-layer structure of "legal table cell + fixed cover block":

  • TableCell as="selection" still renders the real <td>. The width, minimum width and maximum width of the <td> are all zero in overlay mode, and sticky to the left, which only exists as a legal table DOM and positioning anchor.

  • The .snowui-table-selection-control inside the cell reads the screen position of the current tr through getBoundingClientRect(), and synchronizes as position: fixed when scroll / resize / row resize. The selection overlay block is fixed to the left side of the row. The width is --size-8 (32px), and the height is equal to the height of the current line. z-index is set to the highest layer to ensure that it is pressed above the real content of the first column.

  • Checkbox and .snowui-table-role-blur-layer are in the same .snowui-table-selection-control container. Checkbox is kept at the top layer as a real interactive control; blur layer uses aria-hidden and pointer-events: none, which only assumes visual effects and does not participate in click hits.

  • Progressive blur uses components/src/lib/progressive-blur.ts. Selection blurs most strongly at the left and clears to the right; actions reverse the direction. Table Demo adjusts maximum blur radius and visible width through --snowui-table-role-overlay-blur-override and --snowui-table-role-overlay-width-override.

  • DataTable controls blur layer count and mode with roleOverlayLayers and roleOverlayBlurMode, passing both through Table context to selection and action cells in the header and body. More layers smooth the progressive blur. roleOverlayBlurMode="uniform" uses createUniformBlurStyles for a single fixed-intensity backdrop blur; roleOverlayUniformFeather (0–1) can mask its inner edge to soften the boundary.

  • The blur layer’s tint is white (white/100%), with opacity from --snowui-table-role-overlay-tint-opacity-override (default 0%). At 0%, only backdrop-filter blurs the backdrop; at 100%, the layer is opaque white.

  • DataTable has selectedRowIds and clear selection capabilities, and is shared through Context for the built-in TableToolbar to automatically display batch operations; the page does not need to repeatedly pass selectedCount / onClearSelection.

  • .snowui-table-role-blur-layer is hidden by default, and is only displayed when the line hovers, focus-within or is selected. In this way, the non-interactive state will not draw additional blur, and the checkbox and blur state remain visible after selection.

  • Do not push the content of the first column through padding; selection must be overwritten above the first column. If the user additionally enhances z-index on the content of the cell, it will cause the content of the first column to overpress Checkbox and blur, destroying the overlay semantics.

Interaction hits are processed according to priority:

  • When clicking the checkbox body, the onCheckedChange of Checkbox updates the current row selection state and prevents events from bubbling to TableRow to avoid double switching.

  • Because the overlay checkbox visually overlaps with the content of the first column, TableRow will judge the click of the 32px area on the left side of the row; even if the browser hits the link of the first column below the bottom, it will preventDefault() and switch the current row selection state.

  • Clicking on the real interactive content in the cell (a, button, input, label, select, textarea, [role="button"], [role="checkbox"]) will not trigger the line selection.

  • Clicking the non-interactive blank area in the line will switch the current line selection state; click again to unselect.

Select attribution: DataTable holds selectedRowIds, and TableRow registers the current rendering line with rowId. The full selection of the header only affects the currently rendered row (the paging scene is the current page), and the cross-page selected id will be retained.

The header select-all Checkbox is always visible in a persistent role column. In overlay layout it appears only when: (1) any data row is hovered (.snowui-table-viewport:has(.snowui-table-body .snowui-table-row:hover)), alongside row Checkboxes; (2) the first ordinary header next to the selection overlay is hovered (.snowui-table-head[data-as="selection"] + .snowui-table-head:hover); (3) the select-all overlay itself is hovered or keyboard-focused, so moving the pointer from a row leaves it usable; or (4) the table has a selected row (data-selected="true"). Hovering other headers does not show it. The overlay container always has pointer-events:none; only its Checkbox receives pointer-events:auto when shown.

Overlay hover edge progressive transparency (built-in ability)

Under roleLayout="overlay", TableCell / TableHead has a built-in set of hover edge progressive transparency: use CSS mask-image gradient to directly act on the cell content, so that the checkbox / operation button overwrite the block the content directly below is gradually hidden from the control side to clear , so as to ensure that the controls floating above the content are clearly readable. This ability is the inherent behavior of the table, the parameters are fixed, and there is no external switch.

Rules:

  • Trigger timing: The content of the data line fades when the row hovers(.snowui-table-row:hover); the header only the fading of the first column title (the Date column adjacent to the selection overlay block) is exactly the same as the appearance of time of all-selected Checkbox** - that is, hover will only disappear when there is an arbitrary data line, hover the header, hover/focus on all-select floating layer itself, or when there is a selection state; the fully selected Checkbox does not appear when the header is not appear. The rest of the table header columns (including the actions side) do not fade away.

  • Objects:

    • Checkbox side = adjacent to the content cell of the selection overlay block ([data-as="selection"] + .snowui-table-cell's .snowui-table-cell-content), direction to right.

    • Actions one side = actions overwrite the ordinary content cell before the block, direction to left. All content takes the right edge of the current visible line as the same coordinate origin, and remains continuously faded across columns; after horizontal scrolling, the floating layer is still limited to the Table viewport. When selection and actions act on a content block at the same time, use the intersection to keep the mask on both sides.

  • Parameters (can be overridden separately, the three sets are independent of each other): Each set of Fade start / Fade end is exposed as a CSS overlay variable, and the default value is the same as below; it can be set separately on <Table> or style of any ancestor container.

    • The first column of the header: --snowui-table-head-fade-start-override (default actual Checkbox right edge) → --snowui-table-head-fade-end-override (default right edge + --size-5), the transition does not change with the column width.

    • Checkbox side: --snowui-table-election-fade-start-override (default actual Checkbox right edge) → --snowui-table-election-fade-end-override (default right edge + --size-5), the transition does not change with the column width.

    • Actions one side: the completely transparent area is covered by default to the actual left edge of the leftmost button (the width of the measured button group includes the inner margin on the right side, and the coverage defaults to 1). Transition from the edge to clear with a fixed length of --size-5 (nominal 20px) to the left, without changing with the width of the button group, the number of buttons or responsive padding; scale with the global Token. --snowui-table-actions-fade-coverage-override can still explicitly adjust the coverage ratio; --snowui-table-actions-fade-feather-override is not set by default, only compatible with the multiple semantics explicitly set by the old call method. At this time, the transition end point is still the width of the transparent area multiplied by this multiple.

The three gradually disappearing mask-image are reused. The basic sharing ability edge-fade (source code reference: components/src/lib/edge-fade.md) (createEdgeFadeMaskImage) is generated and stored in CSS variables, and the hover state rules of TableCell / TableHead only mask-image: var(...) Consumption. Selection / head adapts table-selection-fade.ts through private layout to measure the right edge of the actual Checkbox and generate a mask in the content node; actions mask depends on the width of the actual measurement button per line, so it is generated by TableCell of each ordinary content in its own scope, and subtract the offset from the right edge of the content block from the right edge of the visible row to ensure that the row-level --snowui-table-role-overlay-content-width can be read. The above *-override variables are the configurable parameters exposed to the table by the ability. " The positioning of the "floating operation layer" itself (sticky / fixed + JS measurement) belongs to the table layout responsibility and is not within the scope of general ability.

  • Exit synchronization: When hover ends and the operation menu is not unfolded, the entire floating layer of actions is immediately hidden, and the synchronization is canceled with the content mask to avoid leaving afterglow of the fade-out button or blur layer; the gradual appearance remains unchanged when entering.

  • It does not affect the click: mask only changes the visibility, not the hit test; the links, buttons, etc. in the faded content can still be clicked normally.

  • Relationship with blur: Edge fading and .snowui-table-role-blur-layer background blur are two independent mechanisms. When you only need to keep the fade, set --snowui-table-role-overlay-blur-override to 0rem and turn off the background blur.

  • Active row: The caller or external state keeps <TableRow active> set, drawing a persistent --black-4 background. This differs from hover and selection and does not change Checkbox state. Hovering an active row overlays the moving hover layer.

  • Static hover preview: Add data-force-hover="true" on a <TableRow> to make the line constantly present the hover state without actual hover (background / line checkbox / action button / fade on both sides / header full selection and header fade will be triggered by this line), which is used for document screenshots and visual checks; business persistence should use active Prop.

The implementation entrance is TableCell.svelte (source code reference: components/src/components/TableCell.svelte) and TableHead.svelte (source code reference: components/src/components/TableHead.svelte). TableCell reads the content coordinates in the existing positioning batch of the activated row, and does not create a new Observer for each content column. For each ordinary content block, the two color marks of the actions mask are fade-width − edge-offset and fade-width + fixed transition length − edge-offset respectively; negative color marks are allowed to keep the columns away from the operation area clear. TableCell synthesizes the two-layer mask of selection and actions into mask-composite: intersect, and the role control itself does not participate in the content mask.

Scrolling attribution: Table creates a unique local horizontal viewport by itself, and shares the same horizontal track sticky to the bottom of the current page viewport by sharing useOverlayScrollbar. The track is only displayed when the inherent minimum width of the table exceeds the host, and the table withdraws the table boundary after leaving the viewport or reaching the bottom. Do not spread the width of the wide table to the minimum width of the page, do not wrap the Table with the outer ScrollArea, and do not create a second synchronous scroll bar. minWidth can still further expand the inherent width of the table. Table / DataTable still does not create vertical scrolling containers. The bottom track must be higher than the table content layer; even if TableBody continuously improves the table to the content layer by default, the track still receives hover, pointer down and drag completely, and must not be intercepted by the data line below it. The continuous Hover layer is carried by a local horizontal viewport, and its background is only drawn within the range of the currently visible table, and the background corresponding to the hidden column must not be leaked outside the viewport.

Give a demonstration

<script lang="ts">  import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '@snowui-design-system/components';  let columnWidths = $state<Record<string, number>>({});</script> <Table bind:columnWidths minWidth={600}>    <TableHeader><TableRow><TableHead columnId="name">Name</TableHead></TableRow></TableHeader>    <TableBody><TableRow rowId="one"><TableCell columnId="name">A very long name</TableCell></TableRow></TableBody></Table>

TableCell defaults to lines={1}, and the original text does not need to be wrapped in a layer of Text. When hovering, the first and last cells will automatically form 12px rounded corners.

Keyword

Keyword Description
component Current public component contract
  • Maintain a legitimate table DOM tree and do not use div simulation grids.

  • The sorting status is provided by the upper DataTable through the shared context.

  • Column width persistence belongs to the page layer, and Table only makes changes.

Responsive contraction and recovery

Responsive column stay recovery: After the width 1s no longer changes, the column still displayed restores its original transparency (including the default weakened transparency of the header), and the displacement is completed naturally. Narrow again from the current transparency, and the columns that have been closed are kept hidden; DataTable reuses the same rules.

Fading computing and OverflowActions share responsive-exit (source code reference: components/src/lib/responsive-exit.md), and the unified dynamic boundary can be found in the responsive project (source code reference: specs/maintainers/MotionPresetSpec.md).

Table is the only layout calculation entrance of Table / DataTable. According to the available width and actual column content of its own container, it does not use device breakpoints.

  1. roleLayout="auto": When all the content and the preferred spacing are put down, Checkbox / actions occupy the resident column and are always displayed; first, it is collected as a hover / keyboard focus floating layer, and the role column is not deleted. Checkbox has been selected, and the expanded operation menu continues to be visible.

  2. Re-compress the left and right padding of the cell: by default, each side is received from --padding-3 (12px) to --padding-1 (4px), and the minimum visual spacing of adjacent columns is 8px; the outer padding of the leftmost/rightmost visible cell and character floating layer is not lower than --padding-2(8px). The font size, icon, line height and internal gap of the cell are not reduced. The explicit padding override is reserved. The permanent operation column will reserve the width for the actual button content; the explicit columnWidths.__actions still takes precedence, and the column width of the column is automatically measured without writing back.

  3. horizontalScroll default true: keep all ordinary columns when there is still not enough space, and use Table to scroll horizontally locally.

  4. horizontalScroll={false}: Ordinary columns are allowed to be hidden by default, and they are retracted from right to left according to the current DOM order; the columns of TableHead responsiveHide={false} and the first ordinary column are always retained. The role column does not participate in hiding. The next column to be hidden is linearly faded in the container width interval of --size-5 (nominal 20px) before the threshold. Only the header fades synchronously with the cell content, and the background and demitor are always intact. After crossing the threshold, the native grid directly determines the target layout. The content layer uses the shared resize preset (currently 250ms) transition position and gradually reveals the expanded content area without scaling the text. The background, separation line and rounded corners do not participate in interpolation, and do not temporarily switch the table-layout or compress the last column to zero width. When dragging continuously, the content will gradually restore according to the current width; the rules for staying and restoring are shown below. The bit movement picture is only started when the visible column collection changes; continuous dragging in the same set does not restart the animation, and does not interpolate the vertical position generated by line changes. Take over from the current display position and crop boundary when quickly crossing the column threshold in reverse. The first column, protection column, role column and merged cells do not participate in fading; prefers-reduced-motion: reduce reserve direct switching.

  5. When the last column is still not available, if there is no hard-sized ordinary text column, it is limited to container width: nowrap content should not break lines and display ellipsis, and the default Tooltip provides the full text (including lines={false} nowrap); the content of new lines is allowed to be folded, and long continuous strings can also be broken. The original text and data remain unchanged, and the natural layout is restored after widening. The explicit tooltip={false} can still turn off Tooltip. Multiple protection columns, explicit column width / minWidth, complex merge grid or buttons in a single column, input, pictures and other incompressible controls still use horizontal scrolling to the bottom, and the operation is not cut off. The container is too narrow to accommodate both sides of 8px. When leaving white, the scrolling is also retained. Turning off horizontal scrolling represents priority to receive columns and text adaptation, and does not force hidden inevitable overflows.

  6. The Head / Cell of the hidden column exits the layout, keyboard sequence and auxiliary technology reading together, but the data, sorting and selection status remain unchanged. Finally, it can be seen that the ordinary column takes over the right rounded corner; when there is only one column, it has the left and right rounded corners at the same time.

Multi-row or cross-list header and cross-row data cells maintain horizontal scrolling, and do not guess the column correspondence of the merged grid; the cross-column empty / Spinner cell of the ordinary table body updates the span according to the number of visible columns.

  1. As width returns, restore ordinary columns first, then padding, then role columns to persistent layout. Hidden columns recover using their original unhidden content measurements to avoid oscillation. Recalculate when data, column widths, fonts, or tokens change.

The configuration of DataTable is issued by Context; explicit Table configuration takes precedence. Ordinary Table Reuses Spacing, Hiding And Scrolling Rules, And Does Not Add Select/Operation Status. The old explicit roleLayout="column" / "overlay" retains the fixed layout meaning; column now permanently displays the role control.

Action role budget

DataTable action columns use the minimum of 20% of the local viewport, 14rem, and an explicit or dragged column width. Actions overflow before the existing role-column, padding, and data-column rules run. Padding and the overlay fade footprint count toward the budget. More keeps its usable minimum size; very narrow tables scroll locally. Layout freezes while the menu is open and updates on close. Shared observation and font or token changes trigger measurement without adding per-row ResizeObservers.

Table style overlay

Read the full LICENSE first; reuse that review for the same task, version, and scope.

First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.

Variable Purpose and default reference
--snowui-table-font-size-override default: --text-12
--snowui-table-line-height-override default: --leading-12

Design Guide · Token · Combination boundary

Table type and status

Required Props: no named required Props.

Two-way binding: bind:columnWidths.

Inheritance: Omit<FrameProps, "children">. Consult the base class public documentation; fields excluded by Omit cannot be passed through unchanged.

Share Frame API · Return API

The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.

TableRoleLayout

Source: components/src/lib/table-context.svelte.ts

export type TableRoleLayout = "auto" | "column" | "overlay";

ResourceSize

Source: components/src/context.ts

export type ResourceSize = 12 | 16 | 20 | 24 | 28 | 32 | 40 | 48 | 80;