UIUpdated August 18, 2026

Overview

Composable UI primitives built for real SaaS interfaces. Designed to scale from product validation to production.

UIComposable primitives

Build interfaces that scale with your productLink to section

PyColors UI components are small, composable primitives built for real SaaS interfaces.

They are designed to help you build:

  • dashboards
  • forms
  • settings pages
  • billing surfaces
  • admin tools
  • auth flows
  • data-heavy product views

This is not a UI kit for isolated demos.

It is a component foundation for products that need to evolve without becoming inconsistent.

Core idea

UI components are the lowest product layer. They should stay small, token-driven, and predictable.

Where UI fitsLink to section

PyColors is organized as a product system, not only a component library.

Design System

Tokens, colors, typography, radius, and shadows define the visual foundation.

Mental modelLink to section

Tokens define the system. Components stay small. Guides explain usage. Patterns handle complexity. Starters connect everything into a product.

This keeps the UI layer focused.

If a primitive starts carrying too much product logic, the abstraction is probably in the wrong place.

Interactive component examplesLink to section

Storybook is the canonical interactive component example system for @pycolors/ui. Use it to inspect isolated component states, exercise keyboard and pointer behavior, and compare the PyColors light and dark themes. These Fumadocs pages remain the public usage documentation and product-context examples; Storybook does not replace them.

Open PyColors UI Explorer to try the public catalog without cloning the repository. Each component page links to its exact example. To use PyColors in your own application’s Storybook, follow the consumer Storybook guide.

Contributors can also run Storybook from the repository root:

pnpm --filter @pycolors/ui storybook

Maintaining examplesLink to section

Canonical examples live in packages/ui/stories/components/<family>.stories.tsx. The public src/index.ts barrel remains the source of truth for supported families. Foundations demonstrate existing tokens; compositions are small synthetic examples. The local navigation orders Foundations, Components, then Compositions.

When a public component or meaningful state changes:

  1. Update its typed family module with an explicit components-<family> ID, stable story exports, a Default, a useful description and its Fumadocs link. Import through ../../src/index.js, never a component's internal file.
  2. Expose only supported args/controls. Controlled examples own their state; keep labels, native/Radix semantics, tokens and both themes intact.
  3. Update the matching component tests and Fumadocs page when behavior changes. Run pnpm --filter @pycolors/ui verify, pnpm check:ui-package, and pnpm --filter pycolors-marketing types:check for documentation changes.
  4. Install Chromium with pnpm --filter @pycolors/ui test:storybook:install, then run pnpm --filter @pycolors/ui test:storybook for interactions, accessibility scans, light/dark and desktop/mobile checks. Check generated story IDs separately. Automated checks do not replace assistive-technology and visual review; setup, selection and diagnostics are in the story guide.
  5. Preserve old IDs through shared-render compatibility entries when migrating links. The migration ledger and deprecation rules live in packages/ui/stories/README.md; the legacy module contains no new examples.

Story-only changes do not need a package release. Public API/behavior changes retain their normal Changeset, test and documentation requirements. Public stories must contain only public primitives and fixtures: no Pro source, private imports, credentials or customer data. Public Explorer hosting and a full consumer integration guide remain separate work; no production Explorer URL is assumed.

Start with the essentialsLink to section

Component categoriesLink to section

Composition rulesLink to section

Start with semantic tokensLink to section

Use token-driven utilities such as bg-card, text-muted-foreground, border-border, and shadow-sm.

Components should consume meaning, not raw visual values.

Compose before configuringLink to section

Prefer composition over large prop APIs.

If a component needs too many product-specific props, extract the product behavior into a pattern.

Keep interaction ownership clearLink to section

A primitive should usually own one interaction responsibility.

Complex flows like forms, tables, overlays, and async actions belong in Guides or Patterns.

Use UI for structure, not business logicLink to section

Components should render state clearly.

Product rules, billing checks, auth ownership, and backend decisions should stay outside the primitive layer.

When to use PatternsLink to section

Use a UI component when you need a primitive.

Use a Pattern when you need a product behavior.

NeedUse
Button actionUI component
Form inputUI component
Form validation flowGuide
Data table with loading, empty, error, filtersPattern
Dropdown vs Dialog vs Sheet decisionPattern
Mutation feedback with toast, retry, undoPattern

Rule of thumb

Components render building blocks. Patterns explain how those blocks behave in a real product.

What to avoidLink to section

Prefer

  • small primitives
  • semantic tokens
  • composition-first APIs
  • clear accessibility defaults
  • patterns for complex flows

Avoid

  • hardcoded one-off styles
  • giant components with too many variants
  • business logic inside primitives
  • using badges as buttons
  • duplicating the same product flow repeatedly

Explore core componentsLink to section

Next stepsLink to section

Build the primitive once. Compose the product many times.

PyColors UI is designed to keep your components simple while your SaaS grows in complexity.