@johnfilipstad/groundwork-tokens
v2.0.0
Published
Design tokens (CSS custom properties) — single source of truth for Groundwork vNext.
Maintainers
Readme
Groundwork Tokens 🏗️
The foundation of every great design system.
Groundwork Tokens is the Single Source of Truth (SSOT) for the entire Groundwork vNext ecosystem. Every layer—from base styling to complex components—builds upon these carefully crafted design tokens to create cohesive, accessible, and beautiful web experiences.
⚡ Why Groundwork Tokens?
🎯 Single Source of Truth — One place to define colors, typography, spacing, and more. 🎨 Instant Theming — Change 3 brand colors, get 362 coordinated CSS variables. 🌍 Universal Foundation — Powers every layer of the Groundwork ecosystem. 🔄 Effortless Updates — Update once, cascade everywhere. 🌙 Built-in Dark Mode — Automatic light/dark theming with zero configuration. 🌐 RTL/LTR Ready — Logical properties and directional awareness. ♿ Accessibility First — WCAG AA contrast ratios and reduced motion support.
🚀 Quick Start
Installation
npm i @johnfilipstad/groundwork-tokensBasic Usage
The groundwork must be laid first. Always import tokens before any other Groundwork layers:
<!-- Tokens MUST come first -->
<link rel="stylesheet" href="/node_modules/@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.css">
<!-- Then other layers (optional) -->
<link rel="stylesheet" href="node_modules/@johnfilipstad/groundwork-harmony/dist/groundwork-harmony.css">
<link rel="stylesheet" href="node_modules/@johnfilipstad/groundwork-flow/dist/groundwork-flow.css">CDN Usage
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.css">📦 Multiple Formats
Groundwork Tokens provides design tokens in multiple formats to fit any workflow:
| Format | Base Tokens | With Themes | Use Case |
|--------|-------------|-------------|----------|
| CSS | ✅ groundwork-tokens.css | ✅ Built-in themes | Web projects, universal compatibility |
| SCSS | ✅ groundwork-tokens.scss | ✅ groundwork-tokens-themes.scss | Sass/SCSS workflows, theme mixins |
| JavaScript | ✅ groundwork-tokens.js | ✅ groundwork-tokens-themes.js | React/Vue, programmatic theming |
| TypeScript | ✅ groundwork-tokens.d.ts | ⚠️ Base types only | Type definitions |
| JSON | ✅ groundwork-tokens.json | ✅ groundwork-tokens-themes.json | Design tools, documentation |
🌙 Theme Support: All theme-aware formats include automatic dark/light mode switching via prefers-color-scheme and manual data-theme attributes.
CSS Custom Properties (Default)
Perfect for modern web development with native CSS variables:
<link rel="stylesheet" href="/node_modules/@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.css">.my-component {
background: var(--color-primary);
color: var(--color-text);
padding: var(--spacing-m);
font-size: var(--font-size-l);
}SCSS Variables
For Sass/SCSS workflows:
// Base variables only
@import '~@johnfilipstad/groundwork-tokens/scss';
.my-component {
background: $color-primary;
color: $color-text;
padding: $spacing-m;
font-size: $font-size-l;
}Or with automatic dark/light theme support:
// Includes theme mixins and media queries
@import '~@johnfilipstad/groundwork-tokens/dist/groundwork-tokens-themes.scss';
// Now automatically supports dark mode via:
// - @media (prefers-color-scheme: dark)
// - :root[data-theme="dark"]
// - Manual @include dark-theme mixinJavaScript/TypeScript
For component libraries and programmatic access:
// Base tokens only
import { ColorPrimary, FontSizeL, SpacingM } from '@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.js';
console.log(ColorPrimary); // "var(--color-primary-600)"
console.log(FontSizeL); // "clamp(1.9rem, 1rem + 2vw, var(--font-size-l-target))"
// CommonJS
const { ColorPrimary } = require('@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.cjs');Or with theme support and utilities:
// Includes theme objects and utilities
import { ColorPrimary, themes, applyTheme } from '@johnfilipstad/groundwork-tokens/dist/groundwork-tokens-themes.js';
// Theme objects
console.log(themes.dark.colorBody); // "hsl(0deg 0% 8%)"
console.log(themes.light.colorBody); // "hsl(0deg 0% 98%)"
// Programmatic theme switching
applyTheme('dark'); // Applies dark theme to document
applyTheme('light'); // Applies light theme to document
### JSON Design Tokens
For design tools and token management:
```javascript
// Base tokens only - flat format
import tokens from '@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.tokens.json';
console.log(tokens.ColorPrimary); // "var(--color-primary-600)"
// Base tokens only - nested format
import tokens from '@johnfilipstad/groundwork-tokens/dist/groundwork-tokens.json';
console.log(tokens["color-primary"]); // "var(--color-primary-600)"Or with complete theme data:
// Includes base tokens + theme objects
import tokenData from '@johnfilipstad/groundwork-tokens/dist/groundwork-tokens-themes.json';
console.log(tokenData.base); // All base design tokens
console.log(tokenData.themes.dark); // Dark theme overrides
console.log(tokenData.themes.light); // Light theme overridesFramework Integration Examples
React/Vue Components
import { tokens } from '@johnfilipstad/groundwork-tokens';
const Button = () => (
<button style={{
backgroundColor: tokens.color.primary.brand,
padding: tokens.spacing.m,
fontSize: tokens.font.size.m
}}>
Click me
</button>
);Styled Components
import styled from 'styled-components';
import { tokens } from '@johnfilipstad/groundwork-tokens';
const Button = styled.button`
background: ${tokens.color.primary.brand};
color: ${tokens.color.text};
padding: ${tokens.spacing.m};
font-size: ${tokens.font.size.m};
`;🏗️ Architecture Power
Groundwork Tokens creates a flexible foundation where each layer can work independently:
Mix and Match
<!-- Want just variables? -->
<link rel="stylesheet" href="groundwork-tokens.css">
<!-- Beautiful semantic HTML? -->
<link rel="stylesheet" href="groundwork-tokens.css">
<link rel="stylesheet" href="groundwork-harmony.css">
<!-- Flexible layouts? -->
<link rel="stylesheet" href="groundwork-tokens.css">
<link rel="stylesheet" href="groundwork-flow.css">
<!-- Complete foundation? -->
<link rel="stylesheet" href="groundwork-tokens.css">
<link rel="stylesheet" href="groundwork-harmony.css">
<link rel="stylesheet" href="groundwork-flow.css">🎨 What's Inside
Mathematical Typography
- Responsive font scales using modular ratios
- Perfect fourth (1.333) creates natural hierarchy
- Fluid sizing with
clamp()for all devices
Semantic Color System
- Auto-generating palettes from brand colors
- Built-in light/dark mode switching
- WCAG AA compliant contrast ratios
Consistent Spacing
- 4px baseline grid for visual rhythm
- Exponential scale for clear hierarchy
- Logical properties for RTL/LTR support
Elevation System
- Theme-aware shadows and depth
- Consistent elevation hierarchy
- Dynamic color integration
🌙 Theme Switching
Automatic (OS Preference)
Tokens automatically respect your user's system preference:
/* Automatically switches based on prefers-color-scheme */
:root {
--color-text: var(--color-text-on-light); /* Light mode */
}
@media (prefers-color-scheme: dark) {
:root {
--color-text: var(--color-text-on-dark); /* Dark mode */
}
}Manual Override
Let users choose their preference:
<!-- Light mode -->
<html data-theme="light">
<!-- Dark mode -->
<html data-theme="dark">
<!-- Auto (remove attribute) -->
<html>Add Theme Toggle (Optional)
Want to add dark mode? Just paste this script before the closing </body> tag:
<script>
// Theme toggle script from the Dark Mode section above
window.addEventListener("DOMContentLoaded", () => {
// ... (see full script from Dark Mode section below)
});
</script>Explore Further
Visit groundwork.filipstad.dev for comprehensive documentation, live demos, and advanced examples (coming soon).
🌓 Dark Mode
Groundwork Tokens supports [data-theme="dark" | "light"] on <html> and respects the user's OS setting via prefers-color-scheme.
If you don't set an attribute, Groundwork Tokens will match the OS preference automatically. To provide a user toggle, use this simple approach:
Copy and paste this complete theme toggle script:
<script>
window.addEventListener("DOMContentLoaded", () => {
const styles = `
.theme-toggle {
position: fixed;
top: var(--spacing-s);
right: var(--spacing-s);
padding: var(--spacing-s);
z-index: var(--z-index-toast);
}
`;
const styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
const themeToggleButton = document.createElement("button");
themeToggleButton.className = "theme-toggle";
document.body.appendChild(themeToggleButton);
const html = document.documentElement;
function toggleTheme() {
let currentTheme = html.getAttribute("data-theme");
if (!currentTheme) {
currentTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
const newTheme = currentTheme === "dark" ? "light" : "dark";
html.setAttribute("data-theme", newTheme);
localStorage.setItem("theme", newTheme);
updateButtonText(newTheme);
}
function updateButtonText(theme) {
themeToggleButton.textContent = theme === "dark" ? "☀️" : "🌙";
}
themeToggleButton.addEventListener("click", toggleTheme);
// Load saved theme or respect OS preference
const savedTheme = localStorage.getItem("theme");
if (savedTheme) {
html.setAttribute("data-theme", savedTheme);
updateButtonText(savedTheme);
} else {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
updateButtonText(prefersDark ? 'dark' : 'light');
}
});
</script>That's it! This script creates the button, adds the CSS using design tokens, and handles OS preferences intelligently.
Notes:
- Uses Groundwork's design tokens (
--spacing-s,--z-index-toast) for consistent styling - Respects user's OS preference until they manually toggle
- Saves preference in localStorage for returning users
💡 Usage Examples
Custom Properties in CSS
.my-component {
background-color: var(--color-surface);
color: var(--color-text);
padding: var(--spacing-m);
border-radius: var(--border-radius-s);
font-size: var(--font-size-l);
}Brand Customization
Override the foundation to match your brand:
:root {
/* Change these 3 variables... */
--color-primary-brand: #your-primary;
--color-secondary-brand: #your-secondary;
--color-accent-brand: #your-accent;
/* ...and get 200+ coordinated variables automatically */
}📚 Documentation
Complete documentation, examples, and interactive demos: groundwork.filipstad.dev
- 🎨 Color system deep dive
- 📏 Typography scale calculator
- 🎛️ Interactive token browser
- 🌙 Theme switching examples
- ♿ Accessibility guidelines
🏗️ Ecosystem
Groundwork Tokens powers the entire Groundwork vNext family:
| Package | Purpose | Dependencies | |---------|---------|-------------| | @groundwork/tokens | Design token foundation | None | | @groundwork/harmony | Semantic HTML styling | tokens | | @groundwork/flow | Layout primitives | tokens | | @groundwork/atoms | Utility classes | tokens | | @groundwork/components | UI components | tokens + others |
🤝 Contributing
We welcome contributions! Please see our Contributing Guidelines for details.
Development Setup
git clone https://github.com/JohnFilipstad/groundwork-tokens.git
cd groundwork-tokens
npm install
npm run dev📄 License
MIT © John Filipstad
🔗 Links
- Documentation: groundwork.filipstad.dev
- GitHub: github.com/JohnFilipstad/groundwork-tokens
- NPM: @groundwork/tokens
- Issues: Report bugs or request features
The groundwork has been laid. Build something amazing. 🏗️
