Motif

Motif Design Library

Built @motif/design as a standalone design library with CSS tokens, Svelte 5 atoms, and Storybook catalogue. Migrated motivka to consume it as its single source of truth.

5 Phases
26 Tasks
6 Bugs Fixed
5 Days

The Problem

Every new externally-facing project required the same design tokens, component atoms, and aesthetic decisions to be re-implemented from scratch or manually copied from motivka. This caused drift between projects over time and meant design changes had to be applied in multiple places. There was no single source of truth that agents and developers could reference when building new interfaces.

I noticed this most acutely when thinking about the encyclopedia-brown and vibration projects. Both would need the same colour palette, typography scale, and basic components. Copying from motivka would create three diverging copies within months.

What I Built

Motif is a standalone design library at ~/Code/motif, published as @motif/design. It extracts the canonical design tokens and atomic components from motivka into a reusable package that any SvelteKit project can install.

Phase 0: Repository foundation. I initialised the repo with Bun, configured Vite in library mode with vite-plugin-dts for TypeScript declarations, set up Tailwind CSS 4 as a utility layer (tokens handle colours and spacing, not Tailwind), and configured Storybook 10 with Svelte CSF. The package.json exports three CSS entry points and two component entry points.

Phase 1: CSS tokens. I extracted all CSS custom properties from motivka's app.css into three separate files. public.css contains the full OKLCH colour palette, typography, spacing, shadows, animations, gradients, and grid pattern tokens. admin.css contains all --admin-* tokens pinned to dark palette values. base.css contains global styles like the typography scale, body defaults, scrollbar styling, focus states, and utility classes. All colour tokens use OKLCH format for perceptual uniformity, with intentional exceptions for --*-rgb tuple tokens and --hex-* SVG tokens.

Phase 2: Svelte 5 atoms. I ported 12 components from motivka: Button, Input, Select, Textarea, Label, Toggle, TagPill, Tooltip, Portrait (public atoms) and StatusBadge, BulkActionModal, DeleteConfirmModal (admin atoms). Each component follows the four-block structure (module script, instance script, markup, style) with Svelte 5 runes only. I created a shared form-states.css with a .motif-form-control class for consistent focus ring and validation styling across all form atoms. Variable fonts replaced 13 individual weight file imports, reducing font imports from 13 to 7.

Phase 3: Storybook catalogue. I ported all token visualisation stories (Colours, Typography, Spacing, Shadows) and wrote component stories for every public and admin atom. The Storybook catalogue serves as both visual documentation and a proof that the components render correctly outside of motivka.

Phase 4: Motivka migration. This was the most delicate phase. I replaced motivka's inline token definitions in app.css with three imports from @motif/design (public, admin, base), maintaining a documented import order dependency. I replaced all direct atom imports throughout the codebase with imports from @motif/design, keeping a deprecated compatibility shim at $lib/ui/atoms/index.ts. The admin design system gallery was updated to show import paths from @motif/design rather than local file paths.

Phase 5: Global design-system skill. I created a comprehensive global Claude skill at ~/.claude/skills/design-system/ covering the full design language: brand identity, layout philosophy, widget and component patterns, and multi-medium guidance. The skill reads ~/Code/motif/src/ directly for Svelte-specific token and component details, ensuring it never goes stale. Motivka's old project-level design-system skill was deleted entirely.

Key Decisions

  • Standalone repo -- not co-located inside motivka. Enables any project outside the monorepo to reference and install it.
  • Motivka becomes a consumer -- eliminates the duplicated source of truth. Motivka is the first proof-of-concept and validates the library API.
  • Atoms only, no composites -- section-level and form composites are too motivka-specific to generalise safely.
  • CSS custom properties, not JS objects -- framework-agnostic, readable directly by agents, works in any consumer.
  • Three CSS entry points -- prevents admin tokens polluting public pages and vice versa.
  • Local path for dev, git URL for CI -- avoids npm registry overhead. github:knedliky/motif with bun.lock commit hash for reproducibility.
  • Alfons is Motif -- the planned alfons/ project was always the same concept under a different name. No separate Alfons project will be built.
  • Global skill reads source directly -- static token summaries go stale. Reading ~/Code/motif/src/ is always accurate.

What is Next

The motif dependency strategy has been resolved: github:knedliky/motif in package.json with bun link for local dev hot reload. The Docker integration tasks (dev volume mount and production build) are queued. The design system cleanup phase was the immediate follow-up to fix inconsistencies surfaced during the motif migration.

Features Delivered

Phase 0: Repository Foundation

  • Initialised repo with Bun, Vite library mode, vite-plugin-dts
  • Configured Tailwind CSS 4 as utility layer
  • Configured Storybook 10 with Svelte CSF
  • Set up package.json exports for 3 CSS and 2 component entry points

Phase 1: CSS Tokens

  • Extracted public.css with full OKLCH colour palette, typography, spacing, shadows, animations, gradients
  • Extracted admin.css with all --admin-* tokens pinned to dark palette
  • Extracted base.css with typography scale, body defaults, scrollbar, focus states, utilities
  • All colour tokens in OKLCH format for perceptual uniformity

Phase 2: Svelte 5 Atoms

  • Ported 9 public atoms: Button, Input, Select, Textarea, Label, Toggle, TagPill, Tooltip, Portrait
  • Ported 3 admin atoms: StatusBadge, BulkActionModal, DeleteConfirmModal
  • Created shared form-states.css with .motif-form-control class
  • Variable fonts reduced imports from 13 to 7

Phase 3: Storybook Catalogue

  • Ported token visualisation stories: Colours, Typography, Spacing, Shadows
  • Wrote component stories for every public and admin atom
  • Configured Storybook extras and verified all stories render

Phase 4: Motivka Migration

  • Replaced motivka app.css inline tokens with 3 @motif/design imports
  • Replaced all atom imports with @motif/design throughout codebase
  • Created deprecated compatibility shim at $lib/ui/atoms/index.ts
  • Updated admin design system gallery to show @motif/design import paths

Phase 5: Global Design-System Skill

  • Created comprehensive global Claude skill at ~/.claude/skills/design-system/
  • Covers brand identity, layout philosophy, widget patterns, multi-medium guidance
  • Skill reads ~/Code/motif/src/ directly for live token and component details
  • Deleted motivka project-level design-system skill

Bugs Fixed

  • BUG-001
  • BUG-002
  • BUG-003
  • BUG-004
  • BUG-005
  • BUG-006

Key Decisions

  • D-001:
  • D-002:
  • D-003:
  • D-004:
  • D-005:
  • D-006:
  • D-009:
  • D-010:
  • D-011:
  • D-013: