Documentation
Collapsible Columns
Hide and show column groups to save space — click the header arrow to collapse or expand.
Enable collapsible groups
Set collapsible: true on a parent with children. Users click the header arrow to hide or show the group.
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "q1", label: "Q1", width: 90, type: "number" },{ accessor: "q2", label: "Q2", width: 90, type: "number" },{ accessor: "q3", label: "Q3", width: 90, type: "number" },{ accessor: "q4", label: "Q4", width: 90, type: "number" },],}
Start collapsed
Use collapseDefault so the group loads collapsed — useful when details should stay optional.
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
TypeScript
Copy
{accessor: "details",label: "Details",collapsible: true,collapseDefault: true,children: [{ accessor: "note", label: "Note", width: 160 },{ accessor: "owner", label: "Owner", width: 120 },],}
Control child visibility
Use showWhen on child columns: parentExpanded (default), parentCollapsed, or always. Common pattern: summary when collapsed, detail when expanded.
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
TypeScript
Copy
{accessor: "sales",label: "Sales",collapsible: true,children: [{ accessor: "total", label: "Total", showWhen: "parentCollapsed" },{ accessor: "q1", label: "Q1", showWhen: "parentExpanded" },{ accessor: "q2", label: "Q2", showWhen: "parentExpanded" },],}
Single-row children
Set singleRowChildren: true so the parent header sits beside its children (same row) instead of above them — the parent acts like a column that collapses its neighbors.
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
TypeScript
Copy
{accessor: "personalInfo",label: "Personal Info",collapsible: true,singleRowChildren: true,children: [{ accessor: "firstName", label: "First Name", width: 120 },{ accessor: "lastName", label: "Last Name", width: 120 },{ accessor: "email", label: "Email", width: 200 },],}
Example
React TSX
Copy
1import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";2import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";3import "@simple-table/react/styles.css";45const CollapsibleColumnsDemo = ({6 height = "400px",7 theme,8}: {9 height?: string | number;10 theme?: Theme;11}) => {12 return (13 <SimpleTable14 columns={collapsibleColumnsConfig.headers}15 rows={collapsibleColumnsConfig.rows}16 columnResizing17 enableColumnEditor18 selectableCells19 columnReordering20 height={height}21 theme={theme}22 />23 );24};2526export default CollapsibleColumnsDemo;
Vue SFC
Copy
1<template>2 <SimpleTable3 :columns="collapsibleColumnsConfig.headers"4 :rows="collapsibleColumnsConfig.rows"5 :column-resizing="true"6 :enable-column-editor="true"7 :selectable-cells="true"8 :column-reordering="true"9 :height="height"10 :theme="theme"11 />12</template>1314<script setup lang="ts">15import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";16import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";17import "@simple-table/vue/styles.css";1819withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {20 height: "400px",21});22</script>
Angularcollapsible-columns-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, Row, Theme } from "@simple-table/angular";3import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";4import "@simple-table/angular/styles.css";56@Component({7 selector: "collapsible-columns-demo",8 standalone: true,9 imports: [SimpleTableComponent],10 template: `11 <simple-table12 [rows]="rows"13 [columns]="headers"14 [columnResizing]="true"15 [enableColumnEditor]="true"16 [selectableCells]="true"17 [columnReordering]="true"18 [height]="height"19 [theme]="theme"20 ></simple-table>21 `,22})23export class CollapsibleColumnsDemoComponent {24 @Input() height: string | number = "400px";25 @Input() theme?: Theme;2627 readonly rows: Row[] = collapsibleColumnsConfig.rows;28 readonly headers: AngularColumnDef[] = collapsibleColumnsConfig.headers;29}303132// collapsible-columns.demo-data.ts33// Self-contained demo table setup for this example.34import type { AngularColumnDef } from "@simple-table/angular";353637export const collapsibleColumnsData = [38 { id: 1, name: "Alice Thompson", region: "North America", q1Sales: 245000, q2Sales: 289000, q3Sales: 312000, q4Sales: 298000, totalSales: 1144000, avgQuarterly: 286000, jan: 78000, feb: 82000, mar: 85000, apr: 89000, may: 95000, jun: 105000, jul: 98000, aug: 102000, sep: 112000, oct: 108000, nov: 95000, dec: 95000, avgMonthly: 95333, bestMonth: 112000, softwareSales: 456000, hardwareSales: 342000, servicesSales: 346000, topCategory: "Software", categoryCount: 3 },39 { id: 2, name: "Marcus Chen", region: "Asia Pacific", q1Sales: 189000, q2Sales: 234000, q3Sales: 287000, q4Sales: 276000, totalSales: 986000, avgQuarterly: 246500, jan: 58000, feb: 62000, mar: 69000, apr: 72000, may: 78000, jun: 84000, jul: 89000, aug: 95000, sep: 103000, oct: 98000, nov: 89000, dec: 89000, avgMonthly: 82166, bestMonth: 103000, softwareSales: 398000, hardwareSales: 298000, servicesSales: 290000, topCategory: "Software", categoryCount: 3 },40 { id: 3, name: "Sofia Rodriguez", region: "Europe", q1Sales: 198000, q2Sales: 245000, q3Sales: 267000, q4Sales: 289000, totalSales: 999000, avgQuarterly: 249750, jan: 62000, feb: 66000, mar: 70000, apr: 78000, may: 82000, jun: 85000, jul: 85000, aug: 88000, sep: 94000, oct: 96000, nov: 97000, dec: 96000, avgMonthly: 83250, bestMonth: 97000, softwareSales: 389000, hardwareSales: 312000, servicesSales: 298000, topCategory: "Software", categoryCount: 3 },41 { id: 4, name: "David Kim", region: "North America", q1Sales: 167000, q2Sales: 198000, q3Sales: 234000, q4Sales: 267000, totalSales: 866000, avgQuarterly: 216500, jan: 52000, feb: 55000, mar: 60000, apr: 63000, may: 66000, jun: 69000, jul: 75000, aug: 78000, sep: 81000, oct: 87000, nov: 89000, dec: 91000, avgMonthly: 72166, bestMonth: 91000, softwareSales: 346000, hardwareSales: 267000, servicesSales: 253000, topCategory: "Software", categoryCount: 3 },42 { id: 5, name: "Emma Wilson", region: "Australia", q1Sales: 134000, q2Sales: 167000, q3Sales: 198000, q4Sales: 234000, totalSales: 733000, avgQuarterly: 183250, jan: 42000, feb: 45000, mar: 47000, apr: 52000, may: 55000, jun: 60000, jul: 63000, aug: 66000, sep: 69000, oct: 75000, nov: 78000, dec: 81000, avgMonthly: 61083, bestMonth: 81000, softwareSales: 293000, hardwareSales: 220000, servicesSales: 220000, topCategory: "Software", categoryCount: 3 },43 { id: 6, name: "James Anderson", region: "South America", q1Sales: 156000, q2Sales: 178000, q3Sales: 201000, q4Sales: 223000, totalSales: 758000, avgQuarterly: 189500, jan: 48000, feb: 52000, mar: 56000, apr: 58000, may: 60000, jun: 60000, jul: 65000, aug: 67000, sep: 69000, oct: 72000, nov: 75000, dec: 76000, avgMonthly: 63166, bestMonth: 76000, softwareSales: 303000, hardwareSales: 227000, servicesSales: 228000, topCategory: "Software", categoryCount: 3 },44 { id: 7, name: "Lisa Chang", region: "Asia Pacific", q1Sales: 145000, q2Sales: 178000, q3Sales: 201000, q4Sales: 234000, totalSales: 758000, avgQuarterly: 189500, jan: 45000, feb: 48000, mar: 52000, apr: 58000, may: 60000, jun: 60000, jul: 65000, aug: 67000, sep: 69000, oct: 75000, nov: 78000, dec: 81000, avgMonthly: 63166, bestMonth: 81000, softwareSales: 303000, hardwareSales: 227000, servicesSales: 228000, topCategory: "Software", categoryCount: 3 },45 { id: 8, name: "Michael Brown", region: "Europe", q1Sales: 178000, q2Sales: 201000, q3Sales: 234000, q4Sales: 256000, totalSales: 869000, avgQuarterly: 217250, jan: 56000, feb: 60000, mar: 62000, apr: 65000, may: 67000, jun: 69000, jul: 75000, aug: 78000, sep: 81000, oct: 83000, nov: 86000, dec: 87000, avgMonthly: 72416, bestMonth: 87000, softwareSales: 347000, hardwareSales: 260000, servicesSales: 262000, topCategory: "Software", categoryCount: 3 },46 { id: 9, name: "Sarah Johnson", region: "North America", q1Sales: 201000, q2Sales: 234000, q3Sales: 267000, q4Sales: 289000, totalSales: 991000, avgQuarterly: 247750, jan: 63000, feb: 67000, mar: 71000, apr: 75000, may: 78000, jun: 81000, jul: 85000, aug: 89000, sep: 93000, oct: 95000, nov: 97000, dec: 97000, avgMonthly: 82583, bestMonth: 97000, softwareSales: 396000, hardwareSales: 297000, servicesSales: 298000, topCategory: "Software", categoryCount: 3 },47 { id: 10, name: "Robert Davis", region: "Australia", q1Sales: 123000, q2Sales: 145000, q3Sales: 167000, q4Sales: 189000, totalSales: 624000, avgQuarterly: 156000, jan: 38000, feb: 42000, mar: 43000, apr: 46000, may: 48000, jun: 51000, jul: 53000, aug: 56000, sep: 58000, oct: 60000, nov: 63000, dec: 66000, avgMonthly: 52000, bestMonth: 66000, softwareSales: 249000, hardwareSales: 187000, servicesSales: 188000, topCategory: "Software", categoryCount: 3 },48 { id: 11, name: "Jennifer Martinez", region: "South America", q1Sales: 134000, q2Sales: 156000, q3Sales: 178000, q4Sales: 201000, totalSales: 669000, avgQuarterly: 167250, jan: 42000, feb: 45000, mar: 47000, apr: 50000, may: 52000, jun: 54000, jul: 57000, aug: 59000, sep: 62000, oct: 65000, nov: 67000, dec: 69000, avgMonthly: 55750, bestMonth: 69000, softwareSales: 267000, hardwareSales: 201000, servicesSales: 201000, topCategory: "Software", categoryCount: 3 },49 { id: 12, name: "Christopher Lee", region: "Europe", q1Sales: 167000, q2Sales: 189000, q3Sales: 212000, q4Sales: 234000, totalSales: 802000, avgQuarterly: 200500, jan: 52000, feb: 55000, mar: 60000, apr: 61000, may: 63000, jun: 65000, jul: 68000, aug: 71000, sep: 73000, oct: 76000, nov: 78000, dec: 80000, avgMonthly: 66833, bestMonth: 80000, softwareSales: 320000, hardwareSales: 241000, servicesSales: 241000, topCategory: "Software", categoryCount: 3 },50];5152const fmt = (accessor: string) => ({ row }: { row: Record<string, unknown> }) =>53 `$${((row[accessor] as number) || 0).toLocaleString()}`;5455const monthCol = (accessor: string, label: string): AngularColumnDef => ({56 accessor,57 label,58 width: 100,59 showWhen: "parentExpanded" as const,60 sortable: true,61 align: "right",62 type: "number",63 cellRenderer: fmt(accessor),64});6566export const collapsibleColumnsHeaders: AngularColumnDef[] = [67 { accessor: "id", label: "ID", width: 60, sortable: true },68 { accessor: "name", label: "Sales Rep", minWidth: 150, width: "1fr", sortable: true },69 { accessor: "region", label: "Region", width: 140, sortable: true },70 {71 accessor: "quarterlySales",72 label: "Quarterly Sales",73 width: 500,74 collapsible: true,75 collapseDefault: true,76 children: [77 { accessor: "totalSales", label: "Total Sales", width: 140, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("totalSales") },78 { accessor: "q1Sales", label: "Q1", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q1Sales") },79 { accessor: "q2Sales", label: "Q2", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q2Sales") },80 { accessor: "q3Sales", label: "Q3", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q3Sales") },81 { accessor: "q4Sales", label: "Q4", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q4Sales") },82 ],83 },84 {85 accessor: "monthlyPerformance",86 label: "Monthly Performance",87 width: 800,88 collapsible: true,89 collapseDefault: true,90 children: [91 { accessor: "avgMonthly", label: "Avg Monthly", width: 130, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("avgMonthly") },92 { accessor: "bestMonth", label: "Best Month", width: 130, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("bestMonth") },93 monthCol("jan", "Jan"), monthCol("feb", "Feb"), monthCol("mar", "Mar"),94 monthCol("apr", "Apr"), monthCol("may", "May"), monthCol("jun", "Jun"),95 monthCol("jul", "Jul"), monthCol("aug", "Aug"), monthCol("sep", "Sep"),96 monthCol("oct", "Oct"), monthCol("nov", "Nov"), monthCol("dec", "Dec"),97 ],98 },99 {100 accessor: "productCategories",101 label: "Product Categories",102 width: 450,103 collapsible: true,104 collapseDefault: true,105 children: [106 { accessor: "topCategory", label: "Top Category", width: 140, showWhen: "parentCollapsed" as const, sortable: true, type: "string" },107 { accessor: "softwareSales", label: "Software", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("softwareSales") },108 { accessor: "hardwareSales", label: "Hardware", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("hardwareSales") },109 { accessor: "servicesSales", label: "Services", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("servicesSales") },110 ],111 },112];113114export const collapsibleColumnsConfig = {115 headers: collapsibleColumnsHeaders,116 rows: collapsibleColumnsData,117 tableProps: {118 columnResizing: true,119 enableColumnEditor: true,120 selectableCells: true,121 columnReordering: true,122 },123} as const;124
Svelte
Copy
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7</script>89<SimpleTable10 columns={collapsibleColumnsConfig.headers}11 rows={collapsibleColumnsConfig.rows}12 columnResizing={true}13 enableColumnEditor={true}14 selectableCells={true}15 columnReordering={true}16 {height}17 {theme}18/>
Solid TSX
Copy
1import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";2import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";3import "@simple-table/solid/styles.css";45export default function CollapsibleColumnsDemo(props: {6 height?: string | number;7 theme?: Theme;8}) {9 return (10 <SimpleTable11 columns={collapsibleColumnsConfig.headers}12 rows={collapsibleColumnsConfig.rows}13 columnResizing14 enableColumnEditor15 selectableCells16 columnReordering17 height={props.height ?? "400px"}18 theme={props.theme}19 />20 );21}
TypeScriptCollapsibleColumnsDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { collapsibleColumnsConfig } from "./collapsible-columns.demo-data";4import "simple-table-core/styles.css";56export function renderCollapsibleColumnsDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 const table = new SimpleTableVanilla(container, {11 columns: collapsibleColumnsConfig.headers,12 rows: collapsibleColumnsConfig.rows,13 columnResizing: true,14 enableColumnEditor: true,15 selectableCells: true,16 columnReordering: true,17 height: options?.height ?? "400px",18 theme: options?.theme,19 });20 return table;21}222324// collapsible-columns.demo-data.ts25// Self-contained demo table setup for this example.26import type { ColumnDef } from "simple-table-core";272829export const collapsibleColumnsData = [30 { id: 1, name: "Alice Thompson", region: "North America", q1Sales: 245000, q2Sales: 289000, q3Sales: 312000, q4Sales: 298000, totalSales: 1144000, avgQuarterly: 286000, jan: 78000, feb: 82000, mar: 85000, apr: 89000, may: 95000, jun: 105000, jul: 98000, aug: 102000, sep: 112000, oct: 108000, nov: 95000, dec: 95000, avgMonthly: 95333, bestMonth: 112000, softwareSales: 456000, hardwareSales: 342000, servicesSales: 346000, topCategory: "Software", categoryCount: 3 },31 { id: 2, name: "Marcus Chen", region: "Asia Pacific", q1Sales: 189000, q2Sales: 234000, q3Sales: 287000, q4Sales: 276000, totalSales: 986000, avgQuarterly: 246500, jan: 58000, feb: 62000, mar: 69000, apr: 72000, may: 78000, jun: 84000, jul: 89000, aug: 95000, sep: 103000, oct: 98000, nov: 89000, dec: 89000, avgMonthly: 82166, bestMonth: 103000, softwareSales: 398000, hardwareSales: 298000, servicesSales: 290000, topCategory: "Software", categoryCount: 3 },32 { id: 3, name: "Sofia Rodriguez", region: "Europe", q1Sales: 198000, q2Sales: 245000, q3Sales: 267000, q4Sales: 289000, totalSales: 999000, avgQuarterly: 249750, jan: 62000, feb: 66000, mar: 70000, apr: 78000, may: 82000, jun: 85000, jul: 85000, aug: 88000, sep: 94000, oct: 96000, nov: 97000, dec: 96000, avgMonthly: 83250, bestMonth: 97000, softwareSales: 389000, hardwareSales: 312000, servicesSales: 298000, topCategory: "Software", categoryCount: 3 },33 { id: 4, name: "David Kim", region: "North America", q1Sales: 167000, q2Sales: 198000, q3Sales: 234000, q4Sales: 267000, totalSales: 866000, avgQuarterly: 216500, jan: 52000, feb: 55000, mar: 60000, apr: 63000, may: 66000, jun: 69000, jul: 75000, aug: 78000, sep: 81000, oct: 87000, nov: 89000, dec: 91000, avgMonthly: 72166, bestMonth: 91000, softwareSales: 346000, hardwareSales: 267000, servicesSales: 253000, topCategory: "Software", categoryCount: 3 },34 { id: 5, name: "Emma Wilson", region: "Australia", q1Sales: 134000, q2Sales: 167000, q3Sales: 198000, q4Sales: 234000, totalSales: 733000, avgQuarterly: 183250, jan: 42000, feb: 45000, mar: 47000, apr: 52000, may: 55000, jun: 60000, jul: 63000, aug: 66000, sep: 69000, oct: 75000, nov: 78000, dec: 81000, avgMonthly: 61083, bestMonth: 81000, softwareSales: 293000, hardwareSales: 220000, servicesSales: 220000, topCategory: "Software", categoryCount: 3 },35 { id: 6, name: "James Anderson", region: "South America", q1Sales: 156000, q2Sales: 178000, q3Sales: 201000, q4Sales: 223000, totalSales: 758000, avgQuarterly: 189500, jan: 48000, feb: 52000, mar: 56000, apr: 58000, may: 60000, jun: 60000, jul: 65000, aug: 67000, sep: 69000, oct: 72000, nov: 75000, dec: 76000, avgMonthly: 63166, bestMonth: 76000, softwareSales: 303000, hardwareSales: 227000, servicesSales: 228000, topCategory: "Software", categoryCount: 3 },36 { id: 7, name: "Lisa Chang", region: "Asia Pacific", q1Sales: 145000, q2Sales: 178000, q3Sales: 201000, q4Sales: 234000, totalSales: 758000, avgQuarterly: 189500, jan: 45000, feb: 48000, mar: 52000, apr: 58000, may: 60000, jun: 60000, jul: 65000, aug: 67000, sep: 69000, oct: 75000, nov: 78000, dec: 81000, avgMonthly: 63166, bestMonth: 81000, softwareSales: 303000, hardwareSales: 227000, servicesSales: 228000, topCategory: "Software", categoryCount: 3 },37 { id: 8, name: "Michael Brown", region: "Europe", q1Sales: 178000, q2Sales: 201000, q3Sales: 234000, q4Sales: 256000, totalSales: 869000, avgQuarterly: 217250, jan: 56000, feb: 60000, mar: 62000, apr: 65000, may: 67000, jun: 69000, jul: 75000, aug: 78000, sep: 81000, oct: 83000, nov: 86000, dec: 87000, avgMonthly: 72416, bestMonth: 87000, softwareSales: 347000, hardwareSales: 260000, servicesSales: 262000, topCategory: "Software", categoryCount: 3 },38 { id: 9, name: "Sarah Johnson", region: "North America", q1Sales: 201000, q2Sales: 234000, q3Sales: 267000, q4Sales: 289000, totalSales: 991000, avgQuarterly: 247750, jan: 63000, feb: 67000, mar: 71000, apr: 75000, may: 78000, jun: 81000, jul: 85000, aug: 89000, sep: 93000, oct: 95000, nov: 97000, dec: 97000, avgMonthly: 82583, bestMonth: 97000, softwareSales: 396000, hardwareSales: 297000, servicesSales: 298000, topCategory: "Software", categoryCount: 3 },39 { id: 10, name: "Robert Davis", region: "Australia", q1Sales: 123000, q2Sales: 145000, q3Sales: 167000, q4Sales: 189000, totalSales: 624000, avgQuarterly: 156000, jan: 38000, feb: 42000, mar: 43000, apr: 46000, may: 48000, jun: 51000, jul: 53000, aug: 56000, sep: 58000, oct: 60000, nov: 63000, dec: 66000, avgMonthly: 52000, bestMonth: 66000, softwareSales: 249000, hardwareSales: 187000, servicesSales: 188000, topCategory: "Software", categoryCount: 3 },40 { id: 11, name: "Jennifer Martinez", region: "South America", q1Sales: 134000, q2Sales: 156000, q3Sales: 178000, q4Sales: 201000, totalSales: 669000, avgQuarterly: 167250, jan: 42000, feb: 45000, mar: 47000, apr: 50000, may: 52000, jun: 54000, jul: 57000, aug: 59000, sep: 62000, oct: 65000, nov: 67000, dec: 69000, avgMonthly: 55750, bestMonth: 69000, softwareSales: 267000, hardwareSales: 201000, servicesSales: 201000, topCategory: "Software", categoryCount: 3 },41 { id: 12, name: "Christopher Lee", region: "Europe", q1Sales: 167000, q2Sales: 189000, q3Sales: 212000, q4Sales: 234000, totalSales: 802000, avgQuarterly: 200500, jan: 52000, feb: 55000, mar: 60000, apr: 61000, may: 63000, jun: 65000, jul: 68000, aug: 71000, sep: 73000, oct: 76000, nov: 78000, dec: 80000, avgMonthly: 66833, bestMonth: 80000, softwareSales: 320000, hardwareSales: 241000, servicesSales: 241000, topCategory: "Software", categoryCount: 3 },42];4344const fmt = (accessor: string) => ({ row }: { row: Record<string, unknown> }) =>45 `$${((row[accessor] as number) || 0).toLocaleString()}`;4647const monthCol = (accessor: string, label: string): ColumnDef => ({48 accessor,49 label,50 width: 100,51 showWhen: "parentExpanded" as const,52 sortable: true,53 align: "right",54 type: "number",55 cellRenderer: fmt(accessor),56});5758export const collapsibleColumnsHeaders: ColumnDef[] = [59 { accessor: "id", label: "ID", width: 60, sortable: true },60 { accessor: "name", label: "Sales Rep", minWidth: 150, width: "1fr", sortable: true },61 { accessor: "region", label: "Region", width: 140, sortable: true },62 {63 accessor: "quarterlySales",64 label: "Quarterly Sales",65 width: 500,66 collapsible: true,67 collapseDefault: true,68 children: [69 { accessor: "totalSales", label: "Total Sales", width: 140, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("totalSales") },70 { accessor: "q1Sales", label: "Q1", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q1Sales") },71 { accessor: "q2Sales", label: "Q2", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q2Sales") },72 { accessor: "q3Sales", label: "Q3", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q3Sales") },73 { accessor: "q4Sales", label: "Q4", width: 120, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("q4Sales") },74 ],75 },76 {77 accessor: "monthlyPerformance",78 label: "Monthly Performance",79 width: 800,80 collapsible: true,81 collapseDefault: true,82 children: [83 { accessor: "avgMonthly", label: "Avg Monthly", width: 130, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("avgMonthly") },84 { accessor: "bestMonth", label: "Best Month", width: 130, showWhen: "parentCollapsed" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("bestMonth") },85 monthCol("jan", "Jan"), monthCol("feb", "Feb"), monthCol("mar", "Mar"),86 monthCol("apr", "Apr"), monthCol("may", "May"), monthCol("jun", "Jun"),87 monthCol("jul", "Jul"), monthCol("aug", "Aug"), monthCol("sep", "Sep"),88 monthCol("oct", "Oct"), monthCol("nov", "Nov"), monthCol("dec", "Dec"),89 ],90 },91 {92 accessor: "productCategories",93 label: "Product Categories",94 width: 450,95 collapsible: true,96 collapseDefault: true,97 children: [98 { accessor: "topCategory", label: "Top Category", width: 140, showWhen: "parentCollapsed" as const, sortable: true, type: "string" },99 { accessor: "softwareSales", label: "Software", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("softwareSales") },100 { accessor: "hardwareSales", label: "Hardware", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("hardwareSales") },101 { accessor: "servicesSales", label: "Services", width: 130, showWhen: "parentExpanded" as const, sortable: true, align: "right", type: "number", cellRenderer: fmt("servicesSales") },102 ],103 },104];105106export const collapsibleColumnsConfig = {107 headers: collapsibleColumnsHeaders,108 rows: collapsibleColumnsData,109 tableProps: {110 columnResizing: true,111 enableColumnEditor: true,112 selectableCells: true,113 columnReordering: true,114 },115} as const;116
Single-row children example
Parent header sits in the same row as its children.
React TSX
Copy
1import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";2import { singleRowChildrenConfig } from "./single-row-children.demo-data";3import "@simple-table/react/styles.css";45const SingleRowChildrenDemo = ({ height = "400px", theme }: { height?: string | number; theme?: Theme }) => {6 return (7 <SimpleTable8 columns={singleRowChildrenConfig.headers}9 rows={singleRowChildrenConfig.rows}10 columnResizing={singleRowChildrenConfig.tableProps.columnResizing}11 selectableCells={singleRowChildrenConfig.tableProps.selectableCells}12 height={height}13 theme={theme}14 />15 );16};1718export default SingleRowChildrenDemo;
Vue SFC
Copy
1<template>2 <SimpleTable3 :columns="singleRowChildrenConfig.headers"4 :rows="singleRowChildrenConfig.rows"5 :column-resizing="singleRowChildrenConfig.tableProps.columnResizing"6 :selectable-cells="singleRowChildrenConfig.tableProps.selectableCells"7 :height="height"8 :theme="theme"9 />10</template>1112<script setup lang="ts">13import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";14import { singleRowChildrenConfig } from "./single-row-children.demo-data";15import "@simple-table/vue/styles.css";1617withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), { height: "400px" });18</script>
Angularsingle-row-children-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, Row, Theme } from "@simple-table/angular";3import { singleRowChildrenConfig } from "./single-row-children.demo-data";4import "@simple-table/angular/styles.css";56@Component({7 selector: "single-row-children-demo",8 standalone: true,9 imports: [SimpleTableComponent],10 template: `11 <simple-table12 [columns]="headers"13 [rows]="rows"14 [columnResizing]="true"15 [selectableCells]="true"16 [height]="height"17 [theme]="theme"18 ></simple-table>19 `,20})21export class SingleRowChildrenDemoComponent {22 @Input() height: string | number = "400px";23 @Input() theme?: Theme;2425 readonly headers: AngularColumnDef[] = singleRowChildrenConfig.headers;26 readonly rows: Row[] = singleRowChildrenConfig.rows;27}282930// single-row-children.demo-data.ts31// Self-contained demo table setup for this example.32import type { AngularColumnDef } from "@simple-table/angular";333435export const singleRowChildrenData = [36 { id: 1, studentId: "STU-2024-001", studentName: "Alexandra Martinez", gradeLevel: "10th Grade", overallGPA: 3.85, mathGrade: 92, scienceGrade: 88, englishGrade: 91, historyGrade: 89 },37 { id: 2, studentId: "STU-2024-002", studentName: "Benjamin Foster", gradeLevel: "11th Grade", overallGPA: 3.65, mathGrade: 85, scienceGrade: 87, englishGrade: 89, historyGrade: 86 },38 { id: 3, studentId: "STU-2024-003", studentName: "Chloe Nakamura", gradeLevel: "12th Grade", overallGPA: 3.95, mathGrade: 96, scienceGrade: 94, englishGrade: 95, historyGrade: 93 },39 { id: 4, studentId: "STU-2024-004", studentName: "Diego Ramirez", gradeLevel: "9th Grade", overallGPA: 3.45, mathGrade: 82, scienceGrade: 84, englishGrade: 85, historyGrade: 83 },40 { id: 5, studentId: "STU-2024-005", studentName: "Emma Lindberg", gradeLevel: "10th Grade", overallGPA: 3.75, mathGrade: 88, scienceGrade: 90, englishGrade: 92, historyGrade: 87 },41 { id: 6, studentId: "STU-2024-006", studentName: "Finn O'Connor", gradeLevel: "11th Grade", overallGPA: 3.55, mathGrade: 84, scienceGrade: 85, englishGrade: 87, historyGrade: 86 },42 { id: 7, studentId: "STU-2024-007", studentName: "Grace Wellington", gradeLevel: "12th Grade", overallGPA: 4.0, mathGrade: 98, scienceGrade: 97, englishGrade: 99, historyGrade: 98 },43 { id: 8, studentId: "STU-2024-008", studentName: "Hassan Al-Rashid", gradeLevel: "9th Grade", overallGPA: 3.35, mathGrade: 80, scienceGrade: 82, englishGrade: 83, historyGrade: 81 },44 { id: 9, studentId: "STU-2024-009", studentName: "Isabella Kowalski", gradeLevel: "10th Grade", overallGPA: 3.8, mathGrade: 90, scienceGrade: 89, englishGrade: 93, historyGrade: 88 },45 { id: 10, studentId: "STU-2024-010", studentName: "Jackson Mbele", gradeLevel: "11th Grade", overallGPA: 3.7, mathGrade: 87, scienceGrade: 88, englishGrade: 90, historyGrade: 89 },46 { id: 11, studentId: "STU-2024-011", studentName: "Keiko Tanaka", gradeLevel: "12th Grade", overallGPA: 3.9, mathGrade: 94, scienceGrade: 93, englishGrade: 96, historyGrade: 92 },47];4849export const singleRowChildrenHeaders: AngularColumnDef[] = [50 { accessor: "studentId", label: "Student ID", width: 160, sortable: true, type: "string" },51 { accessor: "gradeLevel", label: "Grade Level", width: 150, sortable: true, type: "string" },52 {53 accessor: "studentName",54 label: "Student Name",55 width: 200,56 collapsible: true,57 type: "string",58 sortable: true,59 singleRowChildren: true,60 children: [61 { accessor: "overallGPA", label: "GPA", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentCollapsed", valueFormatter: ({ value }) => (value as number).toFixed(2) },62 { accessor: "mathGrade", label: "Math", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },63 { accessor: "scienceGrade", label: "Science", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },64 { accessor: "englishGrade", label: "English", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },65 { accessor: "historyGrade", label: "History", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },66 ],67 },68];6970export const singleRowChildrenConfig = {71 headers: singleRowChildrenHeaders,72 rows: singleRowChildrenData,73 tableProps: {74 columnResizing: true,75 selectableCells: true,76 },77} as const;78
Svelte
Copy
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { singleRowChildrenConfig } from "./single-row-children.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7</script>89<SimpleTable10 columns={singleRowChildrenConfig.headers}11 rows={singleRowChildrenConfig.rows}12 columnResizing={singleRowChildrenConfig.tableProps.columnResizing}13 selectableCells={singleRowChildrenConfig.tableProps.selectableCells}14 {height}15 {theme}16/>
Solid TSX
Copy
1import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";2import { singleRowChildrenConfig } from "./single-row-children.demo-data";3import "@simple-table/solid/styles.css";45export default function SingleRowChildrenDemo(props: { height?: string | number; theme?: Theme }) {6 return (7 <SimpleTable8 columns={singleRowChildrenConfig.headers}9 rows={singleRowChildrenConfig.rows}10 columnResizing={singleRowChildrenConfig.tableProps.columnResizing}11 selectableCells={singleRowChildrenConfig.tableProps.selectableCells}12 height={props.height ?? "400px"}13 theme={props.theme}14 />15 );16}
TypeScriptSingleRowChildrenDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { singleRowChildrenConfig } from "./single-row-children.demo-data";4import "simple-table-core/styles.css";56export function renderSingleRowChildrenDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 return new SimpleTableVanilla(container, {11 columns: singleRowChildrenConfig.headers,12 rows: singleRowChildrenConfig.rows,13 columnResizing: singleRowChildrenConfig.tableProps.columnResizing,14 selectableCells: singleRowChildrenConfig.tableProps.selectableCells,15 height: options?.height ?? "400px",16 theme: options?.theme,17 });18}192021// single-row-children.demo-data.ts22// Self-contained demo table setup for this example.23import type { ColumnDef } from "simple-table-core";242526export const singleRowChildrenData = [27 { id: 1, studentId: "STU-2024-001", studentName: "Alexandra Martinez", gradeLevel: "10th Grade", overallGPA: 3.85, mathGrade: 92, scienceGrade: 88, englishGrade: 91, historyGrade: 89 },28 { id: 2, studentId: "STU-2024-002", studentName: "Benjamin Foster", gradeLevel: "11th Grade", overallGPA: 3.65, mathGrade: 85, scienceGrade: 87, englishGrade: 89, historyGrade: 86 },29 { id: 3, studentId: "STU-2024-003", studentName: "Chloe Nakamura", gradeLevel: "12th Grade", overallGPA: 3.95, mathGrade: 96, scienceGrade: 94, englishGrade: 95, historyGrade: 93 },30 { id: 4, studentId: "STU-2024-004", studentName: "Diego Ramirez", gradeLevel: "9th Grade", overallGPA: 3.45, mathGrade: 82, scienceGrade: 84, englishGrade: 85, historyGrade: 83 },31 { id: 5, studentId: "STU-2024-005", studentName: "Emma Lindberg", gradeLevel: "10th Grade", overallGPA: 3.75, mathGrade: 88, scienceGrade: 90, englishGrade: 92, historyGrade: 87 },32 { id: 6, studentId: "STU-2024-006", studentName: "Finn O'Connor", gradeLevel: "11th Grade", overallGPA: 3.55, mathGrade: 84, scienceGrade: 85, englishGrade: 87, historyGrade: 86 },33 { id: 7, studentId: "STU-2024-007", studentName: "Grace Wellington", gradeLevel: "12th Grade", overallGPA: 4.0, mathGrade: 98, scienceGrade: 97, englishGrade: 99, historyGrade: 98 },34 { id: 8, studentId: "STU-2024-008", studentName: "Hassan Al-Rashid", gradeLevel: "9th Grade", overallGPA: 3.35, mathGrade: 80, scienceGrade: 82, englishGrade: 83, historyGrade: 81 },35 { id: 9, studentId: "STU-2024-009", studentName: "Isabella Kowalski", gradeLevel: "10th Grade", overallGPA: 3.8, mathGrade: 90, scienceGrade: 89, englishGrade: 93, historyGrade: 88 },36 { id: 10, studentId: "STU-2024-010", studentName: "Jackson Mbele", gradeLevel: "11th Grade", overallGPA: 3.7, mathGrade: 87, scienceGrade: 88, englishGrade: 90, historyGrade: 89 },37 { id: 11, studentId: "STU-2024-011", studentName: "Keiko Tanaka", gradeLevel: "12th Grade", overallGPA: 3.9, mathGrade: 94, scienceGrade: 93, englishGrade: 96, historyGrade: 92 },38];3940export const singleRowChildrenHeaders: ColumnDef[] = [41 { accessor: "studentId", label: "Student ID", width: 160, sortable: true, type: "string" },42 { accessor: "gradeLevel", label: "Grade Level", width: 150, sortable: true, type: "string" },43 {44 accessor: "studentName",45 label: "Student Name",46 width: 200,47 collapsible: true,48 type: "string",49 sortable: true,50 singleRowChildren: true,51 children: [52 { accessor: "overallGPA", label: "GPA", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentCollapsed", valueFormatter: ({ value }) => (value as number).toFixed(2) },53 { accessor: "mathGrade", label: "Math", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },54 { accessor: "scienceGrade", label: "Science", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },55 { accessor: "englishGrade", label: "English", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },56 { accessor: "historyGrade", label: "History", width: 90, sortable: true, type: "number", align: "right", showWhen: "parentExpanded" },57 ],58 },59];6061export const singleRowChildrenConfig = {62 headers: singleRowChildrenHeaders,63 rows: singleRowChildrenData,64 tableProps: {65 columnResizing: true,66 selectableCells: true,67 },68} as const;69
Props
Collapsible Columns Configuration
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
ColumnDef.collapsibleboolean | Optional | Enables expand/collapse on a parent column that has children. | |
ColumnDef.collapseDefaultboolean | Optional | Starts the group collapsed. Only applies when collapsible is true. | |
ColumnDef.showWhenenum | Optional | When a child column is visible relative to the parent's collapse state. Options: parentExpanded parentCollapsed always | |
ColumnDef.singleRowChildrenboolean | Optional | Renders the parent header beside its children in one row instead of nested above them. | |
icons.headerExpandReactNode | Optional | Custom expand icon for collapsible headers. | |
icons.headerCollapseReactNode | Optional | Custom collapse icon for collapsible headers. |