apps/shade/src/docs/introduction.mdx
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Introduction" /> <div className="sb-doc">If you're shipping admin features, Shade gives you four things:
A set of visual values (color, type, spacing, radius, motion) that automatically work in light and dark mode.
A set of layout primitives (Stack, Inline, Box, Grid, Container, Text) that replace the endless flex flex-col gap-4 strings with something readable.
A library of generic UI controls (Button, Input, Dialog, Tabs, and so on) built on Radix and ShadCN, accessible by default.
A smaller set of product-shaped compositions for things Ghost does over and over — KPI cards, filter builders, the area chart on Stats — where the generic controls aren't enough.
The line between those four layers is the most important thing to understand about Shade. We cover it in detail on the Architecture page, including a glossary of terms.
Designers working in code use Shade to compose screens fast. The primitives and components do the heavy lifting; you focus on the structure and content of the surface you're designing.
Engineers use it as a reliable substrate. If a control already exists in Shade, use it — it's accessible, themed, and tested. If it doesn't, the design system tells you which layer to build into.
AI agents generating UI code use Shade as a constraint. The layer rules and the typed component APIs let the agent pick the right tool without inventing components or making up tokens.
Shade lives in the Ghost monorepo (apps/shade) and is consumed by the React admin apps via @tryghost/shade/* entrypoints. There's nothing to install separately — just import:
import {Button} from '@tryghost/shade/components';
function MyComponent() {
return <Button>Continue</Button>;
}
To pick up Shade's CSS in your app, import its stylesheet once at your entry point:
@import "@tryghost/shade/styles.css";
If you're using Tailwind v4, add Shade's source paths to your @source directives so utility generation picks up classes used inside Shade components.
Every Shade component is themed. To toggle modes, wrap your tree in ShadeApp:
import {ShadeApp} from '@tryghost/shade/app';
import {Button} from '@tryghost/shade/components';
export default function App() {
return (
<ShadeApp darkMode={false}>
<Button>Continue</Button>
</ShadeApp>
);
}
ShadeApp adds a .shade scope to your tree and toggles a .dark class inside it. If you'd rather not use the wrapper, you can apply those two classes manually — the components will respond.
If you're new here, read the Architecture page next. It explains the layers (tokens, primitives, components, recipes, features) with a glossary so the vocabulary makes sense, and a short decision rule for choosing where new code belongs.
If you already know your way around and just want to ship, browse:
inputSurface that shape every form control's chrome.Stack, Inline, Box, Grid, Container, Text. The structural vocabulary.Each section's pages have a description, props, and live examples.
</div>