@@ -5,7 +5,8 @@ import type { ColumnDef, SortingState } from "@tanstack/react-table";
55import type { ExtendedDataTableColumnDef } from "./data-table" ;
66import { Badge } from "../badge/badge" ;
77import { Button } from "../button/button" ;
8- import { IconEdit , IconTrash } from "@humansignal/icons" ;
8+ import { Tooltip } from "../Tooltip/Tooltip" ;
9+ import { IconEdit , IconTrash , IconMonitors } from "@humansignal/icons" ;
910
1011const meta : Meta < typeof DataTable > = {
1112 component : DataTable ,
@@ -27,18 +28,36 @@ type User = {
2728 role : string ;
2829 status : "active" | "inactive" ;
2930 lastActive : string ;
31+ activeSessions ?: number ;
3032} ;
3133
3234const sampleData : User [ ] = [
33- { id : 1 , name : "John Doe" , email : "john@example.com" , role : "Admin" , status : "active" , lastActive : "2024-01-15" } ,
34- { id : 2 , name : "Jane Smith" , email : "jane@example.com" , role : "Editor" , status : "active" , lastActive : "2024-01-14" } ,
35+ {
36+ id : 1 ,
37+ name : "John Doe" ,
38+ email : "john@example.com" ,
39+ role : "Admin" ,
40+ status : "active" ,
41+ lastActive : "2024-01-15" ,
42+ activeSessions : 2 ,
43+ } ,
44+ {
45+ id : 2 ,
46+ name : "Jane Smith" ,
47+ email : "jane@example.com" ,
48+ role : "Editor" ,
49+ status : "active" ,
50+ lastActive : "2024-01-14" ,
51+ activeSessions : 1 ,
52+ } ,
3553 {
3654 id : 3 ,
3755 name : "Bob Johnson" ,
3856 email : "bob@example.com" ,
3957 role : "Viewer" ,
4058 status : "inactive" ,
4159 lastActive : "2024-01-10" ,
60+ activeSessions : 0 ,
4261 } ,
4362 {
4463 id : 4 ,
@@ -47,6 +66,7 @@ const sampleData: User[] = [
4766 role : "Editor" ,
4867 status : "active" ,
4968 lastActive : "2024-01-15" ,
69+ activeSessions : 1 ,
5070 } ,
5171 {
5272 id : 5 ,
@@ -55,6 +75,7 @@ const sampleData: User[] = [
5575 role : "Viewer" ,
5676 status : "active" ,
5777 lastActive : "2024-01-13" ,
78+ activeSessions : 3 ,
5879 } ,
5980] ;
6081
@@ -516,3 +537,92 @@ export const ConditionalRowSelection: Story = {
516537 ) ;
517538 } ,
518539} ;
540+
541+ /**
542+ * Custom React Node Headers
543+ *
544+ * Demonstrates using custom React nodes as column headers instead of text.
545+ * The header property accepts any React node - icons, buttons, dropdowns, or any
546+ * custom component. Simply pass a function that returns your custom header content.
547+ *
548+ * This example shows an icon wrapped in a Tooltip for a compact column, but you can
549+ * use any React component as a header (buttons, dropdowns, badges, etc.).
550+ *
551+ * Hover over the monitors icon to see the tooltip explaining the column.
552+ */
553+ export const WithCustomHeaders : Story = {
554+ render : ( ) => {
555+ const [ sorting , setSorting ] = useState < SortingState > ( [ ] ) ;
556+
557+ const columnsWithCustomHeaders : ColumnDef < User > [ ] = [
558+ {
559+ accessorKey : "name" ,
560+ header : "Name" ,
561+ enableSorting : true ,
562+ } ,
563+ {
564+ accessorKey : "email" ,
565+ header : "Email" ,
566+ enableSorting : true ,
567+ } ,
568+ {
569+ accessorKey : "role" ,
570+ header : "Role" ,
571+ cell : ( { getValue } ) => {
572+ const role = getValue ( ) as string ;
573+ return (
574+ < Badge variant = { role === "Admin" ? "primary" : role === "Editor" ? "success" : "info" } size = "small" >
575+ { role }
576+ </ Badge >
577+ ) ;
578+ } ,
579+ } ,
580+ {
581+ accessorKey : "activeSessions" ,
582+ // Icon-only header with tooltip - wrap icon in Tooltip directly
583+ header : ( ) => (
584+ < Tooltip title = "Active Sessions: Number of active browser sessions." alignment = "top-center" >
585+ < div className = "flex items-center cursor-help" >
586+ < IconMonitors width = { 24 } height = { 24 } />
587+ </ div >
588+ </ Tooltip >
589+ ) ,
590+ size : 32 ,
591+ minSize : 30 ,
592+ cell : ( { getValue } ) => {
593+ const sessions = getValue ( ) as number ;
594+ return (
595+ < div className = "flex items-center justify-center" >
596+ < Badge variant = { sessions > 1 ? "warning" : "default" } size = "small" >
597+ { sessions }
598+ </ Badge >
599+ </ div >
600+ ) ;
601+ } ,
602+ } ,
603+ {
604+ accessorKey : "lastActive" ,
605+ header : "Last Active" ,
606+ enableSorting : true ,
607+ } ,
608+ ] ;
609+
610+ return (
611+ < div className = "flex flex-col gap-4" >
612+ < div className = "p-4 bg-neutral-surface rounded-md" >
613+ < p className = "text-sm text-neutral-content-subtle" >
614+ 💡 The column between "Role" and "Last Active" uses an icon wrapped in a Tooltip as the header. Hover over
615+ the monitors icon to see the tooltip.
616+ </ p >
617+ </ div >
618+ < DataTable
619+ data = { sampleData }
620+ columns = { columnsWithCustomHeaders }
621+ enableSorting
622+ sorting = { sorting }
623+ onSortingChange = { setSorting }
624+ />
625+ </ div >
626+ ) ;
627+ } ,
628+ } ;
0 commit comments