Documentation
Themes
Simple Table includes several beautiful built-in themes to match your application's visual design. Choose from Modern Light, Modern Dark, Light, Dark, or Neutral themes. Learn more about customizing your table or explore creating custom themes.
1import { useState } from "react";2import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";3import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";4import "@simple-table/react/styles.css";56const ThemesDemo = ({7 height = "400px",8 theme,9}: {10 height?: string | number;11 theme?: Theme;12}) => {13 const [selectedTheme, setSelectedTheme] = useState<Theme>(theme ?? "light");1415 return (16 <div>17 <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 12 }}>18 {AVAILABLE_THEMES.map((t) => (19 <button20 key={t.value}21 onClick={() => setSelectedTheme(t.value)}22 style={{23 padding: "6px 14px",24 borderRadius: 6,25 border: selectedTheme === t.value ? "2px solid #3b82f6" : "1px solid #d1d5db",26 background: selectedTheme === t.value ? "#eff6ff" : "#fff",27 color: selectedTheme === t.value ? "#1d4ed8" : "#374151",28 fontWeight: selectedTheme === t.value ? 600 : 400,29 cursor: "pointer",30 fontSize: 13,31 }}32 >33 {t.label}34 </button>35 ))}36 </div>37 <SimpleTable38 defaultHeaders={themesConfig.headers}39 rows={themesConfig.rows}40 height={height}41 theme={selectedTheme}42 />43 </div>44 );45};4647export default ThemesDemo;
1<template>2 <div>3 <div style="display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px">4 <button5 v-for="t in AVAILABLE_THEMES"6 :key="t.value"7 @click="selectedTheme = t.value"8 :style="{9 padding: '6px 14px',10 borderRadius: '6px',11 border: selectedTheme === t.value ? '2px solid #3b82f6' : '1px solid #d1d5db',12 background: selectedTheme === t.value ? '#eff6ff' : '#fff',13 color: selectedTheme === t.value ? '#1d4ed8' : '#374151',14 fontWeight: selectedTheme === t.value ? 600 : 400,15 cursor: 'pointer',16 fontSize: '13px',17 }"18 >19 {{ t.label }}20 </button>21 </div>22 <SimpleTable23 :default-headers="themesConfig.headers"24 :rows="themesConfig.rows"25 :height="height"26 :theme="selectedTheme"27 />28 </div>29</template>3031<script setup lang="ts">32import { ref } from "vue";33import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";34import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";35import "@simple-table/vue/styles.css";3637const props = withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {38 height: "400px",39});4041const selectedTheme = ref<Theme>(props.theme ?? "light");42</script>
1import { Component, Input } from "@angular/core";2import { NgFor } from "@angular/common";3import {SimpleTableComponent} from "@simple-table/angular";import type { AngularHeaderObject, Row, Theme } from "@simple-table/angular";4import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";5import "@simple-table/angular/styles.css";67@Component({8 selector: "themes-demo",9 standalone: true,10 imports: [SimpleTableComponent, NgFor],11 template: `12 <div>13 <div style="display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px">14 <button15 *ngFor="let t of themes"16 (click)="selectedTheme = t.value"17 [style.padding]="'6px 14px'"18 [style.borderRadius]="'6px'"19 [style.border]="selectedTheme === t.value ? '2px solid #3b82f6' : '1px solid #d1d5db'"20 [style.background]="selectedTheme === t.value ? '#eff6ff' : '#fff'"21 [style.color]="selectedTheme === t.value ? '#1d4ed8' : '#374151'"22 [style.fontWeight]="selectedTheme === t.value ? 600 : 400"23 [style.cursor]="'pointer'"24 [style.fontSize]="'13px'"25 >26 {{ t.label }}27 </button>28 </div>29 <simple-table30 [rows]="rows"31 [defaultHeaders]="headers"32 [height]="height"33 [theme]="selectedTheme"34 ></simple-table>35 </div>36 `,37})38export class ThemesDemoComponent {39 @Input() height: string | number = "400px";40 @Input() theme?: Theme;4142 readonly rows: Row[] = themesConfig.rows;43 readonly headers: AngularHeaderObject[] = themesConfig.headers;44 readonly themes = AVAILABLE_THEMES;45 selectedTheme: Theme = "light";4647 ngOnInit() {48 if (this.theme) this.selectedTheme = this.theme;49 }50}515253// themes.demo-data.ts54// Self-contained demo table setup for this example.55import type { AngularHeaderObject, Theme } from "@simple-table/angular";565758export const AVAILABLE_THEMES: { value: Theme; label: string }[] = [59 { value: "light", label: "Light" },60 { value: "dark", label: "Dark" },61 { value: "modern-light", label: "Modern Light" },62 { value: "modern-dark", label: "Modern Dark" },63 { value: "neutral", label: "Neutral" },64];6566export const themesHeaders: AngularHeaderObject[] = [67 { accessor: "id", label: "ID", width: 80, type: "number" },68 { accessor: "name", label: "Name", minWidth: 100, width: "1fr", type: "string" },69 { accessor: "email", label: "Email", width: 220, type: "string" },70 { accessor: "department", label: "Department", width: 150, type: "string" },71 { accessor: "status", label: "Status", width: 120, type: "string" },72];7374export const themesData = [75 { id: 1, name: "Dr. Sarah Mitchell", email: "s.mitchell@cityhospital.org", department: "Cardiology", status: "Active" },76 { id: 2, name: "Nurse Emily Chen", email: "e.chen@cityhospital.org", department: "Emergency", status: "Active" },77 { id: 3, name: "Dr. Marcus Williams", email: "m.williams@cityhospital.org", department: "Neurology", status: "Active" },78 { id: 4, name: "Therapist Ana Rodriguez", email: "a.rodriguez@cityhospital.org", department: "Physical Therapy", status: "Active" },79 { id: 5, name: "Dr. Yuki Tanaka", email: "y.tanaka@cityhospital.org", department: "Pediatrics", status: "On Call" },80 { id: 6, name: "Technician Omar Hassan", email: "o.hassan@cityhospital.org", department: "Radiology", status: "Active" },81 { id: 7, name: "Dr. Priya Patel", email: "p.patel@cityhospital.org", department: "Oncology", status: "Active" },82 { id: 8, name: "Coordinator Lisa Kim", email: "l.kim@cityhospital.org", department: "Patient Care", status: "Active" },83 { id: 9, name: "Dr. Giovanni Rossi", email: "g.rossi@cityhospital.org", department: "Surgery", status: "Active" },84 { id: 10, name: "Pharmacist David Lee", email: "d.lee@cityhospital.org", department: "Pharmacy", status: "Active" },85 { id: 11, name: "Nurse Zara Singh", email: "z.singh@cityhospital.org", department: "ICU", status: "Active" },86 { id: 12, name: "Dr. Felix Martinez", email: "f.martinez@cityhospital.org", department: "Orthopedics", status: "Active" },87];8889export const themesConfig = {90 headers: themesHeaders,91 rows: themesData,92} as const;93
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7 let userThemePick = $state<Theme | undefined>(undefined);8 const selectedTheme: Theme = $derived(userThemePick ?? theme ?? "light");9</script>1011<div>12 <div style="display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px">13 {#each AVAILABLE_THEMES as t}14 <button15 onclick={() => (userThemePick = t.value)}16 style="padding: 6px 14px; border-radius: 6px; cursor: pointer; font-size: 13px; border: {selectedTheme === t.value ? '2px solid #3b82f6' : '1px solid #d1d5db'}; background: {selectedTheme === t.value ? '#eff6ff' : '#fff'}; color: {selectedTheme === t.value ? '#1d4ed8' : '#374151'}; font-weight: {selectedTheme === t.value ? 600 : 400}"17 >18 {t.label}19 </button>20 {/each}21 </div>22 <SimpleTable23 defaultHeaders={themesConfig.headers}24 rows={themesConfig.rows}25 {height}26 theme={selectedTheme}27 />28</div>
1import { createSignal, For } from "solid-js";2import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";3import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";4import "@simple-table/solid/styles.css";56export default function ThemesDemo(props: { height?: string | number; theme?: Theme }) {7 const [selectedTheme, setSelectedTheme] = createSignal<Theme>(props.theme ?? "light");89 return (10 <div>11 <div style={{ display: "flex", "flex-wrap": "wrap", gap: "8px", "margin-bottom": "12px" }}>12 <For each={AVAILABLE_THEMES}>13 {(t) => (14 <button15 onClick={() => setSelectedTheme(t.value)}16 style={{17 padding: "6px 14px",18 "border-radius": "6px",19 border: selectedTheme() === t.value ? "2px solid #3b82f6" : "1px solid #d1d5db",20 background: selectedTheme() === t.value ? "#eff6ff" : "#fff",21 color: selectedTheme() === t.value ? "#1d4ed8" : "#374151",22 "font-weight": selectedTheme() === t.value ? 600 : 400,23 cursor: "pointer",24 "font-size": "13px",25 }}26 >27 {t.label}28 </button>29 )}30 </For>31 </div>32 <SimpleTable33 defaultHeaders={themesConfig.headers}34 rows={themesConfig.rows}35 height={props.height ?? "400px"}36 theme={selectedTheme()}37 />38 </div>39 );40}
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { themesConfig, AVAILABLE_THEMES } from "./themes.demo-data";4import "simple-table-core/styles.css";56export function renderThemesDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 let selectedTheme: Theme = options?.theme ?? "light";1112 const wrapper = document.createElement("div");1314 const buttonRow = document.createElement("div");15 buttonRow.style.cssText = "display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px";1617 const tableContainer = document.createElement("div");18 wrapper.appendChild(buttonRow);19 wrapper.appendChild(tableContainer);20 container.appendChild(wrapper);2122 const table = new SimpleTableVanilla(tableContainer, {23 defaultHeaders: themesConfig.headers,24 rows: themesConfig.rows,25 height: options?.height ?? "400px",26 theme: selectedTheme,27 });2829 function renderButtons() {30 buttonRow.innerHTML = "";31 for (const t of AVAILABLE_THEMES) {32 const btn = document.createElement("button");33 btn.textContent = t.label;34 const active = selectedTheme === t.value;35 btn.style.cssText = `padding:6px 14px;border-radius:6px;cursor:pointer;font-size:13px;border:${active ? "2px solid #3b82f6" : "1px solid #d1d5db"};background:${active ? "#eff6ff" : "#fff"};color:${active ? "#1d4ed8" : "#374151"};font-weight:${active ? 600 : 400}`;36 btn.addEventListener("click", () => {37 selectedTheme = t.value;38 table.update({ theme: selectedTheme });39 renderButtons();40 });41 buttonRow.appendChild(btn);42 }43 }4445 renderButtons();46 return table;47}484950// themes.demo-data.ts51// Self-contained demo table setup for this example.52import type { HeaderObject, Theme } from "simple-table-core";535455export const AVAILABLE_THEMES: { value: Theme; label: string }[] = [56 { value: "light", label: "Light" },57 { value: "dark", label: "Dark" },58 { value: "modern-light", label: "Modern Light" },59 { value: "modern-dark", label: "Modern Dark" },60 { value: "neutral", label: "Neutral" },61];6263export const themesHeaders: HeaderObject[] = [64 { accessor: "id", label: "ID", width: 80, type: "number" },65 { accessor: "name", label: "Name", minWidth: 100, width: "1fr", type: "string" },66 { accessor: "email", label: "Email", width: 220, type: "string" },67 { accessor: "department", label: "Department", width: 150, type: "string" },68 { accessor: "status", label: "Status", width: 120, type: "string" },69];7071export const themesData = [72 { id: 1, name: "Dr. Sarah Mitchell", email: "s.mitchell@cityhospital.org", department: "Cardiology", status: "Active" },73 { id: 2, name: "Nurse Emily Chen", email: "e.chen@cityhospital.org", department: "Emergency", status: "Active" },74 { id: 3, name: "Dr. Marcus Williams", email: "m.williams@cityhospital.org", department: "Neurology", status: "Active" },75 { id: 4, name: "Therapist Ana Rodriguez", email: "a.rodriguez@cityhospital.org", department: "Physical Therapy", status: "Active" },76 { id: 5, name: "Dr. Yuki Tanaka", email: "y.tanaka@cityhospital.org", department: "Pediatrics", status: "On Call" },77 { id: 6, name: "Technician Omar Hassan", email: "o.hassan@cityhospital.org", department: "Radiology", status: "Active" },78 { id: 7, name: "Dr. Priya Patel", email: "p.patel@cityhospital.org", department: "Oncology", status: "Active" },79 { id: 8, name: "Coordinator Lisa Kim", email: "l.kim@cityhospital.org", department: "Patient Care", status: "Active" },80 { id: 9, name: "Dr. Giovanni Rossi", email: "g.rossi@cityhospital.org", department: "Surgery", status: "Active" },81 { id: 10, name: "Pharmacist David Lee", email: "d.lee@cityhospital.org", department: "Pharmacy", status: "Active" },82 { id: 11, name: "Nurse Zara Singh", email: "z.singh@cityhospital.org", department: "ICU", status: "Active" },83 { id: 12, name: "Dr. Felix Martinez", email: "f.martinez@cityhospital.org", department: "Orthopedics", status: "Active" },84];8586export const themesConfig = {87 headers: themesHeaders,88 rows: themesData,89} as const;90
Basic Theme Configuration
To apply a theme to Simple Table, simply pass the theme prop with one of the available theme options. The new modern-light and modern-dark themes feature a clean, minimal design that works great for modern applications:
Styling Flags
In addition to themes, Simple Table provides several boolean flags that control specific aspects of table appearance:
Theme Configuration Options
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
theme | Optional | Built-in theme option for styling the table. Choose from predefined themes to quickly customize your table's appearance. Options: light dark neutral modern-light modern-dark custom | |
useHoverRowBackgroundboolean | Optional | Enables a background color change when hovering over a row. This provides better visual feedback for users when interacting with the table. | |
useOddEvenRowBackgroundboolean | Optional | Applies alternating background colors to odd and even rows. This makes it easier to distinguish between adjacent rows, especially in tables with many columns. | |
useOddColumnBackgroundboolean | Optional | Applies alternating background colors to odd and even columns. This can help differentiate between adjacent columns in tables with many columns or narrow columns. | |
columnBordersboolean | Optional | Displays vertical borders between columns. This provides clear visual separation between columns, which is especially useful for spreadsheet-style tables or tables with many columns. |
You can use these flags together with any theme to control the visual presentation of your table:
Tip
When creating custom themes, you can customize the colors used for these styling features using CSS variables like --st-hover-row-background-color and --st-odd-row-background-color. See the Custom Theme documentation for details.