flexitablesort
v1.1.13
Published
Sortable table with draggable rows and columns
Maintainers
Readme
flexitablesort
Why flexitablesort?
- Rows & columns — reorder both independently, automatic direction detection
- 60fps — direct DOM transforms during drag, no React re-renders until drop
- Mobile — long-press to drag on touch devices, optimized for Chrome Android & Safari iOS
- Auto-scroll — accelerates when dragging near container edges
- 100k+ rows — works with
@tanstack/react-virtual - Drag handles — restrict drag to a grip icon with
<DragHandle> - Constraints — lock specific rows or columns via drag range options
- Drop animation — clone smoothly flies to the drop target
- Fully styleable —
className+styleon every component — Tailwind, styled-components, CSS modules - TypeScript — full type definitions out of the box
- Tiny — only peer dependency is React
Install
npm install flexitablesortRequires
reactandreact-dom>= 17.0.0
Quick Start
import {
TableContainer, TableHeader, ColumnCell,
TableBody, BodyRow, RowCell,
} from "flexitablesort";
function arrayMove(arr, from, to) {
const next = [...arr];
const [item] = next.splice(from, 1);
next.splice(to, 0, item);
return next;
}
export default function App() {
const [cols, setCols] = useState([
{ id: "name", label: "Name", width: 150 },
{ id: "age", label: "Age", width: 100 },
{ id: "city", label: "City", width: 160 },
]);
const [rows, setRows] = useState([
{ id: "1", name: "Alice", age: 28, city: "NYC" },
{ id: "2", name: "Bob", age: 34, city: "LA" },
{ id: "3", name: "Carol", age: 22, city: "SF" },
]);
return (
<TableContainer
onDragEnd={({ sourceIndex, targetIndex, dragType }) => {
if (dragType === "column") setCols(arrayMove(cols, sourceIndex, targetIndex));
else setRows(arrayMove(rows, sourceIndex, targetIndex));
}}
>
<TableHeader>
{cols.map((col, i) => (
<ColumnCell key={col.id} id={col.id} index={i} width={col.width}>
{col.label}
</ColumnCell>
))}
</TableHeader>
<TableBody>
{rows.map((row, ri) => (
<BodyRow key={row.id} id={row.id} index={ri}>
{cols.map((col, ci) => (
<RowCell key={col.id} index={ci} width={col.width}>
{row[col.id]}
</RowCell>
))}
</BodyRow>
))}
</TableBody>
</TableContainer>
);
}API
Components
| Component | Props | Description |
|---|---|---|
| TableContainer | onDragEnd, options, renderPlaceholder, className, style | Root wrapper — provides drag context |
| TableHeader | className, style | Header row container |
| ColumnCell | id, index, width, className, style | Draggable column header cell |
| TableBody | className, style | Scrollable body — pass ref for virtual scrolling |
| BodyRow | id, index, className, style | Draggable row |
| RowCell | index, width, className, style | Cell within a row |
| DragHandle | className, style | Wrap inside BodyRow/ColumnCell to restrict drag to this element |
Bold props are required.
Types
interface DragEndResult {
sourceIndex: number;
targetIndex: number;
dragType: "row" | "column";
}
interface DragRange {
start?: number; // first draggable index
end?: number; // last draggable index (exclusive)
}Options
<TableContainer
options={{
rowDragRange: { start: 1 }, // lock first row
columnDragRange: { start: 1, end: 5 }, // lock first col, only 1-4 draggable
}}
/>Drag Handle
import { DragHandle } from "flexitablesort";
<BodyRow id="1" index={0}>
<RowCell index={0}>
<DragHandle><GripIcon /></DragHandle>
Content here
</RowCell>
</BodyRow>Custom Placeholder
<TableContainer
renderPlaceholder={() => (
<div style={{
background: "#6366f122",
border: "2px dashed #6366f1",
height: "100%",
}} />
)}
/>Styling
Every component accepts className and style. No opinionated styles on cells.
<ColumnCell style={{
padding: "0 16px",
fontWeight: 700,
}} /><ColumnCell className="px-4
font-bold text-sm" />const Col = styled(ColumnCell)`
padding: 0 16px;
font-weight: 700;
`;Browser Support
| | Chrome | Firefox | Safari | Edge | |---|---|---|---|---| | Desktop | ✅ | ✅ | ✅ | ✅ | | Mobile | ✅ | ✅ | ✅ | ✅ |
Mobile uses long-press to initiate drag.
Contributing
git clone https://github.com/samiodeh1337/sortable-table.git
cd sortable-table
npm install
npm run dev # docs site at localhost:5173