Early bird: 30% off Dashral ProSee pricing

Dashral

Data gridPro

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.

example.tsx
"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.

PropTypeDefault
titleReact.ReactNode"Orders"
rowsGridRow[]

The rows at first. A new array replaces what's shown (edits included), so keep yours in state.

sample
viewsGridView[]sample
onCellChange(row: GridRow, column: "status" | "owner" | "amount", value: string | number) => Promise<void> | void

A cell changed in place: shown at once, put back with the error shown if this throws.

—
onBulkStatus(rows: GridRow[], status: GridStatus) => Promise<void> | void

The rows picked, changed to a status from the action bar.

—
onBulkDelete(rows: GridRow[]) => Promise<void> | void

The rows picked, deleted from the action bar: they fold away at once and come back if this throws.

—
onExport(rows: GridRow[]) => void

Export what's shown (or picked); left out, a CSV is downloaded.

—
classNamestring—

type GridStatus

= "paid" | "pending" | "failed" | "refunded"

type GridRow

PropTypeDefault
idstring—
numberstring—
customerstring—
emailstring—
planstring—
statusGridStatus—
amountnumber—
ownerstring—
datestring—

type GridColumn

= "customer" | "plan" | "status" | "amount" | "owner" | "date"

type GridFilter

PropTypeDefault
field"status" | "plan" | "owner" | "amount"—
valuestring—

type GridView

A saved view: its name and the filters it applies.

PropTypeDefault
idstring—
namestring—
filtersGridFilter[]—