npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@designdaddy/datagrid

v0.1.1

Published

Design Daddy data grid — search, filters, freeze, sort, pagination

Readme

@designdaddy/datagrid

Self-contained React data grid with search, column/value filters, freeze, show/hide columns, header sort, and pagination.

Styles are built in — import Grid only. No theme package and no separate CSS import required. The grid wraps itself in .gds-root with its own tokens so host-page CSS will not break alignment.


Table of contents

  1. Install
  2. Quick start
  3. What to use (Grid vs pieces)
  4. Data modes
  5. Column shape
  6. Grid props by feature
  7. Feature toggles
  8. Icon vs text toolbar
  9. Search field
  10. Responsive behavior
  11. Styling
  12. Custom cells & actions
  13. Pagination
  14. Remote / API data
  15. App wrapper tips
  16. Exports
  17. Local pack / publish
  18. Run the docs UI

Install

npm install @designdaddy/datagrid

Peer dependency: React 17+ (18 / 19 supported).

In this monorepo:

cd designdaddy
npm install

Quick start

1. Two parameters — columns + rows

import { Grid } from "@designdaddy/datagrid";

const columns = [
  { id: "name", label: "Name", width: 180 },
  { id: "email", label: "Email", width: 220 },
  { id: "role", label: "Role", width: 120 },
  { id: "status", label: "Status", width: 120 },
];

const rows = [
  { id: 1, name: "Aarav", email: "[email protected]", role: "Admin", status: "Active" },
  { id: 2, name: "Meera", email: "[email protected]", role: "Staff", status: "Pending" },
];

export default function UsersPage() {
  return <Grid columns={columns} rows={rows} />;
}

Search, sort, freeze, view, filters, clear, and pagination are included.
No extra CSS import — styles load with Grid.

2. One parameter — data (auto columns)

import { Grid } from "@designdaddy/datagrid";

const data = [
  { name: "Aarav", role: "Admin", status: "Active" },
  { name: "Meera", role: "Staff", status: "Pending" },
];

export default function UsersPage() {
  return <Grid data={data} />;
}

Object keys become columns; no columns array needed.

3. One parameter — URL (fetch + auto columns)

import { Grid } from "@designdaddy/datagrid";

export default function UsersPage() {
  return <Grid data="/api/users" />;
}

4. Toolbar — icons and toggles

<Grid columns={columns} rows={rows} toolbarIcons />

<Grid
  columns={columns}
  rows={rows}
  showFreeze={false}
  showPagination={false}
  showToolbar={false}
/>

Optional CSS fallback:

import "@designdaddy/datagrid/styles.css";

What to use (Grid vs pieces)

| Piece | What it is | When to use | |-------|------------|-------------| | Grid | Finished product (toolbar + table + pagination, all wired) | Almost always | | GridShell | Empty layout with 3 slots: filters / grid / pagination | Custom composition | | GridToolbar | Filters strip only | Custom shell, toolbar-only UI | | GridSection | Finished table (headers, sort, empty state, rows) | Custom shell, table-only UI | | ColumnPicker | Freeze / View / Filter popover button | Custom toolbar | | Pagination | Page bar only | Custom shell | | Utils | Pure helpers (no UI) | Custom filter/sort/data logic |

Day to day: use Grid.
Use GridShell + pieces only when you need a custom layout.

TableCell exists for custom GridSection row markup. It is not a separate docs module.


Data modes

// Two params — classic
<Grid columns={columns} rows={rows} />

// One param — JSON (keys → columns)
<Grid data={[{ name: "Aarav", role: "Admin" }]} />

// One param — URL (fetch, then same)
<Grid data="/api/users" />
<Grid data="https://api.example.com/users" />

// Rows only (no columns) → auto columns from keys
<Grid rows={rows} />

Supported data JSON shapes

| Shape | Result | |-------|--------| | [{ a: 1 }, { a: 2 }] | Rows as-is; columns from keys | | { data \| rows \| results \| items: [...] } | Uses that array | | { name: ["A","B"], age: [1,2] } | Columnar → row objects | | Single object | One row |

<Grid
  data="/api/users"
  fetchOptions={{ headers: { Authorization: "Bearer …" } }}
/>

Column shape

| Field | Type | Required | Description | |--------|------|----------|-------------| | id | string | yes | Field key on each row | | label | string | yes* | Header text (*auto from key in one-param mode) | | width | number | recommended | Pixel width | | sortable | boolean | no | Default true | | className | string | no | Extra class on <th> | | cellClassName | string | no | Extra class on <td> |

Prefer a unique id on each row, or set rowKey.


Grid props by feature

Data

| Prop | Default | Description | |------|---------|-------------| | columns | auto | Column defs. Omit / empty → derive from keys | | rows | [] | Row objects | | data | — | One-param: JSON or URL | | rowKey | "id" | Unique key field | | fetchOptions | — | Extra fetch init for URL data |

Toolbar & filters

