solid-tabular
v0.4.0
Published
Spreadsheet-like table UI
Downloads
474
Readme
solid-tabular
Spreadsheet-like table UI for SolidJS.
Demo: https://alexanderrafferty.com/projects/solid-tabular/
⚠️ This library is currently in early development, and breaking changes will definitely occur.
Features
- 🚀 Virtualization: Efficiently renders large datasets using
@tanstack/solid-virtual. - 🖱️ Selection: Excel-like cell and range selection.
- ✏️ Editing: In-place cell editing.
- 📏 Resizing: Draggable column resizing.
- 📋 Clipboard: Copy and paste support.
- ⌨️ Keyboard Navigation: Arrow keys, Tab, Enter, etc.
- 🎨 Customizable: CSS variables for theming.
Installation
npm install solid-tabular
# or
pnpm add solid-tabular
# or
yarn add solid-tabularBasic Usage
The example below shows how to display a static data table with default column widths.
import { createSignal } from 'solid-js'
import { Table, ActiveRange } from 'solid-tabular'
import 'solid-tabular/dist/index.css'
function App() {
const [activeRange, setActiveRange] = createSignal<ActiveRange>()
const columns = ['A', 'B', 'C']
const [data, setData] = createSignal([
['A1', 'B1', 'C1'],
['A2', 'B2', 'C2'],
['A3', 'B3', 'C3'],
])
return (
<div style={{ height: '500px' }}>
<Table
columns={columns}
numRows={data().length}
getCellValue={(row, col) => data()[row][columns.indexOf(col)]}
activeRange={activeRange()}
setActiveRange={setActiveRange}
/>
</div>
)
}API
Table Component
The Table component is the main entry point, and has two generic type parameters Column and Value.
| Prop | Type | Description |
|------|------|-------------|
| columns | Column[] | Array of column objects. |
| numRows | number | Total number of rows. |
| getCellValue | (row: number, column: Column) => Value | Function to get the value for a cell. |
| setCellValue | (row: number, column: Column, value: Value) => void | Function to update the value of a cell. |
| activeRange | ActiveRange | The current selection state. |
| setActiveRange | (range: ActiveRange) => void | Callback to update the selection state. |
| columnsResizeable | boolean | Enables column resizing. |
| columnsRenameable | boolean | Enables column renaming. |
| addColumnButton | boolean | Whether to render an "add column" button. |
| addRowButton | boolean | Whether to render an "add row" button. |
| cellHeight | number | Height of cells in pixels (default: 29). |
| getCellContent | (column: Column) => Component<CellContentProps<Value>> | Component used to render the content of cells for a particular column. |
| getColumnIcon | (column: Column) => Component | Gets the icon for a particular column. |
| getColumnSize | (column: Column) => number | Get column width. |
| setColumnSize | (column: Column, width: number) => void | Set column width. |
| resetColumnSize | (column: Column) => void | Reset column width. |
| getColumnName | (column: Column) => string | Get column name. |
| setColumnName | (column: Column, name: string) => void | Set column name. |
| onInsertColumns | (index: number, count: number) => void | Insert columns. |
| onInsertRows | (index: number, count: number) => void | Insert rows. |
| onViewportChanged | (start: number, end: number) => void | Called whenever the range of rows visible in the viewport changes. |
| onCellContextMenu | (ev: MouseEvent, row: number, column: Column) => void | Fired when a cell context menu is opened. |
| onCopy | (min: CellIndex, max: CellIndex) => void | Called when cells are copied. |
| onPaste | (min: CellIndex, max: CellIndex) => void | Called when cells are pasted. |
| onClear | (min: CellIndex, max: CellIndex) => void | Called when cells are cleared (delete key). |
| initialScrollPosition | { left: number; top: number } | Initial scroll position to restore. |
| onScrollPositionChange | (scrollLeft: number, scrollTop: number) => void | Called when the table scroll position changes. |
Theming
You can customize the appearance using CSS variables:
.my-table {
/* General */
--solid-tabular-font: 0.875rem 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
--solid-tabular-bg-color: oklch(92.8% 0.006 264.531);
--solid-tabular-text-color: black;
/* Cells */
--solid-tabular-cell-color: white;
--solid-tabular-cell-hover-color: oklch(96.7% 0.003 264.542);
--solid-tabular-border-color: oklch(87.2% 0.01 258.338);
--solid-tabular-placeholder-color: oklch(70.7% 0.022 261.325);
/* Headers */
--solid-tabular-header-color: var(--solid-tabular-cell-color);
--solid-tabular-rownum-color: inherit;
--solid-tabular-font-size-row-num: 1em;
/* Selection & Accents */
--solid-tabular-accent-color: oklch(45.7% 0.24 277.023);
--solid-tabular-shade-color: rgba(0, 0, 0, 0.12);
}