Documentation Index Fetch the complete documentation index at: https://mintlify.com/IzumiSy/seizen-table/llms.txt
Use this file to discover all available pages before exploring further.
Seizen Table includes a built-in context menu system that allows plugins to add custom actions when users right-click on cells or column headers. The context menu API provides full type safety and access to table state.
Seizen Table supports two types of context menus:
Type Triggered On Use Cases Cell Context Menu Right-click on a table cell Copy value, filter by value, edit cell, custom actions Column Context Menu Right-click on a column header Sort column, hide column, pin column, column settings
Context menu items are defined in the contextMenuItems property of your plugin:
import { definePlugin , cellContextMenuItem , columnContextMenuItem } from "@izumisy/seizen-table/plugin" ;
const MyPlugin = definePlugin ({
id: "my-plugin" ,
name: "My Plugin" ,
args: MySchema ,
slots: { /* ... */ },
contextMenuItems: {
cell: [
cellContextMenuItem ( "copy-value" , ( ctx ) => ({
label: "Copy value" ,
onClick : () => navigator . clipboard . writeText ( String ( ctx . value )),
})),
],
column: [
columnContextMenuItem ( "hide-column" , ( ctx ) => ({
label: "Hide column" ,
onClick : () => ctx . column . toggleVisibility ( false ),
})),
],
},
});
Create cell context menu items using the cellContextMenuItem helper:
cellContextMenuItem < TData , TArgs >(
id : string ,
factory : ( ctx : CellContextMenuItemContext < TData , TArgs >) => ContextMenuItemEntry
)
Cell Context
The factory function receives a context object with these properties:
interface CellContextMenuItemContext < TData , TArgs > {
cell : Cell < TData , unknown >; // The cell that was right-clicked
column : Column < TData , unknown >; // The column of the cell
row : Row < TData >; // The row containing the cell
value : unknown ; // The raw cell value (cell.getValue())
selectedRows : TData []; // Currently selected rows
table : Table < TData >; // TanStack Table instance
pluginArgs : TArgs ; // Plugin configuration args
emit : EventBus [ "emit" ]; // Emit custom events
}
Copy Cell Value
cellContextMenuItem ( "copy-value" , ( ctx ) => ({
label: "Copy value" ,
onClick : () => {
navigator . clipboard . writeText ( String ( ctx . value ?? "" ));
},
visible: ctx . value != null , // Only show if cell has a value
}))
Filter by Cell Value
cellContextMenuItem ( "filter-by-value" , ( ctx ) => ({
label: `Filter by " ${ ctx . value } "` ,
onClick : () => {
ctx . column . setFilterValue ( ctx . value );
},
visible: ctx . column . getCanFilter (),
}))
cellContextMenuItem ( "mark-important" , ( ctx ) => ({
label: "Mark as important" ,
icon: < StarIcon /> ,
onClick : () => {
// Update row data
updateRow ( ctx . row . id , { important: true });
},
disabled: ctx . row . original . important === true ,
}))
Column Context Menu
columnContextMenuItem API
Create column context menu items using the columnContextMenuItem helper:
columnContextMenuItem < TData , TArgs >(
id : string ,
factory : ( ctx : ColumnContextMenuItemContext < TData , TArgs >) => ContextMenuItemEntry
)
Column Context
The factory function receives a context object with these properties:
interface ColumnContextMenuItemContext < TData , TArgs > {
column : Column < TData , unknown >; // The column header that was right-clicked
table : Table < TData >; // TanStack Table instance
pluginArgs : TArgs ; // Plugin configuration args
emit : EventBus [ "emit" ]; // Emit custom events
}
Column Context Menu Examples
Hide Column
columnContextMenuItem ( "hide-column" , ( ctx ) => ({
label: "Hide column" ,
onClick : () => {
ctx . column . toggleVisibility ( false );
},
}))
Sort Column
columnContextMenuItem ( "sort-asc" , ( ctx ) => ({
label: "Sort ascending" ,
onClick : () => {
ctx . column . toggleSorting ( false ); // false = ascending
},
visible: ctx . column . getCanSort (),
}))
columnContextMenuItem ( "sort-desc" , ( ctx ) => ({
label: "Sort descending" ,
onClick : () => {
ctx . column . toggleSorting ( true ); // true = descending
},
visible: ctx . column . getCanSort (),
}))
Pin Column
columnContextMenuItem ( "pin-left" , ( ctx ) => ({
label: "Pin to left" ,
onClick : () => {
ctx . column . pin ( "left" );
},
visible: ctx . column . getCanPin (),
}))
Each context menu item can have these properties:
interface ContextMenuItemEntry {
label : string ; // Display text
icon ?: ReactNode ; // Optional icon component
onClick : () => void ; // Click handler
visible ?: boolean ; // Show/hide item (default: true)
disabled ?: boolean ; // Disable item (default: false)
}
Label
Required display text for the menu item
Icon (optional)
React component to display alongside the label
onClick
Function called when the item is clicked
Visible (optional)
Boolean to show/hide the item based on context
Disabled (optional)
Boolean to disable the item (shown but not clickable)
Here’s a complete plugin that adds both cell and column context menu items:
import { z } from "zod" ;
import {
definePlugin ,
cellContextMenuItem ,
columnContextMenuItem ,
usePluginContext ,
} from "@izumisy/seizen-table/plugin" ;
import { CopyIcon , FilterIcon , HideIcon , SortIcon } from "./icons" ;
const ContextMenuPluginSchema = z . object ({
enableCopy: z . boolean (). default ( true ),
enableFilter: z . boolean (). default ( true ),
});
const ContextMenuPlugin = definePlugin ({
id: "context-menu-plugin" ,
name: "Context Menu Plugin" ,
args: ContextMenuPluginSchema ,
slots: {}, // This plugin only adds context menu items
contextMenuItems: {
// Cell context menu items
cell: [
cellContextMenuItem ( "copy-value" , ( ctx ) => ({
label: "Copy" ,
icon: < CopyIcon /> ,
onClick : () => {
navigator . clipboard . writeText ( String ( ctx . value ?? "" ));
},
visible: ctx . pluginArgs . enableCopy && ctx . value != null ,
})),
cellContextMenuItem ( "filter-by-value" , ( ctx ) => ({
label: `Filter by " ${ ctx . value } "` ,
icon: < FilterIcon /> ,
onClick : () => {
ctx . column . setFilterValue ( ctx . value );
},
visible: ctx . pluginArgs . enableFilter && ctx . column . getCanFilter (),
})),
],
// Column context menu items
column: [
columnContextMenuItem ( "sort-asc" , ( ctx ) => ({
label: "Sort A-Z" ,
icon: < SortIcon direction = "asc" /> ,
onClick : () => ctx . column . toggleSorting ( false ),
visible: ctx . column . getCanSort (),
})),
columnContextMenuItem ( "sort-desc" , ( ctx ) => ({
label: "Sort Z-A" ,
icon: < SortIcon direction = "desc" /> ,
onClick : () => ctx . column . toggleSorting ( true ),
visible: ctx . column . getCanSort (),
})),
columnContextMenuItem ( "hide-column" , ( ctx ) => ({
label: "Hide column" ,
icon: < HideIcon /> ,
onClick : () => ctx . column . toggleVisibility ( false ),
})),
],
},
});
// Usage
function App () {
return (
< SeizenTable
data = { data }
columns = { columns }
plugins = { [
ContextMenuPlugin . configure ({
enableCopy: true ,
enableFilter: true ,
})
] }
/>
);
}
Using Context Menu Handlers in Custom Rendering
If you’re using custom table rendering, you can access context menu handlers with the useContextMenuHandlers hook:
import { useContextMenuHandlers } from "@izumisy/seizen-table/plugin" ;
function CustomTable < TData >( props ) {
const handlers = useContextMenuHandlers < TData >();
const tanstack = table . _tanstackTable ;
return (
< table >
< thead >
{ tanstack . getHeaderGroups (). map (( headerGroup ) => (
< tr key = { headerGroup . id } >
{ headerGroup . headers . map (( header ) => (
< th
key = { header . id }
onContextMenu = { ( e ) => handlers . handleColumnContextMenu ( e , header . column ) }
>
{ flexRender ( header . column . columnDef . header , header . getContext ()) }
</ th >
)) }
</ tr >
)) }
</ thead >
< tbody >
{ tanstack . getRowModel (). rows . map (( row ) => (
< tr key = { row . id } >
{ row . getVisibleCells (). map (( cell ) => (
< td
key = { cell . id }
onContextMenu = { ( e ) =>
handlers . handleCellContextMenu ( e , cell , cell . column , row )
}
>
{ flexRender ( cell . column . columnDef . cell , cell . getContext ()) }
</ td >
)) }
</ tr >
)) }
</ tbody >
</ table >
);
}
The useContextMenuHandlers hook must be used within a SeizenTable.Root or ContextMenuProvider component. It automatically prevents the default browser context menu and positions the custom menu.
Seizen Table includes a default “Copy” action for cell context menus. Plugin items are grouped by plugin name in the menu:
[Built-in]
Copy
[My Plugin]
Filter by value
Mark as important
[Another Plugin]
Export row
Best Practices
Avoid side effects in factory functions: The factory function may be called multiple times. Keep it pure and only return the menu item configuration.// Bad - side effect in factory
cellContextMenuItem ( "bad" , ( ctx ) => {
console . log ( ctx . value ); // Don't do this
return { label: "Bad" , onClick : () => {} };
})
// Good - side effects in onClick
cellContextMenuItem ( "good" , ( ctx ) => ({
label: "Good" ,
onClick : () => {
console . log ( ctx . value ); // Do this
},
}))
Use visibility wisely: Hide menu items that don’t apply to the current context rather than showing disabled items:visible : ctx . column . getCanSort () // Hide if column can't be sorted
Exported Types
The context menu API exports these types from @izumisy/seizen-table/plugin:
export type {
// Menu item types
ContextMenuItemEntry ,
// Cell context menu
CellContextMenuItemContext ,
CellContextMenuItemFactory ,
// Column context menu
ColumnContextMenuItemContext ,
ColumnContextMenuItemFactory ,
};
export {
// Factory functions
cellContextMenuItem ,
columnContextMenuItem ,
// Hooks
useContextMenuHandlers ,
};
Next Steps
Plugin Development Learn more about creating plugins
Event Bus Emit custom events from context menu actions