| Prop | Default | Description | |------|---------|-------------| | showToolbar | auto | Master switch for filters section | | showFreeze | true | Freeze button | | showView | true | Show/hide columns | | showFilterColumns | true | Filter-columns picker | | showColumnFilter | true | Column + Value dropdowns | | showClear | true | Clear button | | showSearch | true | Search field | | toolbarIcons | false | Force icons at all widths | | searchPlaceholder | "Search any column…" | Search placeholder |

Pagination

| Prop | Default | Description | |------|---------|-------------| | showPagination | true | Pagination bar | | pageSize | 10 | Initial rows per page | | pageSizeOptions | [5,10,15,20,25,50,75,100] | Rows presets | | pageSizeMin / Max / Step | 5 / 100 / 5 | Custom size bounds | | showPageSizeCustom | true | Custom input (hidden on narrow screens) |

Custom rendering

| Prop | Description | |------|-------------| | renderCell | (columnId, row, column) => ReactNode | | renderActions | (row) => ReactNode — adds Actions column |

Styling

| Prop | Description | |------|-------------| | className | Extra class on .gds-root | | style | Inline styles / CSS variables | | theme | Design tokens → CSS variables |

Empty state & a11y

| Prop | Default | |------|---------| | emptyMessage | "No records found." | | emptyHint | package hint | | tableAriaLabel | "Data grid" |


Feature toggles

<Grid
  columns={columns}
  rows={rows}
  showFreeze={false}
  showView={false}
  showFilterColumns={false}
  showColumnFilter={false}
  showClear={false}
  showSearch={true}
  showPagination={false}
  showPageSizeCustom={false}
  showToolbar={false}
/>

| Prop | Hides | |------|--------| | showFreeze={false} | Freeze | | showView={false} | View | | showFilterColumns={false} | Filter-columns picker | | showColumnFilter={false} | Column + Value | | showClear={false} | Clear | | showSearch={false} | Search | | showToolbar={false} | Entire filters section | | showPagination={false} | Pagination (shows all filtered rows) | | showPageSizeCustom={false} | Custom size input |


Icon vs text toolbar

<Grid columns={columns} rows={rows} />                 // text on desktop; icons auto ≤900px
<Grid columns={columns} rows={rows} toolbarIcons />    // icons always

Buttons keep title / aria-label. Count badges (e.g. View 4) still show in icon mode.


Search field

  • No separate “Search” text label.
  • Magnifying-glass icon sits inside the input.
  • Placeholder: searchPlaceholder (default "Search any column…").

Responsive behavior

Layout follows grid width (container queries on .gds-root), not only the browser width.

| Width | Toolbar | Pagination | |-------|---------|------------| | Wide | Text buttons (unless toolbarIcons) | Prev/Next text, Rows + Custom, full info | | ≤900px | Auto icons, compact | One row: chevrons · pages · Rows · short info | | ≤520px | Tools + Column/Value; search may wrap | Still one pagination row |

Use parent minWidth: 0 and avoid overflow-x: hidden on ancestors.


Styling

Two approaches: your classes and built-in classes. Import your CSS after Grid so overrides win.

A. Your own className / theme / style

import { Grid } from "@designdaddy/datagrid";
import "./App.css"; // AFTER Grid

<Grid
  className="my-grid"
  theme={{
    primary: "#0f766e",
    border: "#e2e8f0",
    text: "#0f172a",
    muted: "#64748b",
    radius: "10px",
    fontSize: "15px",
  }}
  style={{ "--gds-text-md": "13px" }}
  columns={columns}
  rows={rows}
/>
/* App.css */
.my-grid {
  --ub-teal: #0f766e;
  --ub-border: #dbe3ee;
}

.my-grid .ub-table th {
  font-size: 11px;
}

B. Built-in class names (default look)

Override these under your wrapper:

| Class | What it styles | |-------|----------------| | .gds-root | Root + CSS variables | | .gds-shell | filters / grid / pagination layout | | .gds-shell__filters / __grid / __pagination | Slots | | .gds-toolbar | Filters toolbar card | | .gds-toolbar__tools / __filters / __search | Toolbar regions | | .gds-search-field / __icon | Search input + icon | | .gds-column-picker / __panel / __count | Freeze/View/Filter popover | | .gff-btn / --sm / --ghost | Buttons | | .gff-input / .gff-select | Inputs and selects | | .ub-table-wrap / .ub-table | Table | | .ub-table th / td | Headers and cells | | .user-builder-pagination | Pagination bar | | .user-builder-pagination-page--active | Active page |

