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
@pycolors/ui is the public primitive package for PyColors product interfaces.
Install it when you want reusable React primitives for SaaS surfaces such as
forms, settings, dashboards, billing panels, overlays, and data views.
Core idea
Install the package, load the semantic token CSS your app needs, import from
@pycolors/ui, then verify one small screen before migrating more UI.
PrerequisitesLink to section
Before installing, confirm the consuming app already has:
- React and React DOM installed;
- Tailwind CSS available 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 @pycolors/ui with your package manager.
pnpm add @pycolors/uinpm i @pycolors/uiyarn add @pycolors/uiPeer 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
Use @pycolors/tokens when your app does not already provide the PyColors
semantic variables and Tailwind v4 mappings.
pnpm add @pycolors/tokensnpm i @pycolors/tokensyarn add @pycolors/tokensImport the token CSS once from your global stylesheet.
@import "@pycolors/tokens/tokens.css";In the PyColors marketing app, this is done from
apps/marketing/app/global.css.
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 at the app shell or document root through your existing theme logic.
Import from the public entry pointLink to section
Import supported primitives from @pycolors/ui.
import {
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@pycolors/ui";
export 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="/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 consuming app’s type check and build command. In this monorepo, the relevant docs app check is:
pnpm --filter pycolors-marketing 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. |
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. |