import React, { CSSProperties } from "react"; import Table, { Column } from "./Table.js"; import FilterSelectTable, { FilterSelect } from "./FilterSelectTable.js"; import { ReportDecorator, CardDecorator } from "../storybook/index.js"; import fixtures, { HumanUse, Categorical, getRandomCategorical, } from "../../testing/fixtures/index.js"; import { styled } from "styled-components"; export default { component: Table, title: "Components/Table/Table", decorators: [CardDecorator, ReportDecorator], }; const TableStyled = styled.div` .dark { background-color: #000; color: #eee; } .med { background-color: #ddd; } .light { background-color: #efefef; } .centered th:not(:first-child) { text-align: center; } .centered td:not(:first-child) { text-align: center; } .squeeze { font-size: 11px; } `; const Percent = new Intl.NumberFormat("en", { style: "percent", }); /** * Types don't have to be specified for table Columns or data in simple use cases * but it provides you with Intellisense and can help avoid unexpected behavior * If the columns or data change they can/should be wrapped in React.useMemo to avoid * extra renders or infinite call stack errors, */ export const simple = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, ]; return ; }; export const squeeze = () => { const Percent2 = new Intl.NumberFormat("en", { style: "percent", minimumFractionDigits: 2, }); const columns: Column[] = [ { Header: "ID", accessor: "id", }, { Header: "Count", Cell: () =>
Number.format(cell.value)
, // Not working? accessor: "count", }, { Header: "High", accessor: (row) => Percent2.format(row.high), }, { Header: "Med", accessor: (row) => Percent2.format(row.med), }, { Header: "Low", accessor: (row) => Percent2.format(row.low), }, { Header: "Comment", accessor: "comment", }, ]; return (
); }; /**** Centered */ export const centered = () => { const columns: Column[] = [ { Header: "Name", accessor: "fullName" }, { Header: "Area", accessor: "value" }, { Header: "Rank", accessor: "rank" }, ]; return (
); }; /**** Set width */ export const setWidth = () => { const columns: Column[] = [ { Header: "Name", accessor: "fullName", style: { width: "70%" } }, { Header: "Area", accessor: "value" }, { Header: "Rank", accessor: "rank" }, ]; return
; }; /**** Formatted column ****/ /** * Beware the formatted value is what's used by sort function, Cell function can be better */ export const formattedPercColumn = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, { Header: "Percent of Activity", accessor: (row) => Percent.format(row.perc), }, ]; return
; }; /**** Paging */ export const paging = () => { const columns: Column[] = [ { Header: "Name", accessor: "fullName", style: { width: "60%" } }, // Fixed width prevents dynamic variation between pages { Header: "Area", accessor: "value", style: { width: "20%" } }, { Header: "Rank", accessor: "rank" }, ]; return (
); }; /**** Style override */ // https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles?file=/src/App.js:3903-3909 export const configDrivenStyle = () => { const columns: Column[] = [ { Header: "Name", style: { backgroundColor: "#000", color: "#eee" }, columns: [ { Header: "Place Name", accessor: "name", style: { backgroundColor: "#efefef" }, }, ], }, { Header: "Count", accessor: "count", style: { backgroundColor: "#ddd" }, }, ]; return
; }; /**** Class-driven styling */ export const classDrivenStyle = () => { const columns: Column[] = React.useMemo( () => [ { Header: "Name", className: "dark", columns: [ { Header: "Place Name", accessor: "name", className: "light", }, ], }, { Header: "Count", accessor: "count", className: "med", }, ], [], ); return (
); }; /**** Data-driven styling */ /** * Any prop can be overridden with these functions, for example onClick, onEnter */ export const dataDrivenProps = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, ]; const headerFn = (header) => header.id === "name" ? { style: { color: "green" } } : {}; const colFn = (column) => column.id === "count" ? { style: { fontStyle: "italic" } } : {}; const rowFn = (row) => row.values.count > 1 ? { style: { fontWeight: "bold" } as CSSProperties } : {}; const cellFn = (cell) => cell.column.id === "count" && cell.value > 1 ? { style: { backgroundColor: "#aaa" } } : {}; return (
); }; /**** Filtering */ export const filterCheckboxes = () => { const filterSelect: FilterSelect = { type: "every", filters: [ { name: "Show only count < 500K", defaultValue: false, filterFn: (row) => row.count < 2_000_000, }, { name: "Show only odd IDs", defaultValue: true, filterFn: (row) => Number.parseInt(row.id) % 2 !== 0, }, ], }; const columns: Column[] = [ { Header: "ID", accessor: "id", }, { Header: "Count", accessor: "count", }, ]; return ( columns, [])} data={getRandomCategorical()} /> ); }; export const tableWithTitle = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, ]; return (
); }; export const tableWithDownload = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, ]; return (
); }; export const tableWithNoData = () => { const columns: Column[] = [ { Header: "Name", accessor: "name", }, { Header: "Count", accessor: "count", }, ]; return (
); };