.my-grid .gds-toolbar { box-shadow: none; }
.my-grid .user-builder-pagination-page--active { background: #0f766e; }

Limits (what you can / cannot do)

You can

  • Change colors, fonts, borders, radius via CSS variables / theme / scoped CSS
  • Add className on Grid and style children (.my-grid .ub-table …)
  • Set className / cellClassName on column defs
  • Restyle toolbar, table, and pagination independently

You should not

  • Remove core layout classes (.gds-root, .gds-shell, .ub-table, …) — layout/freeze can break
  • Rely on global button / input styles without scoping under .my-grid
  • Import your CSS before Grid (package CSS may load later and override you)

Theme tokens

| Token / theme key | Controls | |---------------------|----------| | --ub-teal / primary | Accent | | --ub-teal-dark / primaryDark | Dark accent | | --ub-teal-soft / primarySoft | Soft accent | | --ub-border / border | Borders | | --ub-text / text | Main text | | --ub-muted / muted | Muted labels | | --ub-bg / background | Root background | | --ub-surface / surface | Cards / inputs / table | | --ub-header-bg / headerBg | Table header | | --ub-radius / radius | Corner radius | | --gds-root-font-size / fontSize | Root font size | | --gds-font-family / fontFamily | Font stack | | --gds-text-sm / textSm | Small labels | | --gds-text-md / textMd | Inputs & buttons | | --gds-text-row / textRow | Picker rows |

Raw vars also work: theme={{ "--ub-teal": "#c00" }} or style={{ "--ub-teal": "#c00" }}.

Each docs module page (Grid, GridToolbar, GridSection, …) has its own Styling section with the classes for that piece.


Custom cells & actions

<Grid
  columns={columns}
  rows={rows}
  renderCell={(columnId, row) => {
    if (columnId === "status") {
      return (
        <span className={`ub-status ub-status--${String(row.status).toLowerCase()}`}>
          {row.status}
        </span>
      );
    }
    return row[columnId] ?? "—";
  }}
  renderActions={(row) => (
    <button type="button" className="ub-table-action-btn" onClick={() => edit(row)}>
      Edit
    </button>
  )}
/>

Status helpers: ub-status, ub-status--active, ub-status--inactive, ub-status--pending.


Pagination

<Grid
  columns={columns}
  rows={rows}
  pageSize={20}
  pageSizeOptions={[10, 20, 50, 100]}
  pageSizeMin={5}
  pageSizeMax={200}
  pageSizeStep={5}
  showPageSizeCustom
/>
  • Rows = presets
  • Custom = any value in min–max (desktop; auto-hidden when narrow)
  • Narrow: one row — ‹ · pages · › · Rows · short 1/1 · N

Remote / API data

// Built-in fetch
<Grid data="/api/members" />

// Parent fetch
function MembersGrid() {
  const [rows, setRows] = useState([]);
  useEffect(() => {
    fetch("/api/members").then((r) => r.json()).then(setRows);
  }, []);
  return <Grid columns={columns} rows={rows} />;
}

Filtering, sorting, and paging are client-side.


App wrapper tips

<div
  className="my-grid"
  style={{
    padding: 24,
    width: "100%",
    maxWidth: "100%",
    minWidth: 0,
    boxSizing: "border-box",
    textAlign: "left",
  }}
>
  <Grid columns={columns} rows={rows} />
</div>

Avoid #root { overflow-x: hidden; } — it can clip search / pagination.


Built-in toolbar features

  1. Search (icon inside input)
  2. Freeze
  3. View
  4. Filter columns
  5. Column + Value
  6. Clear
  7. Header sort (asc → desc → none)
  8. Pagination

Exports

import {
  Grid,
  GridShell,
  GridToolbar,
  GridSection,
  Pagination,
  PaginationSection,
  ColumnPicker,
} from "@designdaddy/datagrid";

Most apps only need Grid.

Utils (no UI): filterRows, sortRows, columnsFromRows, normalizeDataPayload, themeToCssVars, isDataUrl, …


Local pack / publish

npm run build -w @designdaddy/datagrid
cd packages/datagrid
npm pack
# then: npm install /path/to/designdaddy-datagrid-0.1.0.tgz

Run the docs UI

cd designdaddy
npm install
npm run dev:docs

Open http://localhost:3002 (or the URL Vite prints).

| Path | What you see | |------|----------------| | /docs/datagrid/overview | Overview + Desktop/Tablet/Mobile demo + Quick start + Styling | | /docs/datagrid/grid | Full Grid — props by feature + Styling | | /docs/datagrid/grid-shell | Shell composition demo + Styling | | /docs/datagrid/grid-toolbar | Toolbar only (no table/pagination) + Styling | | /docs/datagrid/grid-section | Table only + Styling | | /docs/datagrid/filters | ColumnPicker only + Styling | | /docs/datagrid/pagination | Pagination only + Styling | | /docs/datagrid/utils | Helpers (no UI) | | /docs/datagrid/example-* | Focused examples |

Demos include a Desktop (1100px) / Tablet (768px) / Mobile (390px) switcher — scroll horizontally if needed; you do not have to resize the browser.

npm run build -w @designdaddy/docs
npm run preview -w @designdaddy/docs

Folder layout

packages/datagrid/
  package.json
  README.md
  src/
    index.js
    Grid/           # facade you usually import
    GridShell/      # layout slots
    GridToolbar/    # filters strip
    GridSection/    # table region
    Filters/        # ColumnPicker
    Pagination/
    DataTable/      # internal cell helpers (used by GridSection)
    styles/
    utils/
    icons.jsx

Notes for packaging

  1. "exports" points at dist/ — run npm run build before publish.
  2. CSS ships via dist/index.css (imported from the JS entry).
  3. react / react-dom are peerDependencies.
  4. Consumers supply columns/rows or data — no sample rows in the package.