Get Started

Contributing

View as markdown

How to work on @oscarkalid/ui.

Getting set up

Terminal

git clone https://github.com/yajesta/ui
cd ui
pnpm install
pnpm dev

Scripts

pnpm dev # workbench on http://localhost:3200
pnpm build # production build, writes to .next-build
pnpm typecheck # types across the workspace
pnpm lint

Where things live

Workspace

packages/
ui/ the library: tokens, components, hooks, styles
workbench/ the site: docs plus full application demos
db/ demo data the workbench renders against

The two that matter most

Nothing defines its own values

Colours, spacing, radii and transitions all come from packages/ui. A hex code, a px value or a transition: declaration in the workbench belongs in the design system as a token.

TypeScript

// No.
<div className="bg-[#101113] p-[14px] transition-[200ms]" />
// Yes. Every value is a token, so re-theming is one edit in one file.
<div className="bg-surface p-3 transition-colors" />

Write each CSS property exactly once per element

Never set a base value in the class list and then override it conditionally.

TypeScript

// Broken. Tailwind resolves same-property conflicts by the order it emits
// rules, not the order they appear in the string. .bg-transparent is emitted
// after .bg-accent-soft, so the base wins and the selected state never shows.
cn("bg-transparent", selected && "bg-accent-soft")
// Correct. The property is written once, in branches.
cn(selected ? "bg-accent-soft" : "bg-transparent")

It never throws. The base value wins and the conditional one never appears.

Design system rules

  • Token layers. Primitives (--blue-500) are the raw palette. Components never reference them. Semantic tokens (--surface-raised, --accent) name a role and are the only thing components use.
  • Themes are data. A theme is a set of semantic token values on [data-theme]. Adding one must not require touching a component.
  • Transitions are tokens too. No component writes 300ms ease-in-out.
  • Import from the package root, never from @oscarkalid/ui/src/....
  • WCAG 2.2 AA. A component with a broken focus ring is not finished.
  • A component ships with its page. A new component needs a page in the workbench, with the source visible.

House style

No em dashes anywhere: UI copy, code, comments, docs, commit messages, PR bodies. Use commas, colons or parentheses.

Comments explain the reasoning behind the code.

Before you open the PR

Terminal

pnpm typecheck
pnpm lint
pnpm build

Last updated: 12 August 2026