gridsmith-ui
v0.36.0
Published
Gridsmith component library — React components and charts with design tokens and a CSS custom property theming engine
Downloads
2,813
Maintainers
Readme
gridsmith-ui
React components and charts with a CSS custom property theming engine, and 5 icon packs.
Installation
gridsmith-ui needs React 19. On a React 18 project, upgrade react, react-dom, @types/react and @types/react-dom to 19 first; installing with --force or --legacy-peer-deps gives an app that cannot run. On React 18, AppShell and PageContainer stop with an error that says so.
npm install gridsmith-uiUpgrading: each release in CHANGELOG.md (in this package, node_modules/gridsmith-ui/CHANGELOG.md) ends with an upgrade note for agents: what an app on the previous version changes. A 0.x minor release can break code written for the one before, so ^0.26.0 never reaches 0.27.0 by itself.
Charts (optional)
npm install rechartsHeavy components (optional)
Some components depend on large third-party libraries. They live in entry points of their own so the main bundle stays small — install the library only if you use the component:
npm install @tiptap/react @tiptap/pm @tiptap/starter-kit lowlight \
@tiptap/extension-code-block-lowlight @tiptap/extension-color @tiptap/extension-font-family \
@tiptap/extension-highlight @tiptap/extension-image \
@tiptap/extension-placeholder @tiptap/extension-subscript @tiptap/extension-superscript \
@tiptap/extension-table @tiptap/extension-table-cell @tiptap/extension-table-header \
@tiptap/extension-table-row @tiptap/extension-task-item @tiptap/extension-task-list \
@tiptap/extension-text-align @tiptap/extension-text-style # gridsmith-ui/editor
npm install @tiptap/extension-mention@<v> @tiptap/suggestion@<v> # gridsmith-ui/editor-mentions: <v> is your @tiptap/core version (npm ls @tiptap/core)
npm install react-markdown remark-gfm # gridsmith-ui/chat
npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities # gridsmith-ui/kanban
npm install @dnd-kit/core @dnd-kit/utilities # gridsmith-ui/dashboard
npm install @tanstack/react-table # gridsmith-ui/data-grid
npm install @tanstack/react-virtual # gridsmith-ui/virtualized
npm install react-resizable-panels # gridsmith-ui/resizableIcon packs
The Icon component uses lucide-react by default, and every other pack falls back to it for a missing name, so always install it. For another pack, install it and register it once, at the top of your app's shell (in Next.js the shell is a client file; never the root layout, a server component) and before any preloadPack: the library names no pack but Lucide, so your bundler (Next.js's included) only meets the pack you installed. A pack you draw without registering it draws Lucide's icons, and in development the console names the line to add.
# Default and fallback (required)
npm install lucide-react
# Alternative packs: install the one your theme uses
npm install @phosphor-icons/react # phosphor
npm install @heroicons/react # heroicons
npm install @tabler/icons-react # tabler
npm install react-icons # feather (via react-icons)import { registerIconPack } from "gridsmith-ui/icons";
registerIconPack("feather", () => import("react-icons/fi"));
// phosphor: () => import("@phosphor-icons/react")
// heroicons: () => import("@heroicons/react/24/outline")
// tabler: () => import("@tabler/icons-react")Setup
Import the design tokens and Tailwind bindings in your CSS entry point:
@import "tailwindcss";
@import "gridsmith-ui/roots.css";
@import "gridsmith-ui/tokens.css";
@import "gridsmith-ui/tailwind.css";
@source "../node_modules/gridsmith-ui/dist/*.js";- roots.css — the CSS custom property engine (L1 roots, L2 derived scales, L3 semantics)
- tokens.css — default Precision Minimal preset values (a Gridsmith project imports the
tokens_cssfromget_tokenscalled withcss: true, saved asgridsmith-tokens.css, instead) - tailwind.css — maps
--ds-*tokens to Tailwind utilities (p-ds-4,text-2xs,opacity-disabled) - @source — tells Tailwind to scan the compiled components; without it they render unstyled. It must come after every
@import.
For the fastest icon rendering on cold loads, call preloadPack in your entry point before createRoot (in Next.js, at the top of the shell), another pack's after its registration:
import { preloadPack } from "gridsmith-ui/icons";
preloadPack("lucide");Server-rendered apps (Next.js, Remix). Wrap the app's top in LocaleProvider, from gridsmith-ui, with the page's language and the request's Accept-Language header: <LocaleProvider lang={LANG} acceptLanguage={acceptLanguage}>, the same LANG on <html lang>. The server then writes dates and numbers in the visitor's form, as the browser does, so the page hydrates without a mismatch. In Next.js, read the header in the root layout ((await headers()).get("accept-language")). A Vite app doesn't need it.
Entry Points
Every entry but gridsmith-ui/utils is client code, each file opening with "use client". In Next.js (15 or later), a server component (a page with no 'use client' of its own) renders the components with plain data: text, numbers, dates, elements. A function (onClick, onChange, a column's render) needs a client component of yours, and so does calling the library's hooks; a server page hands the library's constants and contexts on as they are, without reading them, and renders a compound part by its own name (TabsList for Tabs.List, CollapsibleTrigger for Collapsible.Trigger). On the server (a page, a route handler, a server action), call the helpers from gridsmith-ui/utils, passing them requestLocale(LANG, acceptLanguage) so their words read as the components' do; a Date is read there in the server's time zone, so hand RelativeTime and the Calendar the data for what the visitor reads in their own. Vite and Remix ignore the marker.
| Import path | What it provides |
|---|---|
| gridsmith-ui | Every component outside the entry points below (actions, forms, data display, navigation, overlays, feedback, layout) |
| gridsmith-ui/charts | 13 chart components (Bar, Line, Area, Pie, Composite, Scatter, Radar, RadialBar, Funnel, Treemap, Sankey, Sparkline, ChartContainer) + useChartColors hook + categoryKind() |
| gridsmith-ui/editor | RichTextEditor (requires the tiptap packages + lowlight) |
| gridsmith-ui/editor-mentions | useMentions, @mentions for RichTextEditor (requires @tiptap/extension-mention and @tiptap/suggestion at your other tiptap packages' version) |
| gridsmith-ui/chat | MarkdownContent for chat replies; pass it to ChatMessageList's renderContent (requires react-markdown + remark-gfm) |
| gridsmith-ui/kanban | KanbanBoard (requires @dnd-kit/*) |
| gridsmith-ui/dashboard | DashboardGrid, DashboardItem, DashboardPalette, DashboardEditor and useDraftHistory: a dashboard its people arrange (requires @dnd-kit/core and @dnd-kit/utilities) |
| gridsmith-ui/data-grid | DataGrid (requires @tanstack/react-table) |
| gridsmith-ui/virtualized | VirtualizedList (requires @tanstack/react-virtual) |
| gridsmith-ui/resizable | ResizablePanelGroup, ResizablePanel, ResizableHandle, SplitView (requires react-resizable-panels) |
| gridsmith-ui/icons | Icon, IconProvider, preloadPack, registerIconPack — 5 icon packs with two-phase loading |
| gridsmith-ui/utils | cn() — className merge utility (clsx + tailwind-merge) — the shared focus styles (FOCUS_RING and its kin) for an element of your own that takes focus, and the helpers server code calls: the repeat rules, calendar days and date ranges, time zones, a chart's label kind, a dashboard's layout (moveItem, resizeItem, addItem, removeItem, normaliseLayout), and requestLocale() for a request's locale. Nothing in it needs React or a browser |
| gridsmith-ui/roots.css | CSS custom property engine |
| gridsmith-ui/tokens.css | Default preset token values |
| gridsmith-ui/tailwind.css | Tailwind v4 @theme bindings for --ds-* tokens |
Usage
import { Button, Card, Input, Table } from "gridsmith-ui";
import { BarChart, LineChart } from "gridsmith-ui/charts";
import { RichTextEditor } from "gridsmith-ui/editor";
import { useMentions } from "gridsmith-ui/editor-mentions";
import { MarkdownContent } from "gridsmith-ui/chat";
import { KanbanBoard } from "gridsmith-ui/kanban";
import { DataGrid } from "gridsmith-ui/data-grid";
import { VirtualizedList } from "gridsmith-ui/virtualized";
import { ResizablePanelGroup, ResizablePanel, ResizableHandle, SplitView } from "gridsmith-ui/resizable";
import { Icon, IconProvider } from "gridsmith-ui/icons";
import { cn } from "gridsmith-ui/utils";Theming
Override any --ds-* CSS custom property on :root or a wrapper element. All derived scales update reactively.
:root {
--ds-hue-primary: 220;
--ds-radius-base: 6px;
--ds-space-unit: 4px;
}Icon packs
Wrap your app in <IconProvider> to select a pack:
<IconProvider pack="phosphor" weight={1.5}>
<App />
</IconProvider>Troubleshooting
- Import errors after installing a package while
viteis running — restart withnpm run dev -- --force(or deletenode_modules/.vite); Vite's dependency cache otherwise serves the pre-install module graph. - Components render unstyled — add
@source "../node_modules/gridsmith-ui/dist/*.js"to your CSS entry point after every@import. Tailwind v4 needs it to scan the compiled components, and rejects an@importthat follows it. IconProvideris not exported — upgrade to a currentgridsmith-ui; the provider ships from thegridsmith-ui/iconsentry point.- "Attempted to call … from the server" in Next.js — a server component called one of the library's functions or hooks: take the helper from
gridsmith-ui/utils, or mark the file'use client'. "Functions cannot be passed directly to Client Components" — it handed a component a function: move that element into a client component of yours. - A component test in jsdom fails on
ResizeObserver— jsdom has none: stub it in the test setup (globalThis.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} }), as the components measure their width.
Peer Dependencies
| Package | Required |
|---------|----------|
| react / react-dom | Yes (^19) |
| lucide-react | Yes (the default icon pack and every pack's fallback) |
| recharts | Optional (required for gridsmith-ui/charts) |
| @tiptap/*, lowlight | Optional (required for gridsmith-ui/editor). The mention packages for gridsmith-ui/editor-mentions aren't declared: install them at your @tiptap/core version, as tiptap's packages must all be one version |
| react-markdown, remark-gfm | Optional (required for gridsmith-ui/chat) |
| @dnd-kit/* | Optional (required for gridsmith-ui/kanban; @dnd-kit/core and @dnd-kit/utilities alone for gridsmith-ui/dashboard) |
| @tanstack/react-table | Optional (required for gridsmith-ui/data-grid) |
| @tanstack/react-virtual | Optional (required for gridsmith-ui/virtualized) |
| react-resizable-panels | Optional (required for gridsmith-ui/resizable) |
| @phosphor-icons/react | Optional |
| @heroicons/react | Optional |
| @tabler/icons-react | Optional |
| react-icons | Optional |
License
MIT
