UI Customization
<TableView> is a compound component. It renders a default layout (toolbars, table, footer), but you can override any part by passing children that replace the defaults.
Default Structure
Section titled “Default Structure”Without any children, <TableView> renders:
TableView├── Toolbars│ ├── ActionsToolbar (filter/sort/settings buttons)│ └── SortsFiltersToolbar (active filter/sort chips)├── Table│ ├── HeaderRow (column headers with menus)│ └── Body (data rows)└── Footer (add row, delete selected -- when editable)Custom Toolbar Buttons
Section titled “Custom Toolbar Buttons”Add buttons to the actions toolbar alongside the built-in ones:
import { TableView, Toolbars, ActionsToolbar, MainActionsToolbarGroup, MainActionsToolbarGroupItems,} from "@blocknote/block-view/react";
function MyTable({ table }) { return ( <TableView table={table} editable> <Toolbars> <ActionsToolbar> <MainActionsToolbarGroup> {/* Built-in buttons (filter, sort, settings) */} <MainActionsToolbarGroupItems /> {/* Your custom buttons */} <button onClick={() => console.log("Export clicked!")}>Export</button> <button onClick={() => console.log("Import clicked!")}>Import</button> </MainActionsToolbarGroup> </ActionsToolbar> </Toolbars> </TableView> );}<MainActionsToolbarGroupItems /> renders the default toolbar buttons. Place your custom buttons before or after it.
Custom Column Menu Items
Section titled “Custom Column Menu Items”Add items to every column header’s dropdown menu:
import { TableView, Table, HeaderRow } from "@blocknote/block-view/react";import { Menu } from "@base-ui/react";
function MyTable({ table }) { return ( <TableView table={table} editable> <Table> <HeaderRow menuAfter={ <Menu.Item onClick={(e) => { // Access the column from the event context console.log("Custom menu item clicked"); }} > Copy column data </Menu.Item> } /> </Table> </TableView> );}The menuAfter prop appends menu items after the default column menu items (rename, sort, filter, hide, delete).
Custom Footer
Section titled “Custom Footer”Replace or extend the footer content:
import { TableView, Footer, AddDocumentFooterButton, DeleteSelectedDocumentsFooterButton, useTableViewContext,} from "@blocknote/block-view/react";
function CustomFooterContent() { const { table } = useTableViewContext(); const hasSelection = table.getIsSomeRowsSelected();
return ( <> <AddDocumentFooterButton /> {hasSelection && <DeleteSelectedDocumentsFooterButton />} <button onClick={() => { const selected = table.getSelectedRowsById(); console.log("Selected rows:", Object.keys(selected)); }} > Log selected </button> <span style={{ marginLeft: "auto", color: "#666" }}>{table.rows.length} rows</span> </> );}
function MyTable({ table }) { return ( <TableView table={table} editable> <Footer> <CustomFooterContent /> </Footer> </TableView> );}Use useTableViewContext() inside any child of <TableView> to access the table instance and editable state.
Full Example: Custom Table with All Overrides
Section titled “Full Example: Custom Table with All Overrides”import { TableView, Toolbars, ActionsToolbar, MainActionsToolbarGroup, MainActionsToolbarGroupItems, Table, HeaderRow, Body, Footer, AddDocumentFooterButton, DeleteSelectedDocumentsFooterButton, useTableViewContext,} from "@blocknote/block-view/react";import { Menu } from "@base-ui/react";
function RowCount() { const { table } = useTableViewContext(); return <span style={{ marginLeft: "auto", color: "#888" }}>{table.rows.length} rows</span>;}
function MyCustomTable({ table }) { return ( <TableView table={table} editable> {/* Custom toolbar with extra buttons */} <Toolbars> <ActionsToolbar> <MainActionsToolbarGroup> <MainActionsToolbarGroupItems /> <button onClick={() => alert("Exported!")}>Export CSV</button> </MainActionsToolbarGroup> </ActionsToolbar> </Toolbars>
{/* Table with custom column menu items */} <Table> <HeaderRow menuAfter={<Menu.Item onClick={() => alert("Copied!")}>Copy column</Menu.Item>} /> <Body /> </Table>
{/* Custom footer */} <Footer> <AddDocumentFooterButton /> <DeleteSelectedDocumentsFooterButton /> <RowCount /> </Footer> </TableView> );}Available Compound Components
Section titled “Available Compound Components”These are all exported from @blocknote/block-view/react:
Layout
Section titled “Layout”TableView— Top-level wrapper. Props:table,editable,childrenToolbars— Container for toolbar rowsTable— Container for header and bodyFooter— Container for footer content
Toolbars
Section titled “Toolbars”ActionsToolbar— Primary toolbar rowSortsFiltersToolbar— Active filter/sort chip barMainActionsToolbarGroup— Group wrapper for toolbar buttonsMainActionsToolbarGroupItems— Renders the default toolbar buttonsShowFiltersToolbarButton— Toggle filter barShowSortsToolbarButton— Toggle sort barSortSettingsComboboxRoot— Sort settings popoverPropertyVisibilitySettingsComboboxRoot— Column visibility popoverTableSettingsMenuRoot— Settings dropdown menu
HeaderRow— Column headers. Props:menuAfter(extra menu items)Body— Data rowsPropertyHeader— Individual column headerHeaderMenuRoot— Column header dropdown menuHeaderResizeHandle— Column resize drag handleAddPropertyHeader— ”+” button to add a new columnSelectAllRowsHeader— Checkbox header for row selection
Footer
Section titled “Footer”AddDocumentFooterButton— ”+ New” buttonDeleteSelectedDocumentsFooterButton— Delete selected rows button
Context Hooks
Section titled “Context Hooks”useTableViewContext()— Returns{ table, editable, ref }useTableContext()— Returns table-specific context within<Table>useToolbarsContext()— Returns toolbar-specific state
Read-Only Mode
Section titled “Read-Only Mode”Toggle editing with the editable prop:
<TableView table={table} editable={false} />When editable is false, cells are read-only, the footer is hidden, and toolbar actions that modify data are disabled. You can also control editability per-cell through useCollectionTableView:
const { table } = useCollectionTableView({ collectionManager: manager, viewId, propertyDefinitions: defaultPropertyDefinitions, getEditable: (document, property) => { // Make "name" column always editable, others read-only return property.id === "name"; },});