Skip to main contentSkip to docs navigation

Dashboard Widgets

A real-world dashboard layout combining stat cards, a data table with badges, a list for recent activity, and progress bars — all from JSON data.

On this page

A dashboard assembles several data-driven components side by side: stat cards, a data table with badges, an activity list, and progress bars. All data below is static for illustration — in practice each array would come from an API response.

Total Users
12,540
+8%
Active Sessions
342
+12%
Open Issues
27
-3%
Server Errors
4
+1
Recent Orders
OrderCustomerAmountStatus
#1042Alice Martin$120.00Paid
#1043Bob Chen$85.50Pending
#1044Carol White$240.00Paid
#1045David Kim$59.99Failed
Traffic Sources
Organic Search52%
Direct24%
Referral14%
Social10%
JSX
import {
  Badge,
  Card,
  CardBody,
  Grid,
  List,
  Progress,
  Table,
  TableBody,
  TableCell,
  TableColumn,
  TableHeader,
  TableRow
} from '@chassis-ui/react'

export const Example = () => {
  const stats = [
    { label: 'Total Users', value: '12,540', delta: '+8%', color: 'primary' },
    { label: 'Active Sessions', value: '342', delta: '+12%', color: 'success' },
    { label: 'Open Issues', value: '27', delta: '-3%', color: 'warning' },
    { label: 'Server Errors', value: '4', delta: '+1', color: 'danger' }
  ] as const
  const orders = [
    { id: '#1042', customer: 'Alice Martin', amount: '$120.00', status: 'Paid' },
    { id: '#1043', customer: 'Bob Chen', amount: '$85.50', status: 'Pending' },
    { id: '#1044', customer: 'Carol White', amount: '$240.00', status: 'Paid' },
    { id: '#1045', customer: 'David Kim', amount: '$59.99', status: 'Failed' }
  ]
  const orderStatusColor = { Paid: 'success', Pending: 'warning', Failed: 'danger' } as const
  const activity = [
    { label: 'New user registered — Alice Martin', href: '#' },
    { label: 'Order #1045 failed payment', href: '#' },
    { label: 'Server backup completed', href: '#' },
    { label: 'Password reset requested', href: '#' }
  ]
  const traffic = [
    { label: 'Organic Search', value: 52, color: 'primary' },
    { label: 'Direct', value: 24, color: 'success' },
    { label: 'Referral', value: 14, color: 'info' },
    { label: 'Social', value: 10, color: 'warning' }
  ] as const
  const orderColumns = [
    { key: 'id', label: 'Order' },
    { key: 'customer', label: 'Customer' },
    { key: 'amount', label: 'Amount' },
    {
      key: 'status',
      label: 'Status',
      render: (v: string) => (
        <Badge color={orderStatusColor[v as keyof typeof orderStatusColor]}>{v}</Badge>
      )
    }
  ]
  return (
    <div>
      <Grid fill min="12rem" gap="md" className="mb-xl">
        {stats.map((stat) => (
          <div key={stat.label}>
            <Card>
              <CardBody>
                <div className="d-flex justify-content-between align-items-start">
                  <div>
                    <div className="sm fg-neutral mb-xs">{stat.label}</div>
                    <div className="h4 mb-0">{stat.value}</div>
                  </div>
                  <Badge color={stat.color}>{stat.delta}</Badge>
                </div>
              </CardBody>
            </Card>
          </div>
        ))}
      </Grid>
      <div className="mb-xl">
        <Card>
          <CardBody>
            <h5 className="mb-md">Recent Orders</h5>
            <Table aria-label="Recent orders" hover>
              <TableHeader columns={orderColumns}>
                {(column) => <TableColumn key={column.key}>{column.label}</TableColumn>}
              </TableHeader>
              <TableBody items={orders}>
                {(row) => (
                  <TableRow key={row.id}>
                    {(columnKey) => {
                      const column = orderColumns.find((c) => c.key === columnKey)
                      const value = row[columnKey as keyof typeof row]
                      return (
                        <TableCell>
                          {column?.render ? column.render(String(value)) : value}
                        </TableCell>
                      )
                    }}
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </CardBody>
        </Card>
      </div>
      <Grid columns={{ base: 1, md: 2 }} gap="md">
        <div>
          <Card>
            <CardBody>
              <h5 className="mb-md">Recent Activity</h5>
              <List plain items={activity} />
            </CardBody>
          </Card>
        </div>
        <div>
          <Card>
            <CardBody>
              <h5 className="mb-md">Traffic Sources</h5>
              {traffic.map((src) => (
                <div key={src.label} className="mb-md">
                  <div className="d-flex justify-content-between mb-xs">
                    <small>{src.label}</small>
                    <small>{src.value}%</small>
                  </div>
                  <Progress color={src.color} value={src.value} />
                </div>
              ))}
            </CardBody>
          </Card>
        </div>
      </Grid>
    </div>
  )
}

Key points

  • Stat cards use <Badge> for delta indicators — the color prop drives the color semantically.
  • The orders table uses a render function to replace raw status strings with <Badge> components.
  • <List flush items={...} /> renders a borderless activity feed from a plain array.
  • Progress bars take color directly; value and max work like the native <progress> element.