Documentation
Custom Icons
Replace sort, filter, pagination, expand, and editor icons with the icons prop.
Override icons
Pass an icons object — only the keys you set replace the defaults. Values are framework nodes (JSX, VNodes, components, or DOM/SVG elements).
React TSX
Copy
const icons = {sortUp: <SortUpIcon />,sortDown: <SortDownIcon />,filter: <FilterIcon />,expand: <ExpandIcon />,headerExpand: <HeaderExpandIcon />,headerCollapse: <HeaderCollapseIcon />,prev: <PrevIcon />,next: <NextIcon />,drag: <DragIcon />,pinnedLeftIcon: <PinLeftIcon />,pinnedRightIcon: <PinRightIcon />,};<SimpleTableicons={icons}columns={columns}rows={rows}/>
Vue SFC
Copy
import { h } from "vue";const icons = {sortUp: h(SortUpIcon),sortDown: h(SortDownIcon),filter: h(FilterIcon),expand: h(ExpandIcon),headerExpand: h(HeaderExpandIcon),headerCollapse: h(HeaderCollapseIcon),prev: h(PrevIcon),next: h(NextIcon),drag: h(DragIcon),pinnedLeftIcon: h(PinLeftIcon),pinnedRightIcon: h(PinRightIcon),};<SimpleTable:icons="icons":columns="columns":rows="rows"/>
Angular
Copy
icons: AngularIconsConfig = {sortUp: SortUpIconComponent,sortDown: SortDownIconComponent,filter: FilterIconComponent,expand: ExpandIconComponent,headerExpand: HeaderExpandIconComponent,headerCollapse: HeaderCollapseIconComponent,prev: PrevIconComponent,next: NextIconComponent,drag: DragIconComponent,pinnedLeftIcon: PinLeftIconComponent,pinnedRightIcon: PinRightIconComponent,};<simple-table[icons]="icons"[columns]="columns"[rows]="rows"></simple-table>
Svelte
Copy
const icons = {sortUp: SortUpIcon,sortDown: SortDownIcon,filter: FilterIcon,expand: ExpandIcon,headerExpand: HeaderExpandIcon,headerCollapse: HeaderCollapseIcon,prev: PrevIcon,next: NextIcon,drag: DragIcon,pinnedLeftIcon: PinLeftIcon,pinnedRightIcon: PinRightIcon,};<SimpleTable {icons} {columns} {rows} />
Solid TSX
Copy
const icons = {sortUp: <SortUpIcon />,sortDown: <SortDownIcon />,filter: <FilterIcon />,expand: <ExpandIcon />,headerExpand: <HeaderExpandIcon />,headerCollapse: <HeaderCollapseIcon />,prev: <PrevIcon />,next: <NextIcon />,drag: <DragIcon />,pinnedLeftIcon: <PinLeftIcon />,pinnedRightIcon: <PinRightIcon />,};<SimpleTableicons={icons}columns={columns}rows={rows()}/>
TypeScript
Copy
const icons = {sortUp: createSvgIcon("M12 19V5M5 12l7-7 7 7"),sortDown: createSvgIcon("M12 5v14M19 12l-7 7-7-7"),filter: createSvgIcon("M3 4h18l-7 8.5V18l-4 2V12.5L3 4z"),expand: createSvgIcon("M9 5l7 7-7 7"),headerExpand: createSvgIcon("M9 5l7 7-7 7"),headerCollapse: createSvgIcon("M19 9l-7 7-7-7"),prev: createSvgIcon("M15 19l-7-7 7-7"),next: createSvgIcon("M9 5l7 7-7 7"),drag: createSvgIcon("M9 5h2M13 5h2M9 12h2M13 12h2M9 19h2M13 19h2"),pinnedLeftIcon: createSvgIcon("M12 17v5M9 10.76V7a3 3 0 116 0v3.76"),pinnedRightIcon: createSvgIcon("M12 17v5M9 10.76V7a3 3 0 116 0v3.76"),};new SimpleTableVanilla(container, {icons,columns,rows,});
Example
Sort and paginate to see the custom icons. Code or StackBlitz has the full example.
React TSX
Copy
1import {SimpleTable} from "@simple-table/react";import type { Theme, ReactIconsConfig } from "@simple-table/react";2import { customIconsConfig } from "./custom-icons.demo-data";3import "@simple-table/react/styles.css";45const customIcons: ReactIconsConfig = {6 sortUp: (7 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">8 <path d="M12 19V5M5 12l7-7 7 7" />9 </svg>10 ),11 sortDown: (12 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">13 <path d="M12 5v14M19 12l-7 7-7-7" />14 </svg>15 ),16 filter: (17 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">18 <path d="M3 4h18l-7 8.5V18l-4 2V12.5L3 4z" />19 </svg>20 ),21 expand: (22 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">23 <path d="M9 5l7 7-7 7" />24 </svg>25 ),26 next: (27 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">28 <path d="M9 5l7 7-7 7" />29 </svg>30 ),31 prev: (32 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">33 <path d="M15 19l-7-7 7-7" />34 </svg>35 ),36};3738const CustomIconsDemo = ({39 height = "400px",40 theme,41}: {42 height?: string | number;43 theme?: Theme;44}) => {45 return (46 <SimpleTable47 columns={customIconsConfig.headers}48 rows={customIconsConfig.rows}49 icons={customIcons}50 height={height}51 theme={theme}52 />53 );54};5556export default CustomIconsDemo;
Vue SFC
Copy
1<script setup lang="ts">2import { h } from "vue";3import { SimpleTable } from "@simple-table/vue";4import type { Theme, VueIconsConfig } from "@simple-table/vue";5import { customIconsConfig } from "./custom-icons.demo-data";6import "@simple-table/vue/styles.css";78const props = withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {9 height: "400px",10});1112function iconSvg(pathD: string, color: string, strokeWidth = "2.5") {13 return h(14 "svg",15 {16 width: 14,17 height: 14,18 viewBox: "0 0 24 24",19 fill: "none",20 stroke: color,21 strokeWidth,22 strokeLinecap: "round",23 strokeLinejoin: "round",24 },25 [h("path", { d: pathD })],26 );27}2829const icons: VueIconsConfig = {30 sortUp: iconSvg("M12 19V5M5 12l7-7 7 7", "#6366f1"),31 sortDown: iconSvg("M12 5v14M19 12l-7 7-7-7", "#6366f1"),32 filter: iconSvg("M3 4h18l-7 8.5V18l-4 2V12.5L3 4z", "#8b5cf6", "2"),33 expand: iconSvg("M9 5l7 7-7 7", "#6366f1"),34 next: iconSvg("M9 5l7 7-7 7", "#2563eb"),35 prev: iconSvg("M15 19l-7-7 7-7", "#2563eb"),36};37</script>3839<template>40 <SimpleTable41 :columns="customIconsConfig.headers"42 :rows="customIconsConfig.rows"43 :icons="icons"44 :height="props.height"45 :theme="props.theme"46 />47</template>
Angularcustom-icons-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import { SimpleTableComponent } from "@simple-table/angular";3import type { AngularColumnDef, AngularIconsConfig, Row, Theme } from "@simple-table/angular";4import { customIconsConfig } from "./custom-icons.demo-data";5import {6 DemoExpandIconComponent,7 DemoFilterIconComponent,8 DemoNextIconComponent,9 DemoPrevIconComponent,10 DemoSortDownIconComponent,11 DemoSortUpIconComponent,12} from "./table-icons.components";13import "@simple-table/angular/styles.css";1415@Component({16 selector: "custom-icons-demo",17 standalone: true,18 imports: [SimpleTableComponent],19 template: `20 <simple-table21 [rows]="rows"22 [columns]="headers"23 [height]="height"24 [theme]="theme"25 [icons]="icons"26 ></simple-table>27 `,28})29export class CustomIconsDemoComponent {30 @Input() height: string | number = "400px";31 @Input() theme?: Theme;3233 readonly rows: Row[] = customIconsConfig.rows;34 readonly headers: AngularColumnDef[] = customIconsConfig.headers;35 readonly icons: AngularIconsConfig = {36 sortUp: DemoSortUpIconComponent,37 sortDown: DemoSortDownIconComponent,38 filter: DemoFilterIconComponent,39 expand: DemoExpandIconComponent,40 next: DemoNextIconComponent,41 prev: DemoPrevIconComponent,42 };43}444546// custom-icons.demo-data.ts47// Self-contained demo table setup for this example.48import type { AngularColumnDef, Row } from "@simple-table/angular";495051export const customIconsData: Row[] = [52 { id: 1, name: "Alpha Release", version: "1.0.0", status: "released", downloads: 15420, date: "2024-01-15" },53 { id: 2, name: "Beta Release", version: "1.1.0", status: "released", downloads: 28300, date: "2024-03-22" },54 { id: 3, name: "Hotfix", version: "1.1.1", status: "released", downloads: 31050, date: "2024-04-05" },55 { id: 4, name: "Feature Update", version: "1.2.0", status: "released", downloads: 42100, date: "2024-06-10" },56 { id: 5, name: "Security Patch", version: "1.2.1", status: "released", downloads: 45800, date: "2024-07-18" },57 { id: 6, name: "Major Release", version: "2.0.0", status: "released", downloads: 67200, date: "2024-09-01" },58 { id: 7, name: "Minor Update", version: "2.1.0", status: "beta", downloads: 8900, date: "2024-11-12" },59 { id: 8, name: "Next Release", version: "2.2.0", status: "planned", downloads: 0, date: "2025-01-20" },60];6162export const customIconsHeaders: AngularColumnDef[] = [63 { accessor: "id", label: "ID", width: 60, type: "number", sortable: true },64 { accessor: "name", label: "Release", width: 170, type: "string", sortable: true },65 { accessor: "version", label: "Version", width: 100, type: "string", sortable: true },66 { accessor: "status", label: "Status", width: 110, type: "string", sortable: true },67 {68 accessor: "downloads",69 label: "Downloads",70 width: 130,71 type: "number",72 sortable: true,73 valueFormatter: ({ value }) => (value as number).toLocaleString(),74 },75 {76 accessor: "date",77 label: "Date",78 width: 130,79 type: "date",80 sortable: true,81 valueFormatter: ({ value }) => new Date(value as string).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }),82 },83];8485export const customIconsConfig = {86 headers: customIconsHeaders,87 rows: customIconsData,88} as const;899091// table-icons.components.ts92import { Component } from "@angular/core";9394@Component({95 standalone: true,96 selector: "demo-icon-sort-up",97 template: `98 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">99 <path d="M12 19V5M5 12l7-7 7 7" />100 </svg>101 `,102})103export class DemoSortUpIconComponent {}104105@Component({106 standalone: true,107 selector: "demo-icon-sort-down",108 template: `109 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">110 <path d="M12 5v14M19 12l-7 7-7-7" />111 </svg>112 `,113})114export class DemoSortDownIconComponent {}115116@Component({117 standalone: true,118 selector: "demo-icon-filter",119 template: `120 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">121 <path d="M3 4h18l-7 8.5V18l-4 2V12.5L3 4z" />122 </svg>123 `,124})125export class DemoFilterIconComponent {}126127@Component({128 standalone: true,129 selector: "demo-icon-expand",130 template: `131 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">132 <path d="M9 5l7 7-7 7" />133 </svg>134 `,135})136export class DemoExpandIconComponent {}137138@Component({139 standalone: true,140 selector: "demo-icon-next",141 template: `142 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">143 <path d="M9 5l7 7-7 7" />144 </svg>145 `,146})147export class DemoNextIconComponent {}148149@Component({150 standalone: true,151 selector: "demo-icon-prev",152 template: `153 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">154 <path d="M15 19l-7-7 7-7" />155 </svg>156 `,157})158export class DemoPrevIconComponent {}159
Svelte
Copy
1<script lang="ts">2 import { SimpleTable } from "@simple-table/svelte";3 import type { Theme, SvelteIconsConfig } from "@simple-table/svelte";4 import { customIconsConfig } from "./custom-icons.demo-data";5 import IconSortUp from "./icons/IconSortUp.svelte";6 import IconSortDown from "./icons/IconSortDown.svelte";7 import IconFilter from "./icons/IconFilter.svelte";8 import IconExpand from "./icons/IconExpand.svelte";9 import IconNext from "./icons/IconNext.svelte";10 import IconPrev from "./icons/IconPrev.svelte";11 import "@simple-table/svelte/styles.css";1213 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();1415 const icons: SvelteIconsConfig = {16 sortUp: IconSortUp,17 sortDown: IconSortDown,18 filter: IconFilter,19 expand: IconExpand,20 next: IconNext,21 prev: IconPrev,22 };23</script>2425<SimpleTable26 columns={customIconsConfig.headers}27 rows={customIconsConfig.rows}28 {icons}29 {height}30 {theme}31/>
Solid TSX
Copy
1import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";2import { customIconsConfig } from "./custom-icons.demo-data";3import "@simple-table/solid/styles.css";45const customIcons = {6 sortUp: (7 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">8 <path d="M12 19V5M5 12l7-7 7 7" />9 </svg>10 ),11 sortDown: (12 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">13 <path d="M12 5v14M19 12l-7 7-7-7" />14 </svg>15 ),16 filter: (17 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">18 <path d="M3 4h18l-7 8.5V18l-4 2V12.5L3 4z" />19 </svg>20 ),21 expand: (22 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">23 <path d="M9 5l7 7-7 7" />24 </svg>25 ),26 next: (27 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">28 <path d="M9 5l7 7-7 7" />29 </svg>30 ),31 prev: (32 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">33 <path d="M15 19l-7-7 7-7" />34 </svg>35 ),36};3738export default function CustomIconsDemo(props: { height?: string | number; theme?: Theme }) {39 return (40 <SimpleTable41 columns={customIconsConfig.headers}42 rows={customIconsConfig.rows}43 height={props.height ?? "400px"}44 theme={props.theme}45 icons={customIcons}46 />47 );48}
TypeScriptCustomIconsDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { customIconsConfig, buildVanillaCustomIcons } from "./custom-icons.demo-data";4import "simple-table-core/styles.css";56export function renderCustomIconsDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 const table = new SimpleTableVanilla(container, {11 columns: [...customIconsConfig.headers],12 rows: customIconsConfig.rows,13 height: options?.height ?? "400px",14 theme: options?.theme,15 icons: buildVanillaCustomIcons(),16 });17 return table;18}192021// custom-icons.demo-data.ts22// Self-contained demo table setup for this example.23import type { ColumnDef, Row } from "simple-table-core";242526export const customIconsData: Row[] = [27 { id: 1, name: "Alpha Release", version: "1.0.0", status: "released", downloads: 15420, date: "2024-01-15" },28 { id: 2, name: "Beta Release", version: "1.1.0", status: "released", downloads: 28300, date: "2024-03-22" },29 { id: 3, name: "Hotfix", version: "1.1.1", status: "released", downloads: 31050, date: "2024-04-05" },30 { id: 4, name: "Feature Update", version: "1.2.0", status: "released", downloads: 42100, date: "2024-06-10" },31 { id: 5, name: "Security Patch", version: "1.2.1", status: "released", downloads: 45800, date: "2024-07-18" },32 { id: 6, name: "Major Release", version: "2.0.0", status: "released", downloads: 67200, date: "2024-09-01" },33 { id: 7, name: "Minor Update", version: "2.1.0", status: "beta", downloads: 8900, date: "2024-11-12" },34 { id: 8, name: "Next Release", version: "2.2.0", status: "planned", downloads: 0, date: "2025-01-20" },35];3637export const customIconsHeaders: ColumnDef[] = [38 { accessor: "id", label: "ID", width: 60, type: "number", sortable: true },39 { accessor: "name", label: "Release", width: 170, type: "string", sortable: true },40 { accessor: "version", label: "Version", width: 100, type: "string", sortable: true },41 { accessor: "status", label: "Status", width: 110, type: "string", sortable: true },42 {43 accessor: "downloads",44 label: "Downloads",45 width: 130,46 type: "number",47 sortable: true,48 valueFormatter: ({ value }) => (value as number).toLocaleString(),49 },50 {51 accessor: "date",52 label: "Date",53 width: 130,54 type: "date",55 sortable: true,56 valueFormatter: ({ value }) => new Date(value as string).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }),57 },58];5960export const customIconsConfig = {61 headers: customIconsHeaders,62 rows: customIconsData,63} as const;6465export function createSvgIcon(pathD: string, color = "#3b82f6", size = 14): SVGSVGElement {66 const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");67 svg.setAttribute("width", String(size));68 svg.setAttribute("height", String(size));69 svg.setAttribute("viewBox", "0 0 24 24");70 svg.setAttribute("fill", "none");71 svg.setAttribute("stroke", color);72 svg.setAttribute("stroke-width", "2.5");73 svg.setAttribute("stroke-linecap", "round");74 svg.setAttribute("stroke-linejoin", "round");75 const path = document.createElementNS("http://www.w3.org/2000/svg", "path");76 path.setAttribute("d", pathD);77 svg.appendChild(path);78 return svg;79}8081export const ICON_PATHS = {82 sortUp: "M12 19V5M5 12l7-7 7 7",83 sortDown: "M12 5v14M19 12l-7 7-7-7",84 filter: "M3 4h18l-7 8.5V18l-4 2V12.5L3 4z",85 expand: "M9 5l7 7-7 7",86 next: "M9 5l7 7-7 7",87 prev: "M15 19l-7-7 7-7",88} as const;8990export function buildVanillaCustomIcons() {91 return {92 sortUp: createSvgIcon(ICON_PATHS.sortUp, "#6366f1"),93 sortDown: createSvgIcon(ICON_PATHS.sortDown, "#6366f1"),94 filter: createSvgIcon(ICON_PATHS.filter, "#8b5cf6"),95 expand: createSvgIcon(ICON_PATHS.expand, "#6366f1"),96 next: createSvgIcon(ICON_PATHS.next, "#2563eb"),97 prev: createSvgIcon(ICON_PATHS.prev, "#2563eb"),98 };99}100
Props
Icons Configuration
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
iconsIconsConfig | Optional | Partial icon map. Unset keys keep the built-in icons. | |
icons.sortUpIconElement | Optional | Ascending sort indicator in column headers. | |
icons.sortDownIconElement | Optional | Descending sort indicator in column headers. | |
icons.filterIconElement | Optional | Column filter button. | |
icons.expandIconElement | Optional | Collapsed row-group expand control. | |
icons.headerExpandIconElement | Optional | Collapsed nested column header. | |
icons.headerCollapseIconElement | Optional | Expanded nested column header. | |
icons.prevIconElement | Optional | Pagination previous button. | |
icons.nextIconElement | Optional | Pagination next button. | |
icons.dragIconElement | Optional | Column editor drag handle. | |
icons.pinnedLeftIconIconElement | Optional | Column editor pin-left control. | |
icons.pinnedRightIconIconElement | Optional | Column editor pin-right control. |