Integration
How to consume design tokens and shared components in any YotoShelf Astro + Svelte project.
The design system (tokens, Svelte components, and brand assets) lives in
this repository at packages/.
The YotoShelf frontend consumes these via a
git submodule
at frontend/design, which pins a commit of this repo.
Consuming as a submodule
The YotoShelf frontend already has this configured. For a new project:
# Add the submodule pointing at this repo
git submodule add https://gitlab.com/yotoshelf/yotoshelf.dev.git design
git submodule update --init
This creates a design/ directory. Your project then imports from design/packages/.
Importing design tokens
Install the font package this repo bundles, so nothing is fetched from a CDN:
npm install @fontsource-variable/nunito. IBM Plex Mono (code/mono) has no
bundled fallback — it renders from whatever the visitor's system provides, or the
--font-mono stack's next fallback.
In your project's global CSS file (e.g., src/styles/global.css):
/* Nunito Variable — bundled locally via @fontsource-variable/nunito (no CDN) */
@import '@fontsource-variable/nunito';
/* Import the Tailwind theme (which imports tokens.css internally) */
@import '../design/packages/tokens/tailwind-theme.css';
/* Import Tailwind */
@import 'tailwindcss';
The Tailwind theme file imports tokens.css automatically, giving you both CSS custom properties and Tailwind utility classes from a single import.
Using design tokens directly
All tokens are available as CSS custom properties:
.my-element {
color: var(--color-foreground);
font-family: var(--font-body);
padding: var(--spacing-4);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
transition: all var(--transition-base);
}
Using Tailwind utilities
The theme maps tokens to Tailwind classes:
<div class="bg-background text-foreground p-4 rounded-lg shadow-md">
<h2 class="font-display text-2xl font-semibold">Heading</h2>
<p class="font-body text-sm text-muted-foreground">Body text</p>
</div>
Importing shared Svelte components
<script>
import { Button, Card, Badge, Input, Dialog, Callout, Carousel }
from '../design/packages/components/index.js';
</script>
<Button variant="primary">Save Card</Button>
<Button variant="secondary">Cancel</Button>
<!-- Compact only where 52px genuinely breaks a dense layout -->
<Button variant="primary" size="compact">Add</Button>
<Card>
<h3>My Collection</h3>
<p>12 cards</p>
<p class="card-meta">12 tracks · 48:20 · updated 3d ago</p>
</Card>
<!-- Status badges — pill shaped -->
<Badge variant="default">New</Badge>
<Badge variant="success">Ready</Badge>
<Badge variant="warning">Draft</Badge>
<!-- Callout variants -->
<Callout variant="note" title="Tip">
Tap a card to preview before syncing.
</Callout>
<Callout variant="warning">
Refresh tokens are single-use.
</Callout>
<Callout variant="quirk">
Yoto cards are identified by NFC UID — duplicates share a slot.
</Callout>
Using the accent correctly
The accent ships as two tokens and they are not interchangeable.
--color-primary #E8654A is for shapes: button fills,
borders, focus rings. --color-primary-deep #B84A33 is for
text: inline links, active labels, anything a reader parses as a sentence.
Setting inline text in the raw accent on a light background computes 3.13:1 and fails
AA. The full contrast table is on the colors page.
Button sizes
The default button is 52px tall with 30px horizontal padding, a pill radius, and a
16px/22px label at weight 600. There is one alternative, size="compact"
at 38px, for dense application chrome — toolbars, table rows — where 52px
genuinely breaks the layout. Reach for it when the layout forces you to, not to add
variety; a third size is a drift, not a feature.
Card meta lines
Durations, hashes, counts, and timestamps inside a card use the .card-meta
class from global.css: IBM Plex Mono at 11px in
--card-meta-color. This is the only place a card uses the mono face.
Component props reference
| Component | Key Props |
|---|---|
| Button | variant (primary/secondary/destructive/ghost/outline), size (default/compact), disabled, href |
| Card | href (makes clickable), padding (boolean) |
| Badge | variant (default/success/warning/destructive/outline), pill shape |
| Input | label, placeholder, value (bindable), type, disabled, error |
| Dialog | open (bindable), title, slots: default + footer |
| Callout | variant (note/warning/quirk), title (optional); left rule, tinted background |
| Carousel | slides ({ src, alt, caption? }[]); picture-book plate layout, omit for placeholder state |
Updating the submodule pointer
# Pull latest from this repo's main branch
git submodule update --remote design
# Commit the pointer update
git add design
git commit -m "update: design system to latest"
Themes
The system is light-only today. There is no dark palette in
packages/tokens/tokens.css and no data-theme hook — adding
one means defining a full second set of colour tokens and re-deriving every contrast
ratio, so it is a deliberate piece of work rather than a flag to flip.
Project structure
your-project/
├── design/ ← git submodule → yotoshelf.dev
│ ├── packages/
│ │ ├── tokens/
│ │ │ ├── tokens.css ← CSS custom properties
│ │ │ └── tailwind-theme.css ← Tailwind v4 @theme
│ │ └── components/
│ │ ├── Button.svelte
│ │ ├── Card.svelte
│ │ ├── Badge.svelte
│ │ ├── Input.svelte
│ │ ├── Dialog.svelte
│ │ ├── Callout.svelte
│ │ ├── Carousel.svelte
│ │ └── index.js ← barrel export
│ └── public/
│ └── logo/ ← hero.svg, mark.svg
├── src/
│ └── styles/
│ └── global.css ← imports from design/packages/
└── ...