Colors
Semantic color roles, theming architecture, and usage guidelines used across PyColors UI.
OverviewLink to section
Colors in PyColors UI are designed as semantic product roles, not decorative values.
The system gives every interface layer a stable meaning: page surfaces, cards, text, actions, states, borders, form controls, sidebars, and charts. Components consume those roles through utilities like bg-card, text-foreground, text-muted-foreground, bg-primary, and border-border instead of hardcoding visual values locally.
At the end of this page, you will understand how PyColors structures color roles, how light and dark mode remain predictable, and how to apply color decisions without creating theme drift.
Why this matters
Color consistency is one of the fastest signals of product quality. A semantic color system keeps dashboards, marketing pages, documentation, forms, and reusable components visually aligned without forcing every component to reinvent its own palette.
Use tokens that explain product meaning: surface, text, action, state, input, and data.
Map CSS variables into Tailwind utilities so components stay stable when themes evolve.
Keep reusable components, dashboards, docs, and commercial pages visually coherent.
What you’ll doLink to section
Understand the semantic role model behind PyColors colors.
Map CSS variables to Tailwind utilities through the token layer.
Apply colors in components without raw values or one-off overrides.
Use decision rules to keep UI colors, state colors, and chart colors separate.
ArchitectureLink to section
PyColors uses an OKLCH-based color system exposed through CSS variables and mapped into Tailwind semantic utilities.
OKLCH gives the token layer more predictable control over perceived lightness, contrast, and theme balance than raw RGB or one-off HSL values. That matters when a product must support light mode, dark mode, reusable UI components, long documentation pages, dashboards, settings screens, and commercial surfaces.
Core principle
Components should consume color roles. The token layer should decide how those roles look.
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-border: var(--border);
--color-ring: var(--ring);
}export function ExampleCard() {
return (
<div className="rounded-2xl border border-border bg-card p-5 text-card-foreground">
<p className="text-sm font-medium text-foreground">Semantic surface</p>
<p className="mt-1 text-sm text-muted-foreground">
This component uses product roles instead of raw color values.
</p>
</div>
);
}:root {
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
}This keeps the component API stable while allowing the underlying theme to evolve centrally. Components keep the same classes, token meaning stays stable, and the theme layer handles contrast and visual balance.
Role modelLink to section
PyColors groups colors by product responsibility. This keeps the system easier to reason about and prevents the table of contents from becoming noisy.
| Category | Tokens | Used for |
|---|---|---|
| Surfaces | background, card, popover, sidebar | Page layers, cards, overlays, navigation |
| Text | foreground, muted-foreground, card-foreground | Primary copy, secondary copy, surface-specific text |
| Actions | primary, secondary, accent, muted | Buttons, emphasis, subtle interaction areas |
| States | destructive, success, warning | Product feedback, validation, risk, confirmation |
| Inputs | border, input, ring | Forms, focus states, separators, control outlines |
| Charts | chart-1 to chart-5 | Data visualization only |
Why this matters
Separating UI roles from chart roles prevents data visualization colors from leaking into product states. A chart palette should not become the source of truth for buttons, alerts, or destructive actions.
ImplementationLink to section
Use semantic utilities in every reusable component.
export function ProductNotice() {
return (
<div className="rounded-2xl border border-border bg-card p-5 text-card-foreground">
<p className="text-sm font-medium text-foreground">Production-ready surface</p>
<p className="mt-1 text-sm text-muted-foreground">
The visual intent comes from the design system, not from local overrides.
</p>
</div>
);
}Avoid raw values inside reusable UI.
export function ProductNotice() {
return (
<div className="rounded-2xl border border-[#e5e7eb] bg-[#ffffff] p-5 text-[#111827]">
<p className="text-sm text-[#6b7280]">This creates theme drift.</p>
</div>
);
}Common pitfall
Do not solve repeated color needs with local overrides. If the same visual intent appears in multiple places, define or adjust the semantic role instead.
Decision guideLink to section
Use PyColors semantic color roles when:
- the component is reusable
- the UI must support light and dark mode
- the surface appears in dashboards, docs, marketing, or settings
- the same visual meaning should remain stable across the product
- theme updates should happen centrally
Avoid local raw values when:
- the component belongs to the design system
- the value represents a product state
- the color affects text contrast or focus visibility
- the color will likely be reused elsewhere
- the value needs to survive future theme changes
Inline CTA
Ready to move from visual consistency to a production-shaped SaaS foundation? Explore Starter Pro for auth, billing, backend, and delivery patterns built on top of PyColors UI.
Common mistakesLink to section
Next stepsLink to section
Continue with readable hierarchy, rhythm, and semantic text structure.
Understand the token layer that keeps PyColors UI consistent across products.
See how primitives consume semantic roles across real product interfaces.
Move from UI consistency to production foundations with auth, billing, and backend structure.