Header
comins-table@0.2.2
Playground paths below are local routes for the module repository’s development server. They are not live routes on this documentation site.
Starting with 0.2.2, .render is the standard UI customization entry point. Legacy properties remain supported throughout 0.x, with removal targeted for 1.0.0. See the migration rules.
Columns can enable sorting, width constraints, resizing, and custom header content.
const columns: Array<CominsTableColumn<PersonRow>> = [ { field: "name", id: "name", label: "Name", sort: true, width: 160 }, { field: "age", id: "age", label: "Age", sort: true, width: 120 },];Use onChangeSort to observe the primary sort rule and onChangeColumnLayout for width, order, and visibility persistence.
Multi-column sort
Section titled “Multi-column sort”Single-column sorting remains the default. Enable ordered multi-column sorting explicitly with multiSort and observe the complete model through onChangeSortModel.
const [sortModel, setSortModel] = useState<CominsSortModel>([]);const tableRef = useRef<CominsTableRef<PersonRow>>(null);
<CominsTable ref={tableRef} columns={columns} data={rows} multiSort onChangeSortModel={setSortModel}/>
tableRef.current?.setSortModel([ { columnId: "department", direction: "asc" }, { columnId: "salary", direction: "desc" },]);- A normal click or
Enter/Spacekeeps the existing single-columnnone -> asc -> desc -> nonecycle. Shiftplus click orEnter/Spaceappends a new ascending rule, updates an existing rule in place, or removes its descending rule.- Header badges show the 1-based comparison priority. Removing a rule compacts the remaining priorities.
- The sort indicator uses state-specific decorative Radix SVG icons (
aria-hidden="true") forasc,desc, and unsorted states. The Header keeps the existing click andEnter/Spacekeyboard cycle and continues to exposearia-sort. getSortModel()andsetSortModel(model)read and restore the full ordered model.getSortState()andsetSortState(rule)remain available for one-rule compatibility;setSortStatereplaces the full model.clearSort()clears every rule.onChangeSortcontinues to observe the first rule, whileonChangeSortModelobserves the complete model.- Hidden sortable Columns keep their rules. Removed or non-sortable Columns are removed from the model.
- Two-level parent Group Headers are not sortable. Their sortable child Columns participate normally.
- Tree Grid applies the same ordered comparator to each sibling set without flattening parents and descendants together.
During multi-sort only the first rule exposes aria-sort="ascending" or "descending". Secondary Headers include an accessible priority description because ARIA does not provide a native multi-key priority attribute.
The live /api/ref (/api/ref) example applies setSortModel, clearSort, getColumnLayout, and setColumnLayout against a Flat Table. Layout methods preserve current Column order, visibility, and width.
Column reorder
Section titled “Column reorder”- A left-button mouse interaction activates column reorder at a 6-pixel horizontal drag threshold. Horizontal movement must be greater than vertical movement.
- Pointer Up below the threshold preserves the normal click and sort behavior. Vertical intent cancels both the pending reorder and sort.
- After activation, the source Header becomes a darker dashed source placeholder that keeps its plain Column or Group name visible while a ghost and target marker show the pending move. This presentation-only source label does not invoke custom Header renderers.
- A 24px move handle with a 15px decorative Radix SVG icon (
aria-hidden="true") appears at the left by default and activates immediately. The whole Header retains the 6-pixel gesture. SetshowColumnMoveHandle={false}to hide handles without removing that existing gesture. - Set
lockPosition: trueon a Column or Group to keep its position fixed. A locked Header has no handle, cannot be moved, and prevents another move from crossing or shifting its position. - A valid same-depth target uses a blue two-pixel border, blue marker, and low-alpha blue background. A different-depth, cross-parent, or position-locked target uses the corresponding red treatment with a
not-allowedcursor and cannot commit. Content opacity is unchanged. - A committed move animates Header, rendered body cells, and Summary cells to their new horizontal positions.
prefers-reduced-motion: reducedisables the transition. - The built-in Header control contract uses an 88px default minimum Column width. Labels may truncate; custom Header content that needs more room should set a larger
minWidth. - A move commits only on Pointer Up over a valid target. Pointer cancellation,
Escape, or window blur cancels it without changing the layout. - For non-mouse pointer input, one-second long-press compatibility is retained.
- Parent groups use the same interaction and move all child columns as one block.
Two-level headers use columnGroups.
<CominsTable columns={columns} columnGroups={[ { id: "profile", label: "Profile", children: ["name", "age"], lockPosition: true }, ]} data={data}/>Parent groups resize their child columns proportionally and move as a block. Nested groups are not part of the first public release.
Column Filter
Section titled “Column Filter”Set columns[].filter and provide controlled columnFiltering state to render the Filter control at the Header’s right edge after sort metadata and before resize. The semantic button and fixed popover isolate pointer, click, double-click, and keyboard events from Header sort, resize, and move interactions. The application owns both the complete Filter model and the currently open Column ID.
See the Column Filtering guide and run the /examples/column-filtering (/examples/column-filtering) Playground route for supported operators, read-only behavior, sorting, Summary, and Row Grouping integration.
In the Playground, parent Group visibility uses independent Checkboxes while child Column visibility uses the MultiSelect. Turning a parent off hides all of its children without deleting the child selection; turning it on restores the previously selected children.