Installation
Install @pycolors/ui, load the token CSS, and verify your first public import in a React or Next.js app.
Install the primitive layer firstLink to section
This guide takes you from an existing React app to a styled PyColors component. You will install the packages, connect the CSS, and verify a small screen in your own app.
PrerequisitesLink to section
Before installing, confirm the consuming app already has:
- React and React DOM installed;
- Tailwind CSS v4 configured in the app stylesheet/build;
- a global stylesheet where token CSS can be imported;
- a React or Next.js setup that supports ESM packages.
@pycolors/ui is Tailwind-friendly and token-driven. Components use semantic
utilities such as bg-card, text-muted-foreground, border-border, and
ring-ring. Those utilities need matching design tokens in the consuming app.
Install packagesLink to section
Install the public primitives and their semantic tokens together. This is the canonical first-install command for a pnpm project.
pnpm add @pycolors/ui @pycolors/tokensUse the equivalent npm install or yarn add command when the app does not use
pnpm. Keep both package names in the command so the components and their token
contract arrive together.
Peer dependenciesLink to section
@pycolors/ui declares these peer dependencies:
| Package | Requirement | Notes |
|---|---|---|
react | >=18 | Required by the React primitives. |
react-dom | >=18 | Required for React DOM apps. |
lucide-react | >=0.300.0 | Optional peer dependency. Install it when your app or examples use Lucide icons. |
The package README documents this install command for peer dependencies:
pnpm add react react-dom lucide-reactUse the equivalent npm or yarn command when the app does not use pnpm.
Add design tokensLink to section
The canonical install command above includes @pycolors/tokens. Use its token
CSS when your app does not already provide the PyColors semantic variables and
Tailwind v4 mappings.
In a Next.js app with an app/ directory at the project root, add the following
to your global stylesheet and import that stylesheet from app/layout.tsx.
Keep any existing app styles after these directives.
@import "tailwindcss";
@import "@pycolors/tokens/tokens.css";
@source "../node_modules/@pycolors/ui/dist";
@custom-variant dark (&:where(.dark, .dark *));
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}Tailwind ignores node_modules during automatic source detection. The
@source directive
includes the installed component classes so their utilities are generated.
This is a CSS scan path; JavaScript imports still use only @pycolors/ui.
The path is relative to the stylesheet. For src/app/globals.css, use
../../node_modules/@pycolors/ui/dist instead. In other React setups, adjust
the path to reach the consuming app's installed package and load this stylesheet
from the app's entry point. Do not add a second Tailwind import if one already
exists.
The base rules apply the semantic border and page colors. Merge them with your existing base styles if the app already sets those roles.
The token CSS provides:
- semantic CSS variables such as
--background,--foreground,--card,--primary,--border, and--ring; - light and dark values using a
.darkclass strategy; - Tailwind v4
@theme inlinemappings for semantic utilities.
Dark mode
@pycolors/tokens uses a .dark class strategy. Add or remove the dark
class on the document root through your existing theme logic. The
@custom-variant
directive
makes Tailwind's dark: utilities follow that same class.
Verify components in StorybookLink to section
Use the consumer Storybook guide to render PyColors in your own React/Vite Storybook with tokens, generated Tailwind utilities, and a light/dark toolbar. For examples without local setup, open PyColors UI Explorer.
Import from the public entry pointLink to section
Import supported primitives from @pycolors/ui.
In the same Next.js app, use this page to verify the installation. Other React apps can render the exported component from their existing route or entry point.
import {
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@pycolors/ui";
export default function FirstPyColorsCard() {
return (
<Card>
<CardHeader>
<CardTitle>PyColors UI installed</CardTitle>
<CardDescription>
Your app can now compose token-driven product primitives.
</CardDescription>
</CardHeader>
<CardContent>
<Button asChild>
<a href="https://pycolors.io/docs/ui/usage-patterns">
Explore usage patterns
</a>
</Button>
</CardContent>
</Card>
);
}Do not import from package internals.
Prefer
- imports from
@pycolors/ui - semantic token utilities such as
bg-cardandtext-muted-foreground - one verified screen before a broad migration
Avoid
- imports from
@pycolors/ui/src/* - imports from
@pycolors/ui/dist/* - raw color overrides that bypass tokens
Server and client component boundariesLink to section
Static primitive composition can stay server-rendered in a Next.js App Router
app. Add "use client" only when the file owns browser state, effects, event
handlers, or interactive overlay/toast state.
import { Button, Card, CardContent, CardHeader, CardTitle } from "@pycolors/ui";
export function BillingCard() {
return (
<Card>
<CardHeader>
<CardTitle>Billing ready</CardTitle>
</CardHeader>
<CardContent>
<Button asChild>
<a href="/settings/billing">Manage billing</a>
</Button>
</CardContent>
</Card>
);
}Use a client boundary for local interaction state.
"use client";
import { Button } from "@pycolors/ui";
export function SaveButton() {
return (
<Button type="button" onClick={() => window.alert("Saved")}>
Save
</Button>
);
}Boundary rule
Keep pages and data loading server-side when possible. Move only the interactive leaf into a client component.
Verify the first screenLink to section
Confirm the app buildsLink to section
Run the type-check and production-build scripts declared in your consuming
app's package.json. For example, when it defines types:check and build:
pnpm types:check
pnpm buildCheck token outputLink to section
Open the screen in light and dark mode. Confirm semantic utilities such as
bg-card, text-foreground, border-border, and ring-ring resolve to
real styles.
Check accessibility basicsLink to section
Tab through interactive elements, verify visible focus, confirm links have descriptive text, and avoid color-only feedback.
Expand one surface at a timeLink to section
After the first screen works, move to usage patterns and migration guidance before replacing a full product area.
Common mistakesLink to section
| Mistake | Safer path |
|---|---|
Importing from @pycolors/ui/src/* or @pycolors/ui/dist/* | Import from @pycolors/ui. |
| Installing UI without token CSS or equivalent semantic variables | Load @pycolors/tokens/tokens.css or provide the same semantic roles intentionally. |
| Components render without spacing or variant styles | Register the installed UI package with @source, using a path relative to the global stylesheet. |
Adding "use client" to every page | Add a client boundary only where browser behavior is owned. |
| Replacing product logic with UI primitives | Keep routing, auth, billing, validation, and data fetching in app code. |
| Styling with raw colors first | Use semantic utilities and customize tokens centrally when needed. |