@graphprotocol/gds-react
React components for The Graph Design System.
Installation
pnpm add @graphprotocol/gds-react --allow-build=@graphprotocol/gds-react
--allow-build allows the package's postinstall script to run. This script auto-updates the GDS AI skill if you have it installed — it does nothing else.
Peer Dependencies
This package requires the following peer dependencies:
pnpm add react react-dom react-is tailwindcss
Setup
-
Ensure Tailwind CSS is installed and configured in your project (preferably with Vite).
-
Replace the tailwind import in your main CSS file with @graphprotocol/gds-react:
- @import 'tailwindcss';
+ @import '@graphprotocol/gds-react';
-
Register source paths relative to your CSS file:
@import '@graphprotocol/gds-react';
+ @source '../src';
@graphprotocol/gds-react disables Tailwind's default content scanning as an optimization measure, so you must explicitly register your source paths using @source directives. Make sure to include all paths where Tailwind classes are used.
-
Wrap your app with GDSProvider:
import { GDSProvider } from '@graphprotocol/gds-react'
function App() {
return <GDSProvider>{/* your app */}</GDSProvider>
}
The provider accepts optional props:
-
theme - 'dark', 'light', or 'system'. Omit for uncontrolled mode (the theme starts at defaultTheme, optionally restored from storage via persistTheme). Pass a value for controlled mode.
-
defaultTheme - initial theme in uncontrolled mode. Defaults to 'dark'.
-
onThemeChange - called whenever the theme changes via setTheme() (e.g. from <ThemeSwitcher />).
-
persistTheme - opt-in persistence so the user's theme selection survives reloads. Omit (default) for no persistence. Accepts:
'localStorage' — reads/writes localStorage['gds-active-theme']. Inline pre-hydration script restores the value before first paint (no SSR flash).
'cookie' — reads/writes a gds-active-theme cookie (path=/; max-age=31536000; samesite=lax). Same no-flash SSR; also readable server-side (e.g. via Next.js headers()).
{ get, set } — custom adapter (different key, encryption, remote storage, etc.). No pre-hydration script is emitted; for zero-flash SSR, inject your own inline script in your HTML head.
The two string presets share the key 'gds-active-theme' — use a custom adapter for per-app isolation on the same origin.
-
direction - 'ltr' (default) or 'rtl'
-
language - defaults to 'en' as long as direction is 'ltr'
To read or change the theme from anywhere in the app, use the useGDS() hook:
import { useGDS } from '@graphprotocol/gds-react'
const { theme, activeTheme, setTheme } = useGDS()
theme is 'dark' | 'light' | 'system'. activeTheme resolves 'system' to 'dark' or 'light' based on the user's OS preference.
Server-side rendering (Next.js App Router): add suppressHydrationWarning to your <html> tag in app/layout.tsx. GDSProvider applies the theme class to <html> before React hydrates (this is what prevents a flash of wrong theme), which would otherwise trigger a hydration warning since React owns <html> in App Router.
<html lang="en" suppressHydrationWarning>
-
Optional recommended steps:
-
If you use VS Code (or a fork like Cursor), install the Tailwind CSS IntelliSense extension.
-
If it doesn't automatically recognize GDS-specific classes like text-16, it is likely because it cannot find the CSS file that registers GDS's Tailwind theme and plugin (which can happen in monorepos or projects with unusual/complex directory structures). Add the following to .vscode/settings.json and customize the paths to match your project:
{
"tailwindCSS.experimental.configFile": {
"packages/ui/globals.css": "packages/ui/**"
}
}
-
Set up your formatter to sort Tailwind classes:
Oxfmt (recommended) — add to .oxfmtrc.json:
{
"sortTailwindcss": {
"functions": ["cn"],
"preserveWhitespace": true,
"stylesheet": "packages/ui/globals.css"
}
}
Prettier — install prettier-plugin-tailwindcss and add to your config (e.g. .prettierrc):
{
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindPreserveWhitespace": true,
"tailwindFunctions": ["cn"],
"overrides": [
{
"files": "packages/ui/**",
"options": {
"tailwindStylesheet": "packages/ui/globals.css"
}
}
]
}
Make sure to customize the paths to match your project (files should match any file that contains classes, and tailwindStylesheet should point to your main CSS file, from which you imported GDS).
That's it, you're ready to use GDS utilities and components!
Usage
import { Button, Card, Input } from '@graphprotocol/gds-react'
function Example() {
return (
<Card>
<Input label="Enter text..." />
<Button variant="primary">Submit</Button>
</Card>
)
}
Exports
@graphprotocol/gds-react - Styled components
@graphprotocol/gds-react/base - Base/primitive (mostly unstyled) components
@graphprotocol/gds-react/hooks - React hooks that are useful when working with GDS components
@graphprotocol/gds-react/icons - React components for gds-icons
@graphprotocol/gds-react/utils - React-specific utility functions
AI Skill
Strongly recommended. GDS ships with a skill that teaches AI agents (Claude Code, Cursor, Copilot, Cline, etc.) how to build UIs with GDS — component selection, styling patterns, design tokens, and common pitfalls.
npx skills add graphprotocol/gds --skill gds
Once installed, the skill is automatically kept up to date whenever you update @graphprotocol/gds-react. Note: this will work as long as the package is listed in pnpm-workspace.yaml's allowBuilds or onlyBuiltDependencies list, which it should if you installed the package with --allow-build=@graphprotocol/gds-react as suggested above. If not, you can run pnpm approve-builds and manually select the @graphprotocol/gds-react package. It might save the approval to package.json if you have an "pnpm" key there; feel free to move it to pnpm-workspace.yaml if you prefer, but both should work.
License
MIT