QUI React Table

Column Pinning

Name
Info
First Name
Last Name
Age
Visits
Status
Profile Progress
{
"columnPinning": {}
}
import {useState} from "react"
import {faker} from "@faker-js/faker"
import {clsx} from "@qui/base"
import {CodeHighlight} from "@qui/mdx-docs"
import {QButton, QCheckbox, QProgressCircle} from "@qui/react"
import {
ColumnDef,
ColumnOrderState,
flexRender,
getCoreRowModel,
QTable,
QTbody,
QTd,
QThead,
QTr,
useReactTable,
VisibilityState,
} from "@qui/react-table"
import {Person, usePersonData} from "~utils/data"
import {PinnableHeader} from "./pinnable-header"
const columns: ColumnDef<Person>[] = [
{
columns: [
{
accessorKey: "firstName",
cell: (info) => info.getValue(),
header: "First Name",
},
{
accessorFn: (row) => row.lastName,
cell: (info) => info.getValue(),
header: "Last Name",
id: "lastName",
},
],
header: "Name",
},
{
columns: [
{
accessorKey: "age",
header: "Age",
},
{
accessorKey: "visits",
header: "Visits",
},
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "progress",
header: "Profile Progress",
minSize: 175,
},
],
header: "Info",
},
]
export default function ColumnPinning() {
const {data = [], isFetching, refetch} = usePersonData(20)
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
const [columnOrder, setColumnOrder] = useState<ColumnOrderState>([])
const [columnPinning, setColumnPinning] = useState({})
const [isSplit, setIsSplit] = useState(false)
const rerender = () => refetch()
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
onColumnOrderChange: setColumnOrder,
onColumnPinningChange: setColumnPinning,
onColumnVisibilityChange: setColumnVisibility,
state: {
columnOrder,
columnPinning,
columnVisibility,
},
})
const randomizeColumns = () => {
table.setColumnOrder(
faker.helpers.shuffle(table.getAllLeafColumns().map((d) => d.id)),
)
}
return (
<div className="p-2">
<div className="q-border-default inline-flex flex-col gap-1 rounded border px-2 py-1">
<QCheckbox
checked={table.getIsAllColumnsVisible()}
label={<span className="q-body-s strong">Toggle All</span>}
onChange={table.getToggleAllColumnsVisibilityHandler()}
/>
{table.getAllLeafColumns().map((column) => {
return (
<QCheckbox
key={column.id}
checked={column.getIsVisible()}
label={column.id}
onChange={column.getToggleVisibilityHandler()}
/>
)
})}
</div>
<div className="mt-4 flex flex-wrap items-center gap-2">
<QButton onClick={rerender} variant="outline">
Regenerate
</QButton>
<QButton onClick={randomizeColumns} variant="outline">
Shuffle Columns
</QButton>
{isFetching ? <QProgressCircle size="xs" /> : null}
</div>
<div className="mt-4">
<QCheckbox
checked={isSplit}
label="Split pinned columns into multiple tables"
onChange={(event) => {
setIsSplit(event.target.checked)
}}
/>
</div>
<div className={clsx("mt-4 flex", {"gap-4": isSplit})}>
{isSplit && table.getIsSomeColumnsPinned("left") ? (
<QTable>
<QThead>
{table.getLeftHeaderGroups().map((headerGroup) => (
<QTr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<PinnableHeader key={header.id} header={header} />
))}
</QTr>
))}
</QThead>
<QTbody>
{table.getRowModel().rows.map((row) => {
return (
<QTr key={row.id}>
{row.getLeftVisibleCells().map((cell) => {
return (
<QTd key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</QTd>
)
})}
</QTr>
)
})}
</QTbody>
</QTable>
) : null}
{(isSplit && table.getCenterFlatHeaders().length) || !isSplit ? (
<QTable>
<QThead>
{(isSplit
? table.getCenterHeaderGroups()
: table.getHeaderGroups()
).map((headerGroup) => (
<QTr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<PinnableHeader key={header.id} header={header} />
))}
</QTr>
))}
</QThead>
<QTbody>
{table.getRowModel().rows.map((row) => {
return (
<QTr key={row.id}>
{(isSplit
? row.getCenterVisibleCells()
: row.getVisibleCells()
).map((cell) => {
return (
<QTd key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</QTd>
)
})}
</QTr>
)
})}
</QTbody>
</QTable>
) : null}
{isSplit && table.getIsSomeColumnsPinned("right") ? (
<QTable>
<QThead>
{table.getRightHeaderGroups().map((headerGroup) => (
<QTr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<PinnableHeader key={header.id} header={header} />
))}
</QTr>
))}
</QThead>
<QTbody>
{table.getRowModel().rows.map((row) => {
return (
<QTr key={row.id}>
{row.getRightVisibleCells().map((cell) => {
return (
<QTd key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</QTd>
)
})}
</QTr>
)
})}
</QTbody>
</QTable>
) : null}
</div>
<div className="mt-4">
<CodeHighlight
className="w-fit"
code={JSON.stringify(
{columnPinning: table.getState().columnPinning},
null,
2,
)}
disableCopy
language="json"
/>
</div>
</div>
)
}