Knoll
A simple, fast, and un-opinionated table component for React.
It is small (1kB gzipped, from 3kB) and has no dependencies.
Installation
npm install --save knoll
Usage
import React from 'react'import Table Column from 'knoll' const data = id: 1 name: 'Birch' kind: 'coniferous' image: 'http...' id: 2 name: 'Oak' kind: 'deciduous' image: 'http...' id: 3 name: 'Maple' kind: 'deciduous' image: 'http...' id: 4 name: 'Fir' kind: 'coniferous' image: 'http...' { return <Table => /* Get a column's content via a function */ <Column ="ID" = /> /* Customize what renders with React elements */ <Column ="Image" = /> /* You can also use the `cellKey` prop as a shorthand to get a property */ <Column ="Name" ="name" /> <Column ="Kind" ="kind" /> </Table> }
API
Table
The Table
component is for configure the table and passing data. It accepts a few props:
data
- Array of data to render (required)components
- Object of elements to render (optional, see Styling)
You can render a Table
by passing it one or many Column
children:
import Table Column from 'knoll' const fruit = name: 'Apple' quantity: 2 name: 'Banana' quantity: 5 name: 'Honeydew' quantity: 3 <Table => <Column ="Name" ="name" /> <Column ="Quantity" ="quantity" /></Table>
Column
Column
allows you to specify the order and rendering of your data. Columns accept these props:
header
- A variable to render as the header contentcell
- A variable to render as the cell contentcellKey
- An shorthand getter for objects (see below)
Showing data
The header
and cell
props accept strings, functions, or other React components, letting you customize how your content looks.
import Table Column from 'knoll' const data = id: 5 name: "Mies van der Rohe" phoneNumber: '6505551234' id: 6 name: "Florence Knoll" phoneNumber: '6505559123' id: 7 name: "Harry Bertoia" phoneNumber: '6505555678' <Table => <Column ="ID" = /> <Column ="Phone Number" = /> <Column ="Name" = /></Table>
Would output a table like this:
ID | Phone Number | Name |
---|---|---|
#5 | +650 555-1234 | Mies van der Rohe |
#6 | +650 555-9123 | Florence Knoll |
#7 | +650 555-5678 | Harry Bertoia |
cellKey
shorthand
Since tables often show properties directly from an object, Column
components accept a cellKey
prop to make this easier.
Passing cellKey="propName"
is shorthand for cell={row => row.propName}
. Like so:
const data = id: 5 name: "Mies van der Rohe" phoneNumber: '650 555 1234' id: 6 name: "Florence Knoll" phoneNumber: '650 555 9123' id: 7 name: "Harry Bertoia" phoneNumber: '650 555 5678' <Table => <Column ="ID" ="id" /> <Column ="Phone Number" ="phoneNumber" /> <Column ="Name" ="name" /></Table>
Note: cellKey
does not currently support nested properties (eg. obj.a.b.c
). If you need to access nested properties, we recommend you use cell
instead.
Styling
Knoll ships with no styling. It only renders HTML. There’s few things worse than finding a good component, only to realize you need to override a bunch of default styles it provides.
Knoll allows you to customize the HTML of every it renders via the components
prop:
// Define components you'd like to render. (defaults below)const components = table: 'table' header: 'thead' headerRow: 'tr' headerCell: 'th' body: 'tbody' row: 'tr' cell: 'td' const DefaultTable = <Table = />
This approach means Knoll supports both className
-based styling (eg. plain CSS, CSS Modules), and CSS-in-JS approaches.
Traditional CSS
Pass components in that add a className
, be it a string of a CSS module class.
const components = <table ="CustomTable" /> <thead ="CustomTable-header" /> <tr ="CustomTable-headerRow" /> <th ="CustomTable-headerCell" /> <tbody ="CustomTable-body" /> // `row` is special and receives the row's data as a prop too <tr ="CustomTable-row" /> <td ="CustomTable-cell" /> const CustomTable = <Table = />
Look overly verbose? Use the flexility of JSX to help!
const wrap = Component className row ...props <Component = /> const components = table: header: headerRow: headerCell: body: row: cell: const CustomTable = <Table = />
Integrating with external CSS
Being able to customize each element means it’s easy to work with external CSS frameworks like Bootstrap. When you only need to customize the className
of <Table />
, you can simply pass it as a prop to the table:
const DefaultTable = <Table ="table" />const StripedTable = <Table ="table table-striped" /> const data = foo: 'bar' foo: 'baz' foo: 'foobar' <DefaultTable => <Column ="This table is plain" ="foo" /></DefaultTable> <StripedTable => <Column ="This table is striped" ="foo" /></StripedTable>
CSS-in-JS
It’s also easy to work with CSS-in-JS solutions. The example below uses styled-components, but is easy to apply to other solutions.
const components = table: styledtable` color: #242424; font-size: 12px; ` tableHeader: styledthead` font-weight: bold; text-align: center; ` const StyledTable = <Table = />
Motivation
Showing tabular data on the web has been a solved problem since 1997. But recent React components for tables make it quite heavy-handed.
React Table comes preloaded with styles, loading states, “pivoting” tables, and a lot of other stuff I don’t want. Other options have strange APIs and look abandoned.
Knoll tries to provide a simple, composable, and elegant interface to building reactive tables.
TODO
A few future plans:
- Examples of using composition for searching, filtering, sorting
- Examples of styling
License
MIT