Orders as a grid: saved views with their counts, filters as chips, columns to sort by and to show or hide, rows grouped by status with their subtotals, cells edited in place, density, and an action bar that rises for the rows picked. On motion.
Installation
When to use
- The main list of an admin or back office: orders, customers or tickets people sort, filter and change all day.
- Lists where people act on many rows at once: change their status, export them or delete them.
When not to use
- A short list on a dashboard: a plain table or the free Orders table is lighter.
- Thousands of rows at once: page or virtualise them on your server and pass in what's shown.
Usage
Data grid with your own data: every prop has the sample as its default, so pass only what you have.
"use client"
import { useState } from "react"
import { DataGrid, type GridRow } from "@/components/dashral/blocks/data-grid"
export default function Orders() {
const [rows, setRows] = useState<GridRow[]>([
{ id: "o1", number: "#5840", customer: "Northwind", email: "billing@northwind.com", plan: "Growth", status: "paid", amount: 490, owner: "Olivia Martin", date: "Nov 14" },
{ id: "o2", number: "#5839", customer: "Globex", email: "billing@globex.com", plan: "Business", status: "failed", amount: 1490, owner: "Noah Kim", date: "Nov 14" },
])
return (
<DataGrid
rows={rows}
views={[
{ id: "all", name: "All orders", filters: [] },
{ id: "unpaid", name: "Unpaid", filters: [{ field: "status", value: "pending" }, { field: "status", value: "failed" }] },
]}
// Shown at once; throw to put it back with your message.
onCellChange={async (row, column, value) => {
await fetch(`/api/orders/${row.id}`, { method: "PATCH", body: JSON.stringify({ [column]: value }) })
}}
onBulkStatus={async (picked, status) => setRows((all) => all.map((r) => (picked.includes(r) ? { ...r, status } : r)))}
onBulkDelete={async (picked) => setRows((all) => all.filter((r) => !picked.includes(r)))}
/>
)
}API reference
DataGrid
A data grid: saved views with their counts, filters as chips, search, columns to sort by and to show or hide, rows grouped by status with their subtotals (folding), cells edited in place, density, and the rows picked acted on from the action bar that rises for them. Every change calls your handler first.
| Prop | Type | Default |
|---|---|---|
title | React.ReactNode | "Orders" |
rows | GridRow[]The rows at first. A new array replaces what's shown (edits included), so keep yours in state. | sample |
views | GridView[] | sample |
onCellChange | (row: GridRow, column: "status" | "owner" | "amount", value: string | number) => Promise<void> | voidA cell changed in place: shown at once, put back with the error shown if this throws. | — |
onBulkStatus | (rows: GridRow[], status: GridStatus) => Promise<void> | voidThe rows picked, changed to a status from the action bar. | — |
onBulkDelete | (rows: GridRow[]) => Promise<void> | voidThe rows picked, deleted from the action bar: they fold away at once and come back if this throws. | — |
onExport | (rows: GridRow[]) => voidExport what's shown (or picked); left out, a CSV is downloaded. | — |
className | string | — |
type GridStatus
= "paid" | "pending" | "failed" | "refunded"type GridRow
| Prop | Type | Default |
|---|---|---|
id | string | — |
number | string | — |
customer | string | — |
email | string | — |
plan | string | — |
status | GridStatus | — |
amount | number | — |
owner | string | — |
date | string | — |
type GridColumn
= "customer" | "plan" | "status" | "amount" | "owner" | "date"type GridFilter
| Prop | Type | Default |
|---|---|---|
field | "status" | "plan" | "owner" | "amount" | — |
value | string | — |
type GridView
A saved view: its name and the filters it applies.
| Prop | Type | Default |
|---|---|---|
id | string | — |
name | string | — |
filters | GridFilter[] | — |