@fudge-me/design-system
v0.3.0
Published
Visual language and UI primitives for the fudge ecosystem
Readme
fudge-design-system
Visual language and UI primitives for the fudge ecosystem. Product-agnostic — no application logic, no backend assumptions, no domain semantics.
Status: v0.2.0 — icons, motion, forms, chat, and data display shipped. v0.3 "Foundations for Beauty" in planning.
Consumers
- fudge-client (Tauri v2 + Svelte 5, desktop)
- Future web clients
- Future mobile clients
Stack
Svelte 5 component library. Product repos depend on this; never the reverse.
Shell Model
The target UI is canvas-first:
| Slot | Position | |---|---| | Command bar | Top | | Sidebar | Left | | Canvas | Center | | AI panel | Right | | Status bar | Bottom |
Layout primitives in this repo map directly to these slots.
What It Provides
- Tokens — three-tier system (raw → semantic → component), exported as
--fds-*CSS custom properties. Color, spacing, typography, radii, shadows, motion (durations + easings) - Themes — light/dark switching via ThemeProvider, CSS-only via
[data-theme] - Layout primitives — AppShell, CommandBar, Sidebar, Canvas, AIPanel, StatusBar, Panel
- Core components — Button, Input, Tooltip, Modal, Command Palette
- Form primitives — FormField, TextArea, Input with validation states and password toggle
- Chat primitives — Avatar, Message, Composer (all product-agnostic)
- Data display — ProgressBar, FilePreview, Card, EmptyState
- Loading states — Skeleton, Spinner (both honor
prefers-reduced-motion) - Icons — 36 tree-shakeable SVG icons across 5 categories (navigation, actions, status, file types, UI)
- Transitions — fade, slide, scale, collapse (token-driven,
prefers-reduced-motionaware)
See ROADMAP.md for v0.3 "Foundations for Beauty" (OKLCH color, elevation system, typography foundation, motion scalar, theme API, contrast/density axes) and beyond.
What It Excludes
- Product logic
- API calls or backend assumptions
- Workspace, comms, or any domain semantics
Local Development
Run pnpm run package:watch in this repo while developing with fudge-client. See docs/ai/local-dev-fast-path.md for the full workflow and failure modes.
Consumer Import Pattern
Root layout in fudge-client:
<!-- 1. Tokens — import once at app root, establishes all --fds-* custom properties -->
<script>
import '@fudge-me/design-system/tokens';
// 2. Theme CSS — both files needed so switching works
import '@fudge-me/design-system/themes/light.css';
import '@fudge-me/design-system/themes/dark.css';
// 3. Components — ThemeProvider, layout, UI primitives
import { ThemeProvider } from '@fudge-me/design-system/themes';
import { AppShell, Sidebar, Canvas, AIPanel, CommandBar, StatusBar } from '@fudge-me/design-system/layout';
import { Button, Icon } from '@fudge-me/design-system/components';
import { iconSend, iconSearch } from '@fudge-me/design-system/icons';
import { fade, slide } from '@fudge-me/design-system/transitions';
</script>
<!-- 4. ThemeProvider sets data-theme on root; consumer handles persistence -->
<ThemeProvider theme="system">
<AppShell>
{#snippet commandbar()}<CommandBar>...</CommandBar>{/snippet}
{#snippet sidebar()}<Sidebar>...</Sidebar>{/snippet}
{#snippet canvas()}<Canvas>...</Canvas>{/snippet}
{#snippet aipanel()}<AIPanel>...</AIPanel>{/snippet}
{#snippet statusbar()}<StatusBar>...</StatusBar>{/snippet}
</AppShell>
</ThemeProvider>Per-layer examples
Token cherry-pick (individual CSS file):
<script>
import '@fudge-me/design-system/tokens/color.css';
</script>Component import:
<script>
import { Button } from '@fudge-me/design-system/components';
import { Modal } from '@fudge-me/design-system/components';
</script>
<Button variant="primary" size="md" onclick={save}>Save</Button>
<Modal open={showDialog} onclose={() => showDialog = false}>
<p>Content here</p>
</Modal>Theme usage:
<script>
import { ThemeProvider } from '@fudge-me/design-system/themes';
</script>
<!-- "system" follows prefers-color-scheme; "light"/"dark" force a theme -->
<ThemeProvider theme="system">
<slot />
</ThemeProvider>Fonts
The DS does not bundle WOFF2 files. It ships:
- Font tokens in
tokens/typography.css—--fds-font-ui(Inter),--fds-font-display(Inter Display),--fds-font-mono(Geist Mono). Each prepends the named font onto the existing system fallback, so they are safe to use whether or not the actual font is loaded. - Optional
./fontssubpath —@import "@fudge-me/design-system/fonts";attaches@font-facedeclarations pointing at the canonical CDN URLs (rsms.mefor Inter,assets.vercel.comfor Geist Mono). Importing this is opt-in; the system stack continues to work without it.
For zero-network production (e.g., Tauri desktop builds): vendor the WOFF2 files locally and override the @font-face blocks with local paths. The font-family names ("Inter", "Inter Display", "Geist Mono") must remain stable so the raw tokens continue to resolve.
Consumers always own the actual bundling decision. The DS contract is the tokens + the optional subpath, not the font files.
Consumer Responsibilities
- Import tokens once at the app root
- Import both theme CSS files so switching works
- Wrap app in
ThemeProvider— consumer handles persistence - Do not override component tokens with raw tokens
- Use subpath exports only — do not import internal DS paths
- Use layered entrypoints when CSS is needed (root re-export excludes tokens)
- Component token overrides use direct child combinators (
>) to prevent leaking - Load order matters: tokens → theme → app → component styles. See
docs/ai/css-load-order.mdfor the four-stage contract, what breaks if reordered, and the canonical consumer recipe.
Docs
| File | Purpose |
|---|---|
| docs/ai/contracts.md | Repo boundaries and responsibilities |
| docs/ai/prd.json | Task definitions |
| docs/ai/decisions.md | Architectural decisions |
| ARCHITECTURE.md | Technical architecture and design decisions |
| ROADMAP.md | Versioned delivery plan |
| docs/ai/css-load-order.md | Four-stage CSS load-order contract (tokens → theme → app → component) |
| docs/ai/css-variable-scoping.md | CSS selector-tier scoping rules and per-zone token table |
| docs/ai/component-theming-boundaries.md | Component theming contract with allowed/forbidden patterns |
| docs/ai/local-dev-fast-path.md | Dev workflow: package:watch, Vite config, failure modes |
| Ecosystem contract | Cross-repo consumption contract and public API surface |
