flotable
v0.1.11
Published
Open-source, ERP-focused table component — zero runtime dependencies
Downloads
245
Readme
FloTable
An open-source, zero-dependency table component built for ERP-style applications. Handles sorting, filtering, pagination, and rich column types out of the box — with full style customization and no runtime baggage.
Features
- Zero runtime dependencies — only React as a peer dependency
- 7 built-in column types — text, number, date, boolean, badge, currency, link
- Quick filters — inline per-column filter pills in the header
- Sorting — single-column sorting with visual indicators
- Pagination — built-in page controls with configurable page size
- Custom renderers — override any column with a
renderfunction - Two data modes — controlled (
dataprop) or self-managed (requestprop for async fetching) - Full style control — CSS custom properties,
classNamesAPI, andstylesprop for every table slot - Framework-agnostic styling — ships plain CSS in
@layer flotable, works with Tailwind, CSS Modules, or vanilla CSS
Installation
npm install flotableFloTable requires React 18+ as a peer dependency.
Quick Start
import { FloTable } from 'flotable';
import 'flotable/dist/flotable.css';
const columns = [
{ key: 'name', header: 'Name', type: 'text' as const },
{ key: 'email', header: 'Email', type: 'text' as const },
{ key: 'role', header: 'Role', type: 'badge' as const, badgeColors: { Admin: '#e0f2fe', User: '#f0fdf4' } },
{ key: 'salary', header: 'Salary', type: 'currency' as const, currency: 'USD' },
];
const data = [
{ name: 'Alice', email: '[email protected]', role: 'Admin', salary: 95000 },
{ name: 'Bob', email: '[email protected]', role: 'User', salary: 72000 },
];
function App() {
return (
<FloTable
columns={columns}
data={data}
totalRows={data.length}
page={1}
onPageChange={(p) => console.log('Page:', p)}
/>
);
}Request Mode (Async Data Fetching)
<FloTable
columns={columns}
pageSize={20}
request={async ({ page, pageSize, sortState, quickFilters }) => {
const res = await fetch(`/api/users?page=${page}&size=${pageSize}`);
const json = await res.json();
return { data: json.rows, totalRows: json.total };
}}
/>Column Types
| Type | Description | Extra Props |
|------|-------------|-------------|
| text | Plain text | — |
| number | Formatted number | locale |
| date | Formatted date string | locale |
| boolean | Checkmark / cross icon | — |
| badge | Colored pill for enum values | badgeColors |
| currency | Formatted money value | currency, locale |
| link | Clickable URL | — |
Any column can use a custom render function to override the default renderer.
Styling & Customization
FloTable ships plain CSS wrapped in @layer flotable. Every visual token uses a CSS custom property with a fallback, so you can theme the entire table without touching source files.
CSS Custom Properties
Override tokens on the root element or via the styles prop:
.my-table {
--flotable-border-color: #e5e7eb;
--flotable-header-bg: #f9fafb;
--flotable-row-hover-bg: #f3f4f6;
--flotable-font-size: 14px;
}classNames API
Pass custom class names to any table slot:
<FloTable
classNames={{
root: 'my-table',
header: 'my-header',
row: 'my-row',
cell: 'my-cell',
pagination: 'my-pagination',
filterBar: 'my-filters',
}}
// ...
/>Tailwind CSS Integration
If your app uses Tailwind, declare the flotable layer before your Tailwind import so utility classes passed via classNames reliably override component defaults:
/* globals.css */
@layer flotable; /* lowest priority — component defaults */
@import "tailwindcss"; /* utilities layer beats flotable */Props Reference
Common Props
| Prop | Type | Description |
|------|------|-------------|
| columns | ColumnDef<T>[] | Column definitions (required) |
| pageSize | number | Rows per page (default: 10) |
| filterDefs | FilterDef[] | Explicit filter pill definitions |
| autoFilters | boolean | Auto-generate filter pills from filterable columns |
| showSearch | boolean | Show a global search input in the filter bar |
| classNames | FloTableClassNames | Custom CSS classes for each table slot |
| styles | FloTableStyles | Inline styles / CSS custom properties for each slot |
Data Mode Props
| Prop | Type | Description |
|------|------|-------------|
| data | T[] | Current page rows |
| totalRows | number | Total row count across all pages |
| page | number | Active page (1-based) |
| onPageChange | (page: number) => void | Page navigation callback |
| sortState | SortState<T> \| null | Current sort state |
| onSortChange | (sort: SortState<T> \| null) => void | Sort change callback |
| quickFilters | QuickFilterState | Active filter values |
| onFilterChange | (filters: QuickFilterState) => void | Filter change callback |
Request Mode Props
| Prop | Type | Description |
|------|------|-------------|
| request | FloTableRequestFn<T> | Async function called on mount and on every state change |
Project Structure
packages/flotable/ # The published npm package
apps/demo/ # Next.js demo app (not published)Contributing
See CONTRIBUTING.md for setup instructions, code style rules, and the PR workflow.
License
MIT — Copyright (c) 2026 Fladeed
