Documentation
Cell Clicking
React to cell clicks with onCellClick.
Handle cell clicks
Pass onCellClick. Use accessor, value, and row for navigation, modals, or other actions.
React TSX
Copy
const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};<SimpleTablecolumns={columns}rows={rows}onCellClick={handleCellClick}/>
Angular
Copy
const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};<simple-table[columns]="columns"[rows]="rows"(cellClick)="handleCellClick($event)"></simple-table>
Vue SFC
Copy
<script setup>const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};</script><template><SimpleTable:columns="columns":rows="rows":on-cell-click="handleCellClick"/></template>
Svelte
Copy
<script>const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};</script><SimpleTable{columns}{rows}onCellClick={handleCellClick}/>
Solid TSX
Copy
const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};<SimpleTablecolumns={columns}rows={rows()}onCellClick={handleCellClick}/>
TypeScript
Copy
const handleCellClick = ({ accessor, value, row, rowIndex, colIndex }) => {// open a detail view, navigate, filter, etc.console.log(accessor, value, row.id, rowIndex, colIndex);};new SimpleTableVanilla(container, {columns,rows,onCellClick: handleCellClick,});
Example
Click cells to filter, toggle status, or open details. Use Code or StackBlitz for the full example.
Last Click:Click any cell to see interaction details...
React TSX
Copy
1import { useState, useMemo } from "react";2import { SimpleTable } from "@simple-table/react";3import type {4 Theme,5 ReactColumnDef,6 CellClickProps7} from "@simple-table/react";8import {9 cellClickingHeaders,10 cellClickingData,11 CELL_CLICKING_STATUSES12} from "./cell-clicking.demo-data";13import type { ProjectTask } from "./cell-clicking.demo-data";14import "@simple-table/react/styles.css";1516const CellClickingDemo = ({ height, theme }: { height?: string | number; theme?: Theme }) => {17 const [clickInfo, setClickInfo] = useState("");18 const [selectedTask, setSelectedTask] = useState<ProjectTask | null>(null);19 const [rows, setRows] = useState<ProjectTask[]>([...cellClickingData]);2021 const headers: ReactColumnDef<ProjectTask>[] = useMemo(22 () =>23 cellClickingHeaders.map((h) => {24 if (h.accessor === "priority") {25 return {26 ...h,27 cellRenderer: ({ row }) => {28 const p = String(row.priority);29 return (30 <span31 style={{32 color: p === "High" ? "#ef4444" : p === "Medium" ? "#f59e0b" : "#10b981",33 fontWeight: "bold",34 cursor: "pointer"35 }}36 title="Click to filter by priority"37 >38 {p}39 </span>40 );41 }42 };43 }44 if (h.accessor === "status") {45 return {46 ...h,47 cellRenderer: ({ row }) => {48 const s = String(row.status);49 const bg =50 s === "Completed" ? "#dcfce7" : s === "In Progress" ? "#fef3c7" : "#fee2e2";51 const color =52 s === "Completed" ? "#166534" : s === "In Progress" ? "#92400e" : "#991b1b";53 return (54 <span55 style={{56 backgroundColor: bg,57 color,58 padding: "4px 8px",59 borderRadius: 4,60 fontSize: 12,61 fontWeight: "bold",62 cursor: "pointer"63 }}64 title="Click to change status"65 >66 {s}67 </span>68 );69 }70 };71 }72 if (h.accessor === "details") {73 return {74 ...h,75 cellRenderer: () => (76 <button77 style={{78 backgroundColor: "#3b82f6",79 color: "white",80 border: "none",81 padding: "6px 12px",82 borderRadius: 4,83 cursor: "pointer",84 fontSize: 12,85 fontWeight: "bold"86 }}87 title="Click to view task details"88 >89 View Details90 </button>91 )92 };93 }94 return h;95 }),96 [],97 );9899 const handleCellClick = ({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) => {100 switch (accessor) {101 case "priority": {102 setClickInfo(`Filtering by ${value} priority`);103 setRows(cellClickingData.filter((t) => t.priority === value));104 break;105 }106 case "status": {107 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));108 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];109 setRows((prev) => prev.map((t) => (t.id === row.id ? { ...t, status: next } : t)));110 setClickInfo(`Status changed from "${value}" to "${next}"`);111 break;112 }113 case "details":114 setSelectedTask(row);115 setClickInfo(`Opening details for: ${row.task}`);116 break;117 case "estimatedHours": {118 const newVal = Math.min(row.estimatedHours + 2, 40);119 setRows((prev) =>120 prev.map((t) => (t.id === row.id ? { ...t, estimatedHours: newVal } : t)),121 );122 setClickInfo(`Est. hours: ${row.estimatedHours}h → ${newVal}h`);123 break;124 }125 case "completedHours": {126 const newVal = Math.min(row.completedHours + 1, row.estimatedHours);127 setRows((prev) =>128 prev.map((t) => (t.id === row.id ? { ...t, completedHours: newVal } : t)),129 );130 setClickInfo(`Done hours: ${row.completedHours}h → ${newVal}h`);131 break;132 }133 default:134 setClickInfo(`Clicked [${accessor}] = "${value}" (row ${rowIndex})`);135 }136 };137138 const isDark = theme === "modern-dark" || theme === "dark" || theme === "modern-black";139140 return (141 <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>142 <div143 style={{144 padding: 12,145 backgroundColor: isDark ? "#374151" : "#f3f4f6",146 borderRadius: 8,147 border: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,148 minHeight: 48,149 display: "flex",150 alignItems: "center"151 }}152 >153 <strong style={{ marginRight: 8, color: isDark ? "#f9fafb" : "#1f2937" }}>154 Last Click:155 </strong>156 <span style={{ color: isDark ? "#d1d5db" : "#4b5563" }}>157 {clickInfo || "Click any cell to see interaction details..."}158 </span>159 </div>160161 {selectedTask && (162 <div163 style={{164 position: "fixed",165 inset: 0,166 backgroundColor: "rgba(0,0,0,0.5)",167 display: "flex",168 alignItems: "center",169 justifyContent: "center",170 zIndex: 1000171 }}172 >173 <div174 style={{175 backgroundColor: isDark ? "#1f2937" : "white",176 padding: 24,177 borderRadius: 8,178 maxWidth: 500,179 width: "90%"180 }}181 >182 <h3 style={{ margin: "0 0 16px", color: isDark ? "#f9fafb" : "#1f2937" }}>183 Task Details184 </h3>185 {(["task", "details", "assignee", "status", "priority"] as const).map((key) => (186 <p key={key} style={{ margin: "8px 0", color: isDark ? "#d1d5db" : "#4b5563" }}>187 <strong>{key.charAt(0).toUpperCase() + key.slice(1)}:</strong> {selectedTask[key]}188 </p>189 ))}190 <button191 onClick={() => setSelectedTask(null)}192 style={{193 marginTop: 16,194 backgroundColor: "#3b82f6",195 color: "white",196 border: "none",197 padding: "8px 16px",198 borderRadius: 4,199 cursor: "pointer",200 fontWeight: "bold"201 }}202 >203 Close204 </button>205 </div>206 </div>207 )}208209 <SimpleTable210 columnResizing211 columns={headers}212 getRowId={({ row }) => row.id}213 height={height ?? "320px"}214 onCellClick={handleCellClick}215 rows={rows}216 theme={theme}217 />218 </div>219 );220};221222export default CellClickingDemo;
Angularcell-click-details-cell.component.ts
Copy
1import { Component } from "@angular/core";23@Component({4 standalone: true,5 selector: "demo-cell-click-details",6 template: `7 <button8 type="button"9 style="background:#3b82f6;color:white;border:none;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px;font-weight:bold;"10 >11 View Details12 </button>13 `,14})15export class CellClickDetailsCellComponent {}161718// cell-click-priority-cell.component.ts19import { Component, Input } from "@angular/core";20import type { ProjectTask } from "./cell-clicking.demo-data";2122@Component({23 standalone: true,24 selector: "demo-cell-click-priority",25 template: `26 <span [style.color]="color" style="font-weight:bold;cursor:pointer;" title="Click to filter by priority">{{ row.priority }}</span>27 `,28})29export class CellClickPriorityCellComponent {30 @Input({ required: true }) row!: ProjectTask;3132 get color(): string {33 const p = this.row.priority;34 if (p === "High") return "#ef4444";35 if (p === "Medium") return "#f59e0b";36 return "#10b981";37 }38}394041// cell-click-status-cell.component.ts42import { Component, Input } from "@angular/core";43import type { ProjectTask } from "./cell-clicking.demo-data";4445@Component({46 standalone: true,47 selector: "demo-cell-click-status",48 template: `49 <span50 [style.background]="bg"51 [style.color]="fg"52 style="padding:4px 8px;border-radius:4px;font-size:12px;font-weight:bold;cursor:pointer;"53 title="Click to change status"54 >{{ row.status }}</span>55 `,56})57export class CellClickStatusCellComponent {58 @Input({ required: true }) row!: ProjectTask;5960 get bg(): string {61 const s = this.row.status;62 if (s === "Completed") return "#dcfce7";63 if (s === "In Progress") return "#fef3c7";64 return "#fee2e2";65 }6667 get fg(): string {68 const s = this.row.status;69 if (s === "Completed") return "#166534";70 if (s === "In Progress") return "#92400e";71 return "#991b1b";72 }73}747576// cell-clicking-demo.component.ts77import { NgIf } from "@angular/common";78import { Component, Input } from "@angular/core";79import { SimpleTableImports } from "@simple-table/angular";80import type { AngularColumnDef, CellClickProps, GetRowIdParams, Theme } from "@simple-table/angular";81import { cellClickingData, cellClickingHeaders, CELL_CLICKING_STATUSES } from "./cell-clicking.demo-data";82import type { ProjectTask } from "./cell-clicking.demo-data";83import { CellClickDetailsCellComponent } from "./cell-click-details-cell.component";84import { CellClickPriorityCellComponent } from "./cell-click-priority-cell.component";85import { CellClickStatusCellComponent } from "./cell-click-status-cell.component";86import "@simple-table/angular/styles.css";8788@Component({89 selector: "cell-clicking-demo",90 standalone: true,91 imports: [SimpleTableImports, NgIf],92 template: `93 <div style="display: flex; flex-direction: column; gap: 16px">94 <div [style.padding]="'12px'" [style.background-color]="isDark ? '#374151' : '#f3f4f6'" [style.border-radius]="'8px'" [style.border]="'1px solid ' + (isDark ? '#4b5563' : '#d1d5db')" [style.min-height]="'48px'" style="display: flex; align-items: center">95 <strong [style.margin-right]="'8px'" [style.color]="isDark ? '#f9fafb' : '#1f2937'">Last Click:</strong>96 <span [style.color]="isDark ? '#d1d5db' : '#4b5563'">{{ clickInfo || 'Click any cell to see interaction details...' }}</span>97 </div>9899 <div *ngIf="selectedTask" style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1000">100 <div [style.background]="isDark ? '#1f2937' : 'white'" style="padding: 24px; border-radius: 8px; max-width: 500px; width: 90%">101 <h3 [style.color]="isDark ? '#f9fafb' : '#1f2937'" style="margin: 0 0 16px">Task Details</h3>102 <p [style.color]="isDark ? '#d1d5db' : '#4b5563'" style="margin: 8px 0"><strong>Task:</strong> {{ selectedTask.task }}</p>103 <p [style.color]="isDark ? '#d1d5db' : '#4b5563'" style="margin: 8px 0"><strong>Details:</strong> {{ selectedTask.details }}</p>104 <p [style.color]="isDark ? '#d1d5db' : '#4b5563'" style="margin: 8px 0"><strong>Assignee:</strong> {{ selectedTask.assignee }}</p>105 <p [style.color]="isDark ? '#d1d5db' : '#4b5563'" style="margin: 8px 0"><strong>Status:</strong> {{ selectedTask.status }}</p>106 <p [style.color]="isDark ? '#d1d5db' : '#4b5563'" style="margin: 8px 0"><strong>Priority:</strong> {{ selectedTask.priority }}</p>107 <button (click)="selectedTask = null" style="margin-top: 16px; background: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-weight: bold">Close</button>108 </div>109 </div>110111 <simple-table112 [getRowId]="getRowId"113 [columnResizing]="true"114 [columns]="headers"115 [height]="height"116 (cellClick)="handleCellClick($event)"117 [rows]="rows"118 [theme]="theme"119 ></simple-table>120 </div>121 `,122})123export class CellClickingDemoComponent {124 @Input() height: string | number = "320px";125 @Input() theme?: Theme;126127 clickInfo = "";128 selectedTask: ProjectTask | null = null;129 rows: ProjectTask[] = [...cellClickingData];130131 get isDark() {132 return this.theme === "modern-dark" || this.theme === "dark" || this.theme === "modern-black";133 }134135 readonly headers: AngularColumnDef<ProjectTask>[] = cellClickingHeaders.map((h) => {136 if (h.accessor === "priority") {137 return { ...h, cellRenderer: CellClickPriorityCellComponent };138 }139 if (h.accessor === "status") {140 return { ...h, cellRenderer: CellClickStatusCellComponent };141 }142 if (h.accessor === "details") {143 return { ...h, cellRenderer: CellClickDetailsCellComponent };144 }145 return { ...h };146 });147148 handleCellClick = ({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) => {149 switch (accessor) {150 case "priority":151 this.clickInfo = `Filtering by ${value} priority`;152 this.rows = cellClickingData.filter((t) => t.priority === value);153 break;154 case "status": {155 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));156 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];157 this.rows = this.rows.map((t) => (t.id === row.id ? { ...t, status: next } : t));158 this.clickInfo = `Status: "${value}" → "${next}"`;159 break;160 }161 case "details":162 this.selectedTask = row;163 this.clickInfo = `Opening details for: ${row.task}`;164 break;165 case "estimatedHours": {166 const n = Math.min(row.estimatedHours + 2, 40);167 this.rows = this.rows.map((t) => (t.id === row.id ? { ...t, estimatedHours: n } : t));168 this.clickInfo = `Est. hours: ${row.estimatedHours}h → ${n}h`;169 break;170 }171 case "completedHours": {172 const n = Math.min(row.completedHours + 1, row.estimatedHours);173 this.rows = this.rows.map((t) => (t.id === row.id ? { ...t, completedHours: n } : t));174 this.clickInfo = `Done hours: ${row.completedHours}h → ${n}h`;175 break;176 }177 default:178 this.clickInfo = `Clicked [${accessor}] = "${value}" (row ${rowIndex})`;179 }180 };181182 getRowId = ({ row }: GetRowIdParams<ProjectTask>) => row.id;183}184185186// cell-clicking.demo-data.ts187// Self-contained demo table setup for this example.188import type { AngularColumnDef } from "@simple-table/angular";189190export type ProjectTask = {191 id: number;192 task: string;193 assignee: string;194 priority: string;195 status: string;196 dueDate: string;197 estimatedHours: number;198 completedHours: number;199 details: string;200};201202export const STATUSES = ["Not Started", "In Progress", "Completed"];203204export const cellClickingData: ProjectTask[] = [205 {206 id: 1001,207 task: "Design login page mockups",208 assignee: "Sarah Chen",209 priority: "High",210 status: "In Progress",211 dueDate: "2024-02-15",212 estimatedHours: 8,213 completedHours: 5,214 details: "Create responsive login page designs with modern UI patterns",215 },216 {217 id: 1002,218 task: "Implement user authentication API",219 assignee: "Marcus Rodriguez",220 priority: "High",221 status: "Not Started",222 dueDate: "2024-02-20",223 estimatedHours: 16,224 completedHours: 0,225 details: "Build secure JWT-based authentication system with OAuth integration",226 },227 {228 id: 1003,229 task: "Write unit tests for payment module",230 assignee: "Luna Martinez",231 priority: "Medium",232 status: "Completed",233 dueDate: "2024-02-10",234 estimatedHours: 12,235 completedHours: 12,236 details: "Comprehensive test coverage for payment processing functionality",237 },238 {239 id: 1004,240 task: "Update documentation for API endpoints",241 assignee: "Kai Thompson",242 priority: "Low",243 status: "In Progress",244 dueDate: "2024-02-25",245 estimatedHours: 6,246 completedHours: 3,247 details: "Update Swagger documentation and add usage examples",248 },249 {250 id: 1005,251 task: "Performance optimization for dashboard",252 assignee: "Zara Kim",253 priority: "Medium",254 status: "Not Started",255 dueDate: "2024-03-01",256 estimatedHours: 20,257 completedHours: 0,258 details: "Optimize rendering performance and implement lazy loading",259 },260 {261 id: 1006,262 task: "Mobile responsiveness testing",263 assignee: "Tyler Anderson",264 priority: "High",265 status: "In Progress",266 dueDate: "2024-02-18",267 estimatedHours: 10,268 completedHours: 7,269 details: "Test application across various mobile devices and screen sizes",270 },271 {272 id: 1007,273 task: "Setup CI/CD pipeline",274 assignee: "Phoenix Lee",275 priority: "Medium",276 status: "Completed",277 dueDate: "2024-02-08",278 estimatedHours: 14,279 completedHours: 14,280 details: "Automated testing and deployment pipeline using GitHub Actions",281 },282 {283 id: 1008,284 task: "Database migration scripts",285 assignee: "River Jackson",286 priority: "Low",287 status: "Not Started",288 dueDate: "2024-02-28",289 estimatedHours: 8,290 completedHours: 0,291 details: "Create migration scripts for database schema updates",292 },293];294295export const cellClickingHeaders: AngularColumnDef<ProjectTask>[] = [296 { accessor: "id", label: "Task ID", width: 80, sortable: true, type: "number" },297 {298 accessor: "task",299 label: "Task Name",300 minWidth: 150,301 width: "1fr",302 sortable: true,303 type: "string",304 },305 { accessor: "assignee", label: "Assignee", width: 120, sortable: true, type: "string" },306 { accessor: "priority", label: "Priority", width: 100, sortable: true, type: "string" },307 { accessor: "status", label: "Status", width: 120, sortable: true, type: "string" },308 { accessor: "dueDate", label: "Due Date", width: 120, sortable: true, type: "date" },309 { accessor: "estimatedHours", label: "Est. Hours", width: 100, sortable: true, type: "number" },310 { accessor: "completedHours", label: "Done Hours", width: 100, sortable: true, type: "number" },311 { accessor: "details", label: "View Details", width: 120, type: "other" },312];313314export const cellClickingConfig = {315 headers: cellClickingHeaders,316 rows: cellClickingData,317};318319export { STATUSES as CELL_CLICKING_STATUSES };320
Vue SFC
Copy
1<script setup lang="ts">2import { ref, computed, h } from "vue";3import { SimpleTable } from "@simple-table/vue";4import type { Theme, VueColumnDef, CellClickProps, CellRendererProps, GetRowIdParams } from "@simple-table/vue";5import { cellClickingHeaders, cellClickingData, CELL_CLICKING_STATUSES } from "./cell-clicking.demo-data";6import type { ProjectTask } from "./cell-clicking.demo-data";7import "@simple-table/vue/styles.css";89const props = withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {10 height: "320px",11});1213const clickInfo = ref("");14const selectedTask = ref<ProjectTask | null>(null);15const rows = ref<ProjectTask[]>([...cellClickingData]);1617const headers: VueColumnDef<ProjectTask>[] = cellClickingHeaders.map((col) => {18 if (col.accessor === "priority") {19 return {20 ...col,21 cellRenderer: ({ row }: CellRendererProps<ProjectTask>) => {22 const p = row.priority;23 const color = p === "High" ? "#ef4444" : p === "Medium" ? "#f59e0b" : "#10b981";24 return h(25 "span",26 {27 style: { color, fontWeight: "bold", cursor: "pointer" },28 title: "Click to filter by priority",29 },30 p,31 );32 },33 };34 }35 if (col.accessor === "status") {36 return {37 ...col,38 cellRenderer: ({ row }: CellRendererProps<ProjectTask>) => {39 const s = row.status;40 const bg = s === "Completed" ? "#dcfce7" : s === "In Progress" ? "#fef3c7" : "#fee2e2";41 const color = s === "Completed" ? "#166534" : s === "In Progress" ? "#92400e" : "#991b1b";42 return h(43 "span",44 {45 style: {46 backgroundColor: bg,47 color,48 padding: "4px 8px",49 borderRadius: "4px",50 fontSize: "12px",51 fontWeight: "bold",52 cursor: "pointer",53 },54 title: "Click to change status",55 },56 s,57 );58 },59 };60 }61 if (col.accessor === "details") {62 return {63 ...col,64 cellRenderer: () =>65 h(66 "button",67 {68 style: {69 background: "#3b82f6",70 color: "white",71 border: "none",72 padding: "6px 12px",73 borderRadius: "4px",74 cursor: "pointer",75 fontSize: "12px",76 fontWeight: "bold",77 },78 title: "Click to view task details",79 },80 "View Details",81 ),82 };83 }84 return { ...col };85});8687const isDark = computed(() => props.theme === "modern-dark" || props.theme === "dark" || props.theme === "modern-black");8889const getRowId = ({ row }: GetRowIdParams<ProjectTask>) => row.id;9091function handleCellClick({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) {92 switch (accessor) {93 case "priority":94 clickInfo.value = `Filtering by ${value} priority`;95 rows.value = cellClickingData.filter((t) => t.priority === value);96 break;97 case "status": {98 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));99 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];100 rows.value = rows.value.map((t) => (t.id === row.id ? { ...t, status: next } : t));101 clickInfo.value = `Status: "${value}" → "${next}"`;102 break;103 }104 case "details":105 selectedTask.value = row;106 clickInfo.value = `Opening details for: ${row.task}`;107 break;108 case "estimatedHours": {109 const n = Math.min(row.estimatedHours + 2, 40);110 rows.value = rows.value.map((t) => (t.id === row.id ? { ...t, estimatedHours: n } : t));111 clickInfo.value = `Est. hours: ${row.estimatedHours}h → ${n}h`;112 break;113 }114 case "completedHours": {115 const n = Math.min(row.completedHours + 1, row.estimatedHours);116 rows.value = rows.value.map((t) => (t.id === row.id ? { ...t, completedHours: n } : t));117 clickInfo.value = `Done hours: ${row.completedHours}h → ${n}h`;118 break;119 }120 default:121 clickInfo.value = `Clicked [${accessor}] = "${value}" (row ${rowIndex})`;122 }123}124</script>125126<template>127 <div style="display: flex; flex-direction: column; gap: 16px">128 <div129 :style="{130 padding: '12px',131 backgroundColor: isDark ? '#374151' : '#f3f4f6',132 borderRadius: '8px',133 border: '1px solid ' + (isDark ? '#4b5563' : '#d1d5db'),134 minHeight: '48px',135 display: 'flex',136 alignItems: 'center',137 }"138 >139 <strong :style="{ marginRight: '8px', color: isDark ? '#f9fafb' : '#1f2937' }">Last Click:</strong>140 <span :style="{ color: isDark ? '#d1d5db' : '#4b5563' }">141 {{ clickInfo || "Click any cell to see interaction details..." }}142 </span>143 </div>144145 <div146 v-if="selectedTask"147 style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1000"148 >149 <div150 :style="{ background: isDark ? '#1f2937' : 'white', padding: '24px', borderRadius: '8px', maxWidth: '500px', width: '90%' }"151 >152 <h3 :style="{ margin: '0 0 16px', color: isDark ? '#f9fafb' : '#1f2937' }">Task Details</h3>153 <p :style="{ margin: '8px 0', color: isDark ? '#d1d5db' : '#4b5563' }"><strong>Task:</strong> {{ selectedTask.task }}</p>154 <p :style="{ margin: '8px 0', color: isDark ? '#d1d5db' : '#4b5563' }"><strong>Details:</strong> {{ selectedTask.details }}</p>155 <p :style="{ margin: '8px 0', color: isDark ? '#d1d5db' : '#4b5563' }"><strong>Assignee:</strong> {{ selectedTask.assignee }}</p>156 <p :style="{ margin: '8px 0', color: isDark ? '#d1d5db' : '#4b5563' }"><strong>Status:</strong> {{ selectedTask.status }}</p>157 <p :style="{ margin: '8px 0', color: isDark ? '#d1d5db' : '#4b5563' }"><strong>Priority:</strong> {{ selectedTask.priority }}</p>158 <button159 @click="selectedTask = null"160 style="margin-top: 16px; background: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-weight: bold"161 >162 Close163 </button>164 </div>165 </div>166167 <SimpleTable168 :column-resizing="true"169 :columns="headers"170 :get-row-id="getRowId"171 :height="height"172 :on-cell-click="handleCellClick"173 :rows="rows"174 :theme="theme"175 />176 </div>177</template>
SvelteCellClickDetailsCell.svelte
Copy
1<button2 type="button"3 style="background:#3b82f6;color:white;border:none;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px;font-weight:bold;"4>5 View Details6</button>789// CellClickPriorityCell.svelte10<script lang="ts">11 import type { CellRendererProps } from "@simple-table/svelte";12 import type { ProjectTask } from "./cell-clicking.demo-data";1314 let { row }: CellRendererProps<ProjectTask> = $props();15 const p = $derived(String(row.priority));16 const color = $derived(p === "High" ? "#ef4444" : p === "Medium" ? "#f59e0b" : "#10b981");17</script>1819<span style="color:{color};font-weight:bold;cursor:pointer;" title="Click to filter by priority">{p}</span>202122// CellClickStatusCell.svelte23<script lang="ts">24 import type { CellRendererProps } from "@simple-table/svelte";25 import type { ProjectTask } from "./cell-clicking.demo-data";2627 let { row }: CellRendererProps<ProjectTask> = $props();28 const s = $derived(String(row.status));29 const bg = $derived(s === "Completed" ? "#dcfce7" : s === "In Progress" ? "#fef3c7" : "#fee2e2");30 const c = $derived(s === "Completed" ? "#166534" : s === "In Progress" ? "#92400e" : "#991b1b");31</script>3233<span34 style="background:{bg};color:{c};padding:4px 8px;border-radius:4px;font-size:12px;font-weight:bold;cursor:pointer;"35 title="Click to change status">{s}</span>363738// CellClickingDemo.svelte39<script lang="ts">40 import { SimpleTable } from "@simple-table/svelte";41 import type { Theme, SvelteColumnDef, CellClickProps, GetRowIdParams } from "@simple-table/svelte";42 import { cellClickingHeaders, cellClickingData, CELL_CLICKING_STATUSES } from "./cell-clicking.demo-data";43 import type { ProjectTask } from "./cell-clicking.demo-data";44 import CellClickPriorityCell from "./CellClickPriorityCell.svelte";45 import CellClickStatusCell from "./CellClickStatusCell.svelte";46 import CellClickDetailsCell from "./CellClickDetailsCell.svelte";47 import "@simple-table/svelte/styles.css";4849 let { height = "320px", theme }: { height?: string | number; theme?: Theme } = $props();5051 let clickInfo = $state("");52 let selectedTask: ProjectTask | null = $state(null);53 let rows: ProjectTask[] = $state([...cellClickingData]);5455 const headers: SvelteColumnDef<ProjectTask>[] = cellClickingHeaders.map((h) => {56 if (h.accessor === "priority") return { ...h, cellRenderer: CellClickPriorityCell };57 if (h.accessor === "status") return { ...h, cellRenderer: CellClickStatusCell };58 if (h.accessor === "details") return { ...h, cellRenderer: CellClickDetailsCell };59 return { ...h };60 });6162 const getRowId = ({ row }: GetRowIdParams<ProjectTask>) => row.id;6364 let isDark = $derived(theme === "modern-dark" || theme === "dark" || theme === "modern-black");6566 function handleCellClick({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) {67 switch (accessor) {68 case "priority":69 clickInfo = `Filtering by ${value} priority`;70 rows = cellClickingData.filter((t) => t.priority === value);71 break;72 case "status": {73 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));74 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];75 rows = rows.map((t) => (t.id === row.id ? { ...t, status: next } : t));76 clickInfo = `Status: "${value}" → "${next}"`;77 break;78 }79 case "details":80 selectedTask = row;81 clickInfo = `Opening details for: ${row.task}`;82 break;83 case "estimatedHours": {84 const n = Math.min(row.estimatedHours + 2, 40);85 rows = rows.map((t) => (t.id === row.id ? { ...t, estimatedHours: n } : t));86 clickInfo = `Est. hours: ${row.estimatedHours}h → ${n}h`;87 break;88 }89 case "completedHours": {90 const n = Math.min(row.completedHours + 1, row.estimatedHours);91 rows = rows.map((t) => (t.id === row.id ? { ...t, completedHours: n } : t));92 clickInfo = `Done hours: ${row.completedHours}h → ${n}h`;93 break;94 }95 default:96 clickInfo = `Clicked [${accessor}] = "${value}" (row ${rowIndex})`;97 }98 }99</script>100101<div style="display: flex; flex-direction: column; gap: 16px">102 <div style="padding: 12px; background-color: {isDark ? '#374151' : '#f3f4f6'}; border-radius: 8px; border: 1px solid {isDark ? '#4b5563' : '#d1d5db'}; min-height: 48px; display: flex; align-items: center;">103 <strong style="margin-right: 8px; color: {isDark ? '#f9fafb' : '#1f2937'}">Last Click:</strong>104 <span style="color: {isDark ? '#d1d5db' : '#4b5563'}">{clickInfo || "Click any cell to see interaction details..."}</span>105 </div>106107 {#if selectedTask}108 <div style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1000">109 <div style="background: {isDark ? '#1f2937' : 'white'}; padding: 24px; border-radius: 8px; max-width: 500px; width: 90%;">110 <h3 style="margin: 0 0 16px; color: {isDark ? '#f9fafb' : '#1f2937'}">Task Details</h3>111 <p style="margin: 8px 0; color: {isDark ? '#d1d5db' : '#4b5563'}"><strong>Task:</strong> {selectedTask.task}</p>112 <p style="margin: 8px 0; color: {isDark ? '#d1d5db' : '#4b5563'}"><strong>Details:</strong> {selectedTask.details}</p>113 <p style="margin: 8px 0; color: {isDark ? '#d1d5db' : '#4b5563'}"><strong>Assignee:</strong> {selectedTask.assignee}</p>114 <p style="margin: 8px 0; color: {isDark ? '#d1d5db' : '#4b5563'}"><strong>Status:</strong> {selectedTask.status}</p>115 <p style="margin: 8px 0; color: {isDark ? '#d1d5db' : '#4b5563'}"><strong>Priority:</strong> {selectedTask.priority}</p>116 <button117 onclick={() => selectedTask = null}118 style="margin-top: 16px; background: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-weight: bold"119 >120 Close121 </button>122 </div>123 </div>124 {/if}125126 <SimpleTable127 columnResizing={true}128 columns={headers}129 {getRowId}130 {height}131 onCellClick={handleCellClick}132 rows={rows}133 {theme}134 />135</div>136
Solid TSX
Copy
1import { createSignal, createMemo, Show, For } from "solid-js";2import {SimpleTable} from "@simple-table/solid";import type { Theme, SolidColumnDef, CellRendererProps, CellClickProps } from "@simple-table/solid";3import { cellClickingHeaders, cellClickingData, CELL_CLICKING_STATUSES } from "./cell-clicking.demo-data";4import type { ProjectTask } from "./cell-clicking.demo-data";5import "@simple-table/solid/styles.css";67const DETAIL_KEYS = ["task", "details", "assignee", "status", "priority"] as const;89export default function CellClickingDemo(props: { height?: string | number; theme?: Theme }) {10 const [clickInfo, setClickInfo] = createSignal("");11 const [selectedTask, setSelectedTask] = createSignal<ProjectTask | null>(null);12 const [rows, setRows] = createSignal<ProjectTask[]>([...cellClickingData]);1314 const headers: SolidColumnDef<ProjectTask>[] = cellClickingHeaders.map((h) => {15 if (h.accessor === "priority") {16 return {17 ...h,18 cellRenderer: (cr: CellRendererProps<ProjectTask>) => {19 const p = String(cr.row.priority);20 const color = p === "High" ? "#ef4444" : p === "Medium" ? "#f59e0b" : "#10b981";21 return (22 <span style={{ color, "font-weight": "bold", cursor: "pointer" }} title="Click to filter">23 {p}24 </span>25 );26 },27 };28 }29 if (h.accessor === "status") {30 return {31 ...h,32 cellRenderer: (cr: CellRendererProps<ProjectTask>) => {33 const s = String(cr.row.status);34 const bg = s === "Completed" ? "#dcfce7" : s === "In Progress" ? "#fef3c7" : "#fee2e2";35 const c = s === "Completed" ? "#166534" : s === "In Progress" ? "#92400e" : "#991b1b";36 return (37 <span38 style={{39 background: bg,40 color: c,41 padding: "4px 8px",42 "border-radius": "4px",43 "font-size": "12px",44 "font-weight": "bold",45 cursor: "pointer",46 }}47 title="Click to change"48 >49 {s}50 </span>51 );52 },53 };54 }55 if (h.accessor === "details") {56 return {57 ...h,58 cellRenderer: () => (59 <button60 type="button"61 style={{62 background: "#3b82f6",63 color: "white",64 border: "none",65 padding: "6px 12px",66 "border-radius": "4px",67 cursor: "pointer",68 "font-size": "12px",69 "font-weight": "bold",70 }}71 >72 View Details73 </button>74 ),75 };76 }77 return h;78 });7980 const isDark = createMemo(() => props.theme === "modern-dark" || props.theme === "dark" || props.theme === "modern-black");8182 const handleCellClick = ({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) => {83 const task = row;84 switch (accessor) {85 case "priority":86 setClickInfo(`Filtering by ${value} priority`);87 setRows(cellClickingData.filter((t) => t.priority === value));88 break;89 case "status": {90 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));91 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];92 setRows((prev) => prev.map((t) => (t.id === task.id ? { ...t, status: next } : t)));93 setClickInfo(`Status: "${value}" → "${next}"`);94 break;95 }96 case "details":97 setSelectedTask(task);98 setClickInfo(`Opening details for: ${task.task}`);99 break;100 case "estimatedHours": {101 const n = Math.min(task.estimatedHours + 2, 40);102 setRows((prev) => prev.map((t) => (t.id === task.id ? { ...t, estimatedHours: n } : t)));103 setClickInfo(`Est. hours: ${task.estimatedHours}h → ${n}h`);104 break;105 }106 case "completedHours": {107 const n = Math.min(task.completedHours + 1, task.estimatedHours);108 setRows((prev) => prev.map((t) => (t.id === task.id ? { ...t, completedHours: n } : t)));109 setClickInfo(`Done hours: ${task.completedHours}h → ${n}h`);110 break;111 }112 default:113 setClickInfo(`Clicked [${accessor}] = "${value}" (row ${rowIndex})`);114 }115 };116117 return (118 <div style={{ display: "flex", "flex-direction": "column", gap: "16px" }}>119 <div120 style={{121 padding: "12px",122 "background-color": isDark() ? "#374151" : "#f3f4f6",123 "border-radius": "8px",124 border: `1px solid ${isDark() ? "#4b5563" : "#d1d5db"}`,125 "min-height": "48px",126 display: "flex",127 "align-items": "center",128 }}129 >130 <strong style={{ "margin-right": "8px", color: isDark() ? "#f9fafb" : "#1f2937" }}>Last Click:</strong>131 <span style={{ color: isDark() ? "#d1d5db" : "#4b5563" }}>132 {clickInfo() || "Click any cell to see interaction details..."}133 </span>134 </div>135136 <Show when={selectedTask()}>137 {(task) => (138 <div139 style={{140 position: "fixed",141 inset: "0",142 background: "rgba(0,0,0,0.5)",143 display: "flex",144 "align-items": "center",145 "justify-content": "center",146 "z-index": 1000,147 }}148 >149 <div150 style={{151 background: isDark() ? "#1f2937" : "white",152 padding: "24px",153 "border-radius": "8px",154 "max-width": "500px",155 width: "90%",156 }}157 >158 <h3 style={{ margin: "0 0 16px", color: isDark() ? "#f9fafb" : "#1f2937" }}>Task Details</h3>159 <For each={DETAIL_KEYS}>160 {(key) => (161 <p style={{ margin: "8px 0", color: isDark() ? "#d1d5db" : "#4b5563" }}>162 <strong>{key.charAt(0).toUpperCase() + key.slice(1)}:</strong> {String(task()[key])}163 </p>164 )}165 </For>166 <button167 type="button"168 onClick={() => setSelectedTask(null)}169 style={{170 "margin-top": "16px",171 background: "#3b82f6",172 color: "white",173 border: "none",174 padding: "8px 16px",175 "border-radius": "4px",176 cursor: "pointer",177 "font-weight": "bold",178 }}179 >180 Close181 </button>182 </div>183 </div>184 )}185 </Show>186187 <SimpleTable188 columnResizing189 columns={headers}190 getRowId={({ row }) => row.id}191 height={props.height ?? "320px"}192 onCellClick={handleCellClick}193 rows={rows()}194 theme={props.theme}195 />196 </div>197 );198}
TypeScriptCellClickingDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme, ColumnDef, CellClickProps, CellRendererProps, GetRowIdParams } from "simple-table-core";3import {4 cellClickingHeaders,5 cellClickingData,6 CELL_CLICKING_STATUSES,7} from "./cell-clicking.demo-data";8import type { ProjectTask } from "./cell-clicking.demo-data";9import "simple-table-core/styles.css";101112const getRowId = ({ row }: GetRowIdParams<ProjectTask>) => row.id;13export function renderCellClickingDemo(14 container: HTMLElement,15 options?: { height?: string | number; theme?: Theme },16): SimpleTableVanilla<ProjectTask> {17 const isDark = options?.theme === "modern-dark" || options?.theme === "dark" || options?.theme === "modern-black";1819 const wrapper = document.createElement("div");20 wrapper.style.cssText = "display:flex;flex-direction:column;gap:16px";2122 const banner = document.createElement("div");23 banner.style.cssText = `padding:12px;background:${isDark ? "#374151" : "#f3f4f6"};border-radius:8px;border:1px solid ${isDark ? "#4b5563" : "#d1d5db"};min-height:48px;display:flex;align-items:center`;24 banner.innerHTML = `<strong style="margin-right:8px;color:${isDark ? "#f9fafb" : "#1f2937"}">Last Click:</strong><span style="color:${isDark ? "#d1d5db" : "#4b5563"}">Click any cell to see interaction details...</span>`;25 wrapper.appendChild(banner);2627 const overlay = document.createElement("div");28 overlay.style.cssText =29 "position:fixed;inset:0;background:rgba(0,0,0,0.5);display:none;align-items:center;justify-content:center;z-index:1000";30 wrapper.appendChild(overlay);3132 const tableContainer = document.createElement("div");33 wrapper.appendChild(tableContainer);34 container.appendChild(wrapper);3536 let rows: ProjectTask[] = [...cellClickingData];3738 const headers: ColumnDef<ProjectTask>[] = cellClickingHeaders.map((h) => {39 if (h.accessor === "priority") {40 return {41 ...h,42 cellRenderer: ({ row }: CellRendererProps<ProjectTask>) => {43 const p = String(row.priority);44 const color = p === "High" ? "#ef4444" : p === "Medium" ? "#f59e0b" : "#10b981";45 const el = document.createElement("span");46 Object.assign(el.style, { color, fontWeight: "bold", cursor: "pointer" });47 el.title = "Click to filter by priority";48 el.textContent = p;49 return el;50 },51 };52 }53 if (h.accessor === "status") {54 return {55 ...h,56 cellRenderer: ({ row }: CellRendererProps<ProjectTask>) => {57 const s = String(row.status);58 const bg = s === "Completed" ? "#dcfce7" : s === "In Progress" ? "#fef3c7" : "#fee2e2";59 const c = s === "Completed" ? "#166534" : s === "In Progress" ? "#92400e" : "#991b1b";60 const el = document.createElement("span");61 Object.assign(el.style, {62 background: bg,63 color: c,64 padding: "4px 8px",65 borderRadius: "4px",66 fontSize: "12px",67 fontWeight: "bold",68 cursor: "pointer",69 });70 el.title = "Click to change status";71 el.textContent = s;72 return el;73 },74 };75 }76 if (h.accessor === "details") {77 return {78 ...h,79 cellRenderer: () => {80 const btn = document.createElement("button");81 Object.assign(btn.style, {82 background: "#3b82f6",83 color: "white",84 border: "none",85 padding: "6px 12px",86 borderRadius: "4px",87 cursor: "pointer",88 fontSize: "12px",89 fontWeight: "bold",90 });91 btn.textContent = "View Details";92 btn.addEventListener("mouseover", () => {93 btn.style.backgroundColor = "#2563eb";94 });95 btn.addEventListener("mouseout", () => {96 btn.style.backgroundColor = "#3b82f6";97 });98 return btn;99 },100 };101 }102 return { ...h };103 });104105 function showModal(task: ProjectTask) {106 overlay.innerHTML = `<div style="background:${isDark ? "#1f2937" : "white"};padding:24px;border-radius:8px;max-width:500px;width:90%">107 <h3 style="margin:0 0 16px;color:${isDark ? "#f9fafb" : "#1f2937"}">Task Details</h3>108 <p style="margin:8px 0;color:${isDark ? "#d1d5db" : "#4b5563"}"><strong>Task:</strong> ${task.task}</p>109 <p style="margin:8px 0;color:${isDark ? "#d1d5db" : "#4b5563"}"><strong>Details:</strong> ${task.details}</p>110 <p style="margin:8px 0;color:${isDark ? "#d1d5db" : "#4b5563"}"><strong>Assignee:</strong> ${task.assignee}</p>111 <p style="margin:8px 0;color:${isDark ? "#d1d5db" : "#4b5563"}"><strong>Status:</strong> ${task.status}</p>112 <p style="margin:8px 0;color:${isDark ? "#d1d5db" : "#4b5563"}"><strong>Priority:</strong> ${task.priority}</p>113 <button style="margin-top:16px;background:#3b82f6;color:white;border:none;padding:8px 16px;border-radius:4px;cursor:pointer;font-weight:bold" id="close-modal">Close</button>114 </div>`;115 overlay.style.display = "flex";116 overlay.querySelector("#close-modal")?.addEventListener("click", () => {117 overlay.style.display = "none";118 });119 }120121 function updateBanner(msg: string) {122 const span = banner.querySelector("span");123 if (span) span.textContent = msg;124 }125126 const table = new SimpleTableVanilla(tableContainer, {127 getRowId,128 columns: headers,129 rows,130 height: options?.height ?? "320px",131 theme: options?.theme,132 columnResizing: true,133 onCellClick: ({ accessor, rowIndex, value, row }: CellClickProps<ProjectTask>) => {134 const task = row;135 switch (accessor) {136 case "priority":137 updateBanner(`Filtering by ${value} priority`);138 rows = cellClickingData.filter((t) => t.priority === value);139 table.update({ rows });140 break;141 case "status": {142 const idx = CELL_CLICKING_STATUSES.indexOf(String(value));143 const next = CELL_CLICKING_STATUSES[(idx + 1) % CELL_CLICKING_STATUSES.length];144 rows = rows.map((t) => (t.id === task.id ? { ...t, status: next } : t));145 table.update({ rows });146 updateBanner(`Status: "${value}" → "${next}"`);147 break;148 }149 case "details":150 showModal(task);151 updateBanner(`Opening details for: ${task.task}`);152 break;153 case "estimatedHours": {154 const n = Math.min(task.estimatedHours + 2, 40);155 rows = rows.map((t) => (t.id === task.id ? { ...t, estimatedHours: n } : t));156 table.update({ rows });157 updateBanner(`Est. hours: ${task.estimatedHours}h → ${n}h`);158 break;159 }160 case "completedHours": {161 const n = Math.min(task.completedHours + 1, task.estimatedHours);162 rows = rows.map((t) => (t.id === task.id ? { ...t, completedHours: n } : t));163 table.update({ rows });164 updateBanner(`Done hours: ${task.completedHours}h → ${n}h`);165 break;166 }167 default:168 updateBanner(`Clicked [${accessor}] = "${value}" (row ${rowIndex})`);169 }170 },171 });172173 return table;174}175176177// cell-clicking.demo-data.ts178// Self-contained demo table setup for this example.179import type { ColumnDef } from "simple-table-core";180181export type ProjectTask = {182 id: number;183 task: string;184 assignee: string;185 priority: string;186 status: string;187 dueDate: string;188 estimatedHours: number;189 completedHours: number;190 details: string;191};192193export const STATUSES = ["Not Started", "In Progress", "Completed"];194195export const cellClickingData: ProjectTask[] = [196 {197 id: 1001,198 task: "Design login page mockups",199 assignee: "Sarah Chen",200 priority: "High",201 status: "In Progress",202 dueDate: "2024-02-15",203 estimatedHours: 8,204 completedHours: 5,205 details: "Create responsive login page designs with modern UI patterns",206 },207 {208 id: 1002,209 task: "Implement user authentication API",210 assignee: "Marcus Rodriguez",211 priority: "High",212 status: "Not Started",213 dueDate: "2024-02-20",214 estimatedHours: 16,215 completedHours: 0,216 details: "Build secure JWT-based authentication system with OAuth integration",217 },218 {219 id: 1003,220 task: "Write unit tests for payment module",221 assignee: "Luna Martinez",222 priority: "Medium",223 status: "Completed",224 dueDate: "2024-02-10",225 estimatedHours: 12,226 completedHours: 12,227 details: "Comprehensive test coverage for payment processing functionality",228 },229 {230 id: 1004,231 task: "Update documentation for API endpoints",232 assignee: "Kai Thompson",233 priority: "Low",234 status: "In Progress",235 dueDate: "2024-02-25",236 estimatedHours: 6,237 completedHours: 3,238 details: "Update Swagger documentation and add usage examples",239 },240 {241 id: 1005,242 task: "Performance optimization for dashboard",243 assignee: "Zara Kim",244 priority: "Medium",245 status: "Not Started",246 dueDate: "2024-03-01",247 estimatedHours: 20,248 completedHours: 0,249 details: "Optimize rendering performance and implement lazy loading",250 },251 {252 id: 1006,253 task: "Mobile responsiveness testing",254 assignee: "Tyler Anderson",255 priority: "High",256 status: "In Progress",257 dueDate: "2024-02-18",258 estimatedHours: 10,259 completedHours: 7,260 details: "Test application across various mobile devices and screen sizes",261 },262 {263 id: 1007,264 task: "Setup CI/CD pipeline",265 assignee: "Phoenix Lee",266 priority: "Medium",267 status: "Completed",268 dueDate: "2024-02-08",269 estimatedHours: 14,270 completedHours: 14,271 details: "Automated testing and deployment pipeline using GitHub Actions",272 },273 {274 id: 1008,275 task: "Database migration scripts",276 assignee: "River Jackson",277 priority: "Low",278 status: "Not Started",279 dueDate: "2024-02-28",280 estimatedHours: 8,281 completedHours: 0,282 details: "Create migration scripts for database schema updates",283 },284];285286export const cellClickingHeaders: ColumnDef<ProjectTask>[] = [287 { accessor: "id", label: "Task ID", width: 80, sortable: true, type: "number" },288 {289 accessor: "task",290 label: "Task Name",291 minWidth: 150,292 width: "1fr",293 sortable: true,294 type: "string",295 },296 { accessor: "assignee", label: "Assignee", width: 120, sortable: true, type: "string" },297 { accessor: "priority", label: "Priority", width: 100, sortable: true, type: "string" },298 { accessor: "status", label: "Status", width: 120, sortable: true, type: "string" },299 { accessor: "dueDate", label: "Due Date", width: 120, sortable: true, type: "date" },300 { accessor: "estimatedHours", label: "Est. Hours", width: 100, sortable: true, type: "number" },301 { accessor: "completedHours", label: "Done Hours", width: 100, sortable: true, type: "number" },302 { accessor: "details", label: "View Details", width: 120, type: "other" },303];304305export const cellClickingConfig = {306 headers: cellClickingHeaders,307 rows: cellClickingData,308};309310export { STATUSES as CELL_CLICKING_STATUSES };311
Props
Cell Clicking Configuration
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
onCellClick | Optional | Fires when a cell is clicked. Receives accessor, value, row, and indices. |
Click arguments
CellClickProps
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
accessor | Required | The column accessor/key of the clicked cell | |
colIndexnumber | Required | The column index of the clicked cell (0-based) | |
row | Required | The complete row object containing the clicked cell | |
rowIndexnumber | Required | The row index of the clicked cell (0-based) | |
value | Required | The value of the clicked cell |