TableHead handbook
v2.4.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
Define Table column headers, with optional sorting and column resizing to help users understand and organize data.
When to use it
Use it for header cells in Table or DataTable. DataTable coordinates data sorting; resizing and sorting are separate capabilities, so resizable does not imply sortable.
columnIdidentifies the column;resizablecontrols width adjustment. IndependentsortDirectionandonSortChangeexpress sorting state.The selection role uses DataTable’s select-all control.
partsconfigures generated Indicator and Checkbox; configure an explicit title directly.
Quick start
This example shows the recommended basic composition. See the sections below for more cases and composition limits.
API
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
Icon and component title
Table and DataTable share TableHead. children is the title slot; no extra icon or header Prop is needed. Resource icons, Icons, Chips, or custom display components participate in native width measurement, alignment, and responsive column collection. Static titles use inline boxes; block-level content and built-in sort buttons follow the column alignment too.
An icon-only title needs an accessible name. label names the column in the TableToolbar sorting list and its column-width handle; it does not automatically name the header or sort button. Give the icon role="img" and aria-label so its title and enclosing sort button are meaningful. Sortable content is placed inside the built-in button, so use only noninteractive children; do not nest links, buttons, or inputs. Selection headers use the built-in select-all Checkbox.
Generated component configuration
parts.Indicatorconfigures the generated resize Indicator.parts.Checkboxconfigures the selection header’s select-all Checkbox.Sorting, selection, and resize events remain owned by TableHead and cannot be overridden through
parts.
Sort state maps to aria-sort. Only the default direction of the DataTable defaultSort column omits the active state and icon, unless defaultSortActive is enabled. Other sorted states show an icon. Following numeric direction, ascending (A→Z, 0→9, early→late) shows ArrowsUp; descending shows ArrowsDown. The icon is nominally 16px and stays at least 4 CSS px from title content as root font or gap scale shrinks. The icon does not shrink, and the title retains its one-line truncation.
Interactive cycle:
defaultSorthit column: default direction (no icon) → reverse (with icon) → default direction (no icon).Other columns: no sorting → ascending (ArrowsUp) → descending (ArrowsDown) → no sorting.
Sortable headers follow the shared colorless text/Icon hover rule: keep Black/100% as the source and raise opacity from 0.4 to 1. Hover, keyboard focus, and active sort use opacity 1, matching the icon and text. Unsortable columns render no button or hover/click state.
No sortable Prop is needed. DataTable infers sortability from the matching raw row field or sorters[columnId]. Standalone TableHead enables sorting when sortDirection or onSortChange is declared. Columns without sorting rules render no button.
Ordinary Table columns do not resize by default; pass resizable to TableHead to enable it. DataTable ordinary columns with columnId resize by default; pass resizable={false} to disable. as="selection" and as="actions" role columns never resize. Use resizable={false} for a fixed-width column. Headers and TableCells share responsive horizontal padding from 4px to 12px; a narrow screen commonly uses 4px per side for at least 8px between adjacent columns, with 8px vertical padding. First and last visible cells and role overlays retain at least 8px toward the outer edge.
Without a fixed column width, the header’s unwrapped min-content participates in Table auto sizing alongside same-column TableCells. A narrow host therefore does not break titles letter by letter. Explicit columnWidths, drag widths, and other fixed widths take precedence; overflow titles still use the header truncation rule.
Without defaultSort, TableHead does not treat the first column as implicitly sorted. When no column has active sorting, DataTable preserves the order of rows or filteredRows supplied by the parent.
Double-click the resize handle
Double-clicking Indicator on a default single-line column fits the widest currently rendered cell and header content, including icons, gaps, padding, and sort-icon space. It does not scan unloaded server data.
If any same-column cell has explicit
nowrap={false}, double-click restores the width from before the first drag. Prefer externalcolumnWidthsfor that baseline; otherwise use the measured initial layout width to avoid unbounded growth from long text.Clamp the result to
minWidth/maxWidthand preserve other columns. UpdatecolumnWidthsbinding and callback; Table may scroll horizontally if needed.Double-click does not sort and is unavailable with
resizable={false}. Repeat double-click to measure current-page content again. Row changes retain the same initial baseline until Table remounts.
Role column
as="selection"renders the built-in select-all Checkbox. Its resident role-column layout always shows it; in overlay mode it appears on first-header hover, direct hover, or keyboard focus. Partial selection uses indeterminate. Table responsive rules set horizontal padding.as="actions"has no title or business button by default. Pass children for a custom title. Table responsive rules set horizontal padding.roleLayout="overlay"gives role headers zero width and sticks them to the left or right edge. Selection Checkbox and any actions title use responsive horizontal padding. Real first and last header cells keep square corners; floating controls may use a 12px radius. The control overlay defaults to one-third of its original width. Its blur layer starts hidden and becomes visible on header hover, using shared Progressive Blur fromcomponents/src/lib/progressive-blur.tsand a segmented mask. Selection fades from strong left to clear right; actions reverse that direction.The first real title behind a selection overlay starts its transparent region at the Checkbox’s actual right edge, then fades over
--size-5(20px nominally) to the right, matching row Checkbox/button columns. Override with--snowui-table-head-fade-start-overrideand--snowui-table-head-fade-end-override.The overlay select-all Checkbox appears progressively. When pointer leaves the header and control with no keyboard focus inside, remove it in the same frame as the title mask to avoid an afterglow. Preserve focusable DOM without visibility hiding so keyboard access remains possible.
Both roles use explicit combination contracts and do not guess the column identity through DOM scanning.
Each TableHead registers its public column structure (columnId, selection/actions role, and alignment) with the nearest Table Context. TableBody uses this order to generate Skeleton rows on first load. Registration does not expose or scan TableHead’s private DOM.
Only data headers adjacent to selection/actions role columns include fade sampling layout boxes. Other columns omit them so incremental loading does not lock width or create horizontal scroll from invisible masks. Sampling width comes from the role overlay width, not ordinary data-column width.
Sort value type inference
TableHead does not declare a content type or expose sortType="text | number | date". DataTable compares raw row fields:
Datevalues compare by timestamp.numbervalues compare numerically, so Unix timestamps sort in time order.ISO 8601 date-time strings with time zones are converted to timestamps before comparison.
Other strings use localized, case-insensitive natural order with numeric segments.
For derived display values, DataTable
sorters[columnId]returns a comparable raw value.
This prevents formatted text such as Just now or $1,299 from driving sort order and avoids redeclaring types already known to the data layer.
Default sorting declaration
The default sorting is directly declared by the corresponding column header:
One DataTable may have only one TableHead declaring defaultSort. It takes precedence over the legacy DataTable-level defaultSort={{ columnId, direction }} object, retained for compatibility.
In the default direction, the column normally has no active styling and cycles “default → reverse → default.” To show that state as active:
defaultSortActive changes behavior as well as appearance: “default (active) → reverse (active) → unsorted → default (active).”
Keyword
Table context coordinates sorting and column width; the component does not store application state.
In DataTable, Context
isSelectionEnabled/isActionsEnabledcontrols whetheras="selection"/as="actions"columns render at all.Default font weight is 400; font size and line height use
--text-12and--leading-12.All header cells and data rows use the same responsive left and right padding, ranging from 4px to 12px.
resizableuses shared Indicator. Its hit strip spans the full header-cell right edge; the visible Indicator is 2px × 16px normally and 4px thick on hover. The entire edge can start a drag.
TableHead 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.
TableHead Type and Status
Required Props: no named required Props.
Bindable Props: this component declares no named two-way binding; handle state updates through public callbacks or its host.
Inheritance: Omit<FrameProps, "children">. Consult the base class public documentation; fields excluded by Omit cannot be passed through unchanged.
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
ComponentPartsOf
Source: components/src/logic/component-parts.svelte.ts
ConfigurableComponentPartProps
Source: components/src/logic/component-parts.svelte.ts
ComponentPartControlledKey
Source: components/src/logic/component-parts.svelte.ts