Guides
Migration notes, agent skills, and contributor workflows for @tollerud/ui.
Migration
Breaking changes ship with CHANGELOG entries. Recent majors to know about.
Replace require('@tollerud/ui') with ESM imports. CJS subpaths are removed.
Install Radix, Lucide, Framer Motion, and Sonner explicitly in consumer apps.
Projects that vendored src/components/ui/* should delete copies and import from the package. See AGENTS.md in the repo.
Tailwind remains available, but consumer apps should use exported components first and reserve utilities for small layout glue.
Consumer project checklist
/resources/consumer-checklist/Self-audit styling setup before shipping. Catches copied components, missing source.css, and invalid Button/Link composition.
# From your consumer app root
npx tollerud-ui-audit
# Monorepo app package
npx tollerud-ui-audit ./apps/web
# Without npx (direct script path)
node node_modules/@tollerud/ui/scripts/audit-consumer-styling.mjs
# Advisory CI — print findings but exit 0 even with errors
npx tollerud-ui-audit --warn-onlyWhat the audit checks
Missing @tollerud/ui in package.json, missing globals.css or source.css imports, local components/ui clones, tollerud-* classes without package imports, hardcoded brand hex values, local cn() helpers, nested Button/Link patterns, and components/ui re-export shims.
Exit codes
Exit 0 when no issues are found, or when --warn-only is set. Exit 1 when errors are found — use in required CI checks.
Audit error codes
Findings print as ERROR [code] or WARN [code]:
| Code | Level | Fix |
|---|---|---|
| missing-ui-dep | error | Add @tollerud/ui and peers to package.json |
| missing-globals-css | error | Import @tollerud/ui/globals.css in Tailwind entry |
| missing-source-css | error | Import @tollerud/ui/source.css (prevents production purge) |
| local-ui-clone | error | Delete components/ui copies; import from @tollerud/ui |
| copied-ds-tokens | error | Replace vendored files using tollerud-* without package imports |
| hardcoded-hex | error | Use text-tollerud-yellow, bg-tollerud-noir-950 tokens |
| button-link-nesting | error | Button asChild + Link, or buttonVariants() on the link |
| ui-reexport-shim | warn | Import from @tollerud/ui instead of local ui/index re-exports |
| local-cn | warn | import { cn } from "@tollerud/ui/utils" |
| generic-yellow-util | warn | Prefer Button variant="primary" or text-tollerud-yellow |
| no-globals-css | warn | Verify Tailwind entry imports both Tollerud CSS files |
| no-package-json | warn | Run audit from the consumer app package root |
// src/features/hosts/HostDeployPanel.tsx — app-specific; composes @tollerud/ui
import { Button, FormPanel, Input, Stack } from '@tollerud/ui'
export function HostDeployPanel({ onDeploy }: { onDeploy: (host: string) => void }) {
return (
<FormPanel
title="Connect host"
footer={<Button variant="primary" onClick={() => onDeploy('emma.tollerud.no')}>Connect</Button>}
>
<Stack gap="md">
<Input label="Hostname" placeholder="emma.tollerud.no" />
</Stack>
</FormPanel>
)
}AI agents
Sync SKILL.md into your project so coding assistants use verified exports and gotchas.
# Claude Code / Cursor — copy verbatim on version bumps
mkdir -p .claude/skills/tollerud-ui
curl -fsSL https://raw.githubusercontent.com/Tollerud/ui/main/SKILL.md \
-o .claude/skills/tollerud-ui/SKILL.md
# Current package version: v4.6.13SKILL.md reflects actual components/index.ts exports — more reliable than stale copy-paste snippets.
Contributing
Validate before opening a PR. Component changes need registry + docs demo updates.
npm run validate # typecheck, lint, test, build, package gates, docs build
# Component checklist (see AGENTS.md):
# components/*.tsx → index.ts → registry.json → docs page demoProp reference
Full generated prop tables live in the repo; key components show props inline on docs pages.
Regenerate after interface changes: npm run docs:props · drift check: npm run test:props