Documentation
Quick Start
Add Simple Table to your app in about 60 seconds.
Paste into your AI coding tool to install Simple Table, map this app's data into columns and rows, and match your design system.
- 1
Install
Full install options (yarn, pnpm) are on the Installation page.ShellCopynpm install @simple-table/reactShellCopynpm install @simple-table/angularShellCopynpm install @simple-table/vueShellCopynpm install @simple-table/svelteShellCopynpm install @simple-table/solidShellCopynpm install simple-table-core - 2
Import
Import the table component and its CSS styles.TypeScriptCopyimport { SimpleTable, type ReactColumnDef } from "@simple-table/react";import "@simple-table/react/styles.css";TypeScriptCopyimport { SimpleTableImports, type AngularColumnDef } from "@simple-table/angular";import "@simple-table/angular/styles.css";TypeScriptCopyimport { SimpleTable, type VueColumnDef } from "@simple-table/vue";import "@simple-table/vue/styles.css";TypeScriptCopyimport { SimpleTable, type SvelteColumnDef } from "@simple-table/svelte";import "@simple-table/svelte/styles.css";TypeScriptCopyimport { SimpleTable, type SolidColumnDef } from "@simple-table/solid";import "@simple-table/solid/styles.css";TypeScriptCopyimport { SimpleTableVanilla, type ColumnDef } from "simple-table-core";import "simple-table-core/styles.css"; - 3
Define columns
Each column needs anaccessorthat matches a property on your row objects.TypeScriptCopyconst columns: ReactColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },];TypeScriptCopyconst columns: AngularColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },];TypeScriptCopyconst columns: VueColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },];TypeScriptCopyconst columns: SvelteColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },];TypeScriptCopyconst columns: SolidColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },];TypeScriptCopyconst columns: ColumnDef[] = [{ accessor: "id", label: "ID", width: 80, type: "number" },{ accessor: "name", label: "Name", width: "1fr", type: "string" },{ accessor: "age", label: "Age", width: 80, type: "number" },]; - 4
Define rows
Provide an array of objects, one object per row.TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },];TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },];TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },];TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },];TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },];TypeScriptCopyconst rows = [{ id: 1, name: "John Doe", age: 30 },{ id: 2, name: "Jane Smith", age: 25 },]; - 5
Render the table
Pass columns and rows to the table. Setheightso the table scrolls with a sticky header.React TSXCopy<SimpleTable columns={columns} rows={rows} height="400px" />AngularCopy<simple-table[columns]="columns"[rows]="rows"height="400px"></simple-table>Vue SFCCopy<SimpleTable:columns="columns":rows="rows"height="400px"/>SvelteCopy<SimpleTable {columns} {rows} height="400px" />Solid TSXCopy<SimpleTable columns={columns} rows={rows} height="400px" />TypeScriptCopynew SimpleTableVanilla(container, {columns,rows,height: "400px",});
Example
A live table built with the same props. Use Code or StackBlitz to explore the full example.
React TSX
Copy
1import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";2import { quickStartConfig } from "./quick-start.demo-data";3import "@simple-table/react/styles.css";45const QuickStartDemo = ({6 height = "300px",7 theme8}: {9 height?: string | number;10 theme?: Theme;11}) => {12 return (13 <SimpleTable14 columns={quickStartConfig.headers}15 rows={quickStartConfig.rows}16 height={height}17 theme={theme}18 enableColumnEditor={quickStartConfig.tableProps.enableColumnEditor}19 selectableCells={quickStartConfig.tableProps.selectableCells}20 customTheme={quickStartConfig.tableProps.customTheme}21 getRowId={({ row }) => row.id}22 />23 );24};2526export default QuickStartDemo;
Angularquick-start-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import { SimpleTableImports } from "@simple-table/angular";3import type { AngularColumnDef, GetRowIdParams, Theme } from "@simple-table/angular";4import { quickStartConfig } from "./quick-start.demo-data";5import "@simple-table/angular/styles.css";6import type { QuickStartEmployee } from "./quick-start.demo-data";78@Component({9 selector: "quick-start-demo",10 standalone: true,11 imports: [SimpleTableImports],12 template: `13 <simple-table14 [getRowId]="getRowId"15 [rows]="rows"16 [columns]="headers"17 [height]="height"18 [theme]="theme"19 [enableColumnEditor]="enableColumnEditorProp"20 [selectableCells]="selectableCellsProp"21 [customTheme]="customTheme"22 ></simple-table>23 `,24})25export class QuickStartDemoComponent {26 @Input() height: string | number = "300px";27 @Input() theme?: Theme;2829 readonly rows: QuickStartEmployee[] = quickStartConfig.rows;30 readonly headers: AngularColumnDef<QuickStartEmployee>[] = quickStartConfig.headers;31 readonly enableColumnEditorProp = quickStartConfig.tableProps.enableColumnEditor;32 readonly selectableCellsProp = quickStartConfig.tableProps.selectableCells;33 readonly customTheme = quickStartConfig.tableProps.customTheme;3435 getRowId = ({ row }: GetRowIdParams<QuickStartEmployee>) => row.id;36}373839// quick-start.demo-data.ts40// Self-contained demo table setup for this example.41import type { AngularColumnDef } from "@simple-table/angular";4243export interface QuickStartEmployee {44 id: number;45 name: string;46 age: number;47 role: string;48 department: string;49 startDate: string;50}5152export const QUICK_START_DATA: QuickStartEmployee[] = [53 {54 id: 1,55 name: "Marcus Rodriguez",56 age: 29,57 role: "Frontend Developer",58 department: "Engineering",59 startDate: "2022-03-15",60 },61 {62 id: 2,63 name: "Sophia Chen",64 age: 27,65 role: "UX/UI Designer",66 department: "Design",67 startDate: "2021-11-08",68 },69 {70 id: 3,71 name: "Raj Patel",72 age: 34,73 role: "Engineering Manager",74 department: "Engineering",75 startDate: "2020-01-20",76 },77 {78 id: 4,79 name: "Luna Martinez",80 age: 23,81 role: "Junior Developer",82 department: "Engineering",83 startDate: "2023-06-12",84 },85 {86 id: 5,87 name: "Tyler Anderson",88 age: 31,89 role: "DevOps Engineer",90 department: "Infrastructure",91 startDate: "2021-08-03",92 },93 {94 id: 6,95 name: "Zara Kim",96 age: 28,97 role: "Product Designer",98 department: "Design",99 startDate: "2022-01-17",100 },101 {102 id: 7,103 name: "Kai Thompson",104 age: 26,105 role: "Full Stack Developer",106 department: "Engineering",107 startDate: "2022-09-05",108 },109 {110 id: 8,111 name: "Ava Singh",112 age: 33,113 role: "Product Manager",114 department: "Product",115 startDate: "2020-07-14",116 },117 {118 id: 9,119 name: "Jordan Walsh",120 age: 25,121 role: "Marketing Specialist",122 department: "Growth",123 startDate: "2023-02-28",124 },125 {126 id: 10,127 name: "Phoenix Lee",128 age: 30,129 role: "Backend Developer",130 department: "Engineering",131 startDate: "2021-05-11",132 },133 {134 id: 11,135 name: "River Jackson",136 age: 24,137 role: "Growth Designer",138 department: "Design",139 startDate: "2023-01-09",140 },141 {142 id: 12,143 name: "Atlas Morgan",144 age: 32,145 role: "Tech Lead",146 department: "Engineering",147 startDate: "2019-12-02",148 },149];150151152export const quickStartHeaders: AngularColumnDef<QuickStartEmployee>[] = [153 { accessor: "id", label: "ID", width: 80, sortable: true, type: "number" },154 {155 accessor: "name",156 label: "Name",157 minWidth: 80,158 width: "1fr",159 sortable: true,160 type: "string",161 },162 { accessor: "age", label: "Age", width: 100, sortable: true, type: "number" },163 { accessor: "role", label: "Role", width: 150, sortable: true, type: "string" },164 { accessor: "department", label: "Department", width: 150, sortable: true, type: "string" },165 { accessor: "startDate", label: "Start Date", width: 150, sortable: true, type: "date" },166];167168export const quickStartConfig = {169 headers: quickStartHeaders,170 rows: QUICK_START_DATA,171 tableProps: {172 enableColumnEditor: true,173 selectableCells: true,174 customTheme: { rowHeight: 32 },175 },176};177
Vue SFC
Copy
1<template>2 <SimpleTable3 :columns="quickStartConfig.headers"4 :rows="quickStartConfig.rows"5 :get-row-id="getRowId"6 :height="height"7 :theme="theme"8 :enable-column-editor="quickStartConfig.tableProps.enableColumnEditor"9 :selectable-cells="quickStartConfig.tableProps.selectableCells"10 :custom-theme="quickStartConfig.tableProps.customTheme"11 />12</template>1314<script setup lang="ts">15import { SimpleTable } from "@simple-table/vue";16import type { Theme, GetRowIdParams } from "@simple-table/vue";17import { quickStartConfig } from "./quick-start.demo-data";18import type { QuickStartEmployee } from "./quick-start.demo-data";19import "@simple-table/vue/styles.css";2021withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {22 height: "300px",23});2425const getRowId = ({ row }: GetRowIdParams<QuickStartEmployee>) => row.id;26</script>
Svelte
Copy
1<script lang="ts">2 import { SimpleTable } from "@simple-table/svelte";3 import type { Theme, GetRowIdParams } from "@simple-table/svelte";4 import { quickStartConfig } from "./quick-start.demo-data";5 import type { QuickStartEmployee } from "./quick-start.demo-data";6 import "@simple-table/svelte/styles.css";78 let { height = "300px", theme }: { height?: string | number; theme?: Theme } = $props();910 const getRowId = ({ row }: GetRowIdParams<QuickStartEmployee>) => row.id;11</script>1213<SimpleTable14 columns={quickStartConfig.headers}15 rows={quickStartConfig.rows}16 getRowId={getRowId}17 {height}18 {theme}19 enableColumnEditor={quickStartConfig.tableProps.enableColumnEditor}20 selectableCells={quickStartConfig.tableProps.selectableCells}21 customTheme={quickStartConfig.tableProps.customTheme}22/>
Solid TSX
Copy
1import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";2import { quickStartConfig } from "./quick-start.demo-data";3import "@simple-table/solid/styles.css";45export default function QuickStartDemo(props: {6 height?: string | number;7 theme?: Theme;8}) {9 return (10 <SimpleTable11 columns={quickStartConfig.headers}12 getRowId={({ row }) => row.id}13 rows={quickStartConfig.rows}14 height={props.height ?? "300px"}15 theme={props.theme}16 enableColumnEditor={quickStartConfig.tableProps.enableColumnEditor}17 selectableCells={quickStartConfig.tableProps.selectableCells}18 customTheme={quickStartConfig.tableProps.customTheme}19 />20 );21}
TypeScriptQuickStartDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { QuickStartEmployee } from "./quick-start.demo-data";3import type { Theme, GetRowIdParams } from "simple-table-core";4import { quickStartConfig } from "./quick-start.demo-data";5import "simple-table-core/styles.css";678const getRowId = ({ row }: GetRowIdParams<QuickStartEmployee>) => row.id;9export function renderQuickStartDemo(10 container: HTMLElement,11 options?: { height?: string | number; theme?: Theme }12): SimpleTableVanilla<QuickStartEmployee> {13 const table = new SimpleTableVanilla(container, {14 getRowId,15 columns: quickStartConfig.headers,16 rows: quickStartConfig.rows,17 height: options?.height ?? "300px",18 theme: options?.theme,19 enableColumnEditor: quickStartConfig.tableProps.enableColumnEditor,20 selectableCells: quickStartConfig.tableProps.selectableCells,21 customTheme: quickStartConfig.tableProps.customTheme,22 });23 return table;24}252627// quick-start.demo-data.ts28// Self-contained demo table setup for this example.29import type { ColumnDef } from "simple-table-core";3031export interface QuickStartEmployee {32 id: number;33 name: string;34 age: number;35 role: string;36 department: string;37 startDate: string;38}3940export const QUICK_START_DATA: QuickStartEmployee[] = [41 {42 id: 1,43 name: "Marcus Rodriguez",44 age: 29,45 role: "Frontend Developer",46 department: "Engineering",47 startDate: "2022-03-15",48 },49 {50 id: 2,51 name: "Sophia Chen",52 age: 27,53 role: "UX/UI Designer",54 department: "Design",55 startDate: "2021-11-08",56 },57 {58 id: 3,59 name: "Raj Patel",60 age: 34,61 role: "Engineering Manager",62 department: "Engineering",63 startDate: "2020-01-20",64 },65 {66 id: 4,67 name: "Luna Martinez",68 age: 23,69 role: "Junior Developer",70 department: "Engineering",71 startDate: "2023-06-12",72 },73 {74 id: 5,75 name: "Tyler Anderson",76 age: 31,77 role: "DevOps Engineer",78 department: "Infrastructure",79 startDate: "2021-08-03",80 },81 {82 id: 6,83 name: "Zara Kim",84 age: 28,85 role: "Product Designer",86 department: "Design",87 startDate: "2022-01-17",88 },89 {90 id: 7,91 name: "Kai Thompson",92 age: 26,93 role: "Full Stack Developer",94 department: "Engineering",95 startDate: "2022-09-05",96 },97 {98 id: 8,99 name: "Ava Singh",100 age: 33,101 role: "Product Manager",102 department: "Product",103 startDate: "2020-07-14",104 },105 {106 id: 9,107 name: "Jordan Walsh",108 age: 25,109 role: "Marketing Specialist",110 department: "Growth",111 startDate: "2023-02-28",112 },113 {114 id: 10,115 name: "Phoenix Lee",116 age: 30,117 role: "Backend Developer",118 department: "Engineering",119 startDate: "2021-05-11",120 },121 {122 id: 11,123 name: "River Jackson",124 age: 24,125 role: "Growth Designer",126 department: "Design",127 startDate: "2023-01-09",128 },129 {130 id: 12,131 name: "Atlas Morgan",132 age: 32,133 role: "Tech Lead",134 department: "Engineering",135 startDate: "2019-12-02",136 },137];138139140export const quickStartHeaders: ColumnDef<QuickStartEmployee>[] = [141 { accessor: "id", label: "ID", width: 80, sortable: true, type: "number" },142 {143 accessor: "name",144 label: "Name",145 minWidth: 80,146 width: "1fr",147 sortable: true,148 type: "string",149 },150 { accessor: "age", label: "Age", width: 100, sortable: true, type: "number" },151 { accessor: "role", label: "Role", width: 150, sortable: true, type: "string" },152 { accessor: "department", label: "Department", width: 150, sortable: true, type: "string" },153 { accessor: "startDate", label: "Start Date", width: 150, sortable: true, type: "date" },154];155156export const quickStartConfig = {157 headers: quickStartHeaders,158 rows: QUICK_START_DATA,159 tableProps: {160 enableColumnEditor: true,161 selectableCells: true,162 customTheme: { rowHeight: 32 },163 },164};165
Height
Prefer height or maxHeight so the table owns scrolling. Details in Table Height.
getRowId (recommended)
Provide a stable id when you sort, filter, group, or update rows often: getRowId={({ row }) => String(row.id)}
SimpleTable Props
Main Component Props
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
columns | Required | Array of column definitions that specify the structure of your table. | |
rows | Required | Array of data objects to display in the table. Each object represents a row. | |
| Optional | Optional but recommended: Function to generate unique identifiers for each row. Receives detailed context (row, depth, index, paths). Enables stable row identification across sorting and filtering. Highly recommended for tables with row grouping, external sorting, or dynamic data updates. | ||
height | Optional | Height of the table container. When specified, Simple Table handles vertical scrolling internally with a fixed header. When omitted, the table expands to fit all rows and overflows the parent container. Most applications should specify a height. | |
customTheme | Optional | Custom theme configuration for dimensions and spacing. Only specify the properties you want to customize. | |
enableColumnEditorboolean | Optional | Enable column reordering by drag and drop. | |
selectableCellsboolean | Optional | Enable cell selection functionality. | |
theme | Optional | Custom theme object to override default styling. |