npm package: @statsbygg/design-tokens
Description: > Statsbygg's design tokens compiled from DigDir Designsystemet. Provides a consistent visual language across all Statsbygg applications.
Latest version: 0.4.3

# @statsbygg/design-tokens

> Statsbygg's design tokens compiled from DigDir Designsystemet. Provides a consistent visual language across all Statsbygg applications.

## Overview

Design tokens are the visual design atoms of your design system — specifically, they are named entities that store visual design attributes. This package provides all color, typography, spacing, and other design primitives as CSS custom properties.

**What are Design Tokens?**

Instead of hard-coding values like `color: #1E3A8A` or `font-size: 16px`, you use semantic tokens:

```css
color: var(--ds-color-accent-text-default);
font-size: var(--ds-font-size-3);
```

Benefits:
- **Consistency**: All components use the same visual language
- **Theming**: Light/dark mode support built-in
- **Maintainability**: Update the entire app by changing token values

## Installation

```bash
npm install @statsbygg/design-tokens
```

This package is automatically included in projects created with `@statsbygg/create-app`.

## Usage

### Import in Your Application

Add the following to your global CSS file (e.g., `/src/app/globals.css` in Next.js):

```css
@import '@statsbygg/design-tokens';
```

Or in a TypeScript/JavaScript file:

```typescript
import '@statsbygg/design-tokens';
```

### Using Design Tokens in CSS

Once imported, all tokens are available as CSS custom properties:

```css
.my-button {
  /* Colors */
  background-color: var(--ds-color-accent-background-default);
  color: var(--ds-color-accent-text-default);
  
  /* Spacing */
  padding: var(--ds-size-4) var(--ds-size-6);
  margin-bottom: var(--ds-size-3);
  
  /* Typography */
  font-family: var(--ds-font-family);
  font-size: var(--ds-font-size-3);
  font-weight: var(--ds-font-weight-medium);
  
  /* Borders & Shadows */
  border-radius: var(--ds-border-radius-md);
  box-shadow: var(--ds-shadow-small);
  
  /* Transitions */
  transition: all 0.2s ease;
}

.my-button:hover {
  background-color: var(--ds-color-accent-background-hover);
}
```

### Using in CSS Modules

```css
/* Button.module.css */
.button {
  background: var(--ds-color-brand-first-background-default);
  color: var(--ds-color-brand-first-text-default);
  padding: var(--ds-size-3) var(--ds-size-5);
  border-radius: var(--ds-border-radius-md);
  font-size: var(--ds-font-size-3);
}
```

## Token Structure

The design token system is organized hierarchically:

1. **Primitives**: Base values (e.g., `blue-500`, `spacing-4`)
2. **Semantic Tokens**: Contextual meaning (e.g., `accent-background-default`)
3. **Component Tokens**: Component-specific overrides (if needed)

### Token Categories

#### 🎨 Colors

##### Semantic Color Tokens

```css
/* Text Colors */
var(--ds-color-neutral-text-default)      /* Primary text */
var(--ds-color-neutral-text-subtle)       /* Secondary/muted text */
var(--ds-color-accent-text-default)       /* Accent text (links, highlights) */
var(--ds-color-brand-first-text-default)  /* Brand primary */
var(--ds-color-brand-second-text-default) /* Brand secondary */

/* Background Colors */
var(--ds-color-neutral-background-default)  /* Page background */
var(--ds-color-neutral-background-subtle)   /* Card/panel background */
var(--ds-color-accent-background-default)   /* Accent elements */
var(--ds-color-accent-background-hover)     /* Hover states */

/* Feedback Colors */
var(--ds-color-feedback-success)  /* Green for success */
var(--ds-color-feedback-warning)  /* Yellow for warnings */
var(--ds-color-feedback-error)    /* Red for errors */
var(--ds-color-feedback-info)     /* Blue for informational */

/* Border Colors */
var(--ds-color-border-default)
var(--ds-color-border-subtle)
```

#### 📏 Spacing

The spacing scale uses a 4px base unit:

```css
var(--ds-size-1)   /* 4px */
var(--ds-size-2)   /* 8px */
var(--ds-size-3)   /* 12px */
var(--ds-size-4)   /* 16px */
var(--ds-size-5)   /* 20px */
var(--ds-size-6)   /* 24px */
var(--ds-size-8)   /* 32px */
var(--ds-size-10)  /* 40px */
var(--ds-size-12)  /* 48px */
```

**Usage Example:**

```css
.card {
  padding: var(--ds-size-6);          /* 24px */
  margin-bottom: var(--ds-size-4);    /* 16px */
  gap: var(--ds-size-3);              /* 12px in flex/grid */
}
```

#### ✍️ Typography

##### Font Families

```css
var(--ds-font-family)  /* Primary font stack */
```

##### Font Sizes

```css
var(--ds-font-size-1)  /* 12px - Small labels */
var(--ds-font-size-2)  /* 14px - Default body text */
var(--ds-font-size-3)  /* 16px - Large body text */
var(--ds-font-size-4)  /* 18px - Small headings */
var(--ds-font-size-5)  /* 20px - Medium headings */
var(--ds-font-size-6)  /* 24px - Large headings */
var(--ds-font-size-7)  /* 30px - Extra large headings */
```

##### Font Weights

```css
var(--ds-font-weight-regular)   /* 400 */
var(--ds-font-weight-medium)    /* 500 */
var(--ds-font-weight-semibold)  /* 600 */
var(--ds-font-weight-bold)      /* 700 */
```

**Typography Example:**

```css
.heading {
  font-family: var(--ds-font-family);
  font-size: var(--ds-font-size-6);
  font-weight: var(--ds-font-weight-bold);
  line-height: 1.2;
}

.body-text {
  font-size: var(--ds-font-size-2);
  font-weight: var(--ds-font-weight-regular);
  line-height: 1.5;
}
```

#### 🔲 Borders & Radius

```css
/* Border Radius */
var(--ds-border-radius-sm)   /* Small (4px) */
var(--ds-border-radius-md)   /* Medium (8px) */
var(--ds-border-radius-lg)   /* Large (12px) */
var(--ds-border-radius-full) /* Fully rounded (9999px) */

/* Example */
.button {
  border-radius: var(--ds-border-radius-md);
}

.avatar {
  border-radius: var(--ds-border-radius-full);
}
```

#### 🌗 Shadows

```css
var(--ds-shadow-small)   /* Subtle elevation */
var(--ds-shadow-medium)  /* Card elevation */
var(--ds-shadow-large)   /* Modal/dialog elevation */

/* Example */
.card {
  box-shadow: var(--ds-shadow-medium);
}
```

## Theming (Light/Dark Mode)

The design token system automatically adapts to light and dark modes using CSS custom properties.

### Automatic Detection

The system uses `prefers-color-scheme` media query to detect the user's OS preference:

```css
/* Tokens automatically adjust */
@media (prefers-color-scheme: dark) {
  :root {
    --ds-color-neutral-background-default: #1a1a1a;
    --ds-color-neutral-text-default: #ffffff;
    /* ... other dark mode overrides */
  }
}
```


### Manual Theme Switching

You can override the OS preference using the `data-color-scheme` attribute:

```html
<html data-color-scheme="light">
  <!-- Forces light mode -->
</html>

<html data-color-scheme="dark">
  <!-- Forces dark mode -->
</html>
```

**Implementing a Theme Toggle:**

```typescript
// ThemeToggle.tsx
'use client';

export function ThemeToggle() {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');
  
  useEffect(() => {
    document.documentElement.setAttribute('data-color-scheme', theme);
  }, [theme]);
  
  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Toggle Theme
    </button>
  );
}
```

## Typography Themes

Designsystemet supports two font theme variations:

1. **Primary Theme** (default): Uses the standard Designsystemet font stack
2. **Secondary Theme**: Uses an alternative font stack for specific branding

### Applying Typography Themes

```css
/* Use primary theme (default) */
body {
  font-family: var(--ds-font-family);
}

/* Use secondary theme for specific sections */
.branded-section {
  font-family: var(--ds-font-family-secondary);
}
```

## Advanced Usage

### Creating Custom Semantic Tokens

You can extend the token system with your own semantic tokens:

```css
:root {
  /* Custom semantic tokens built on primitives */
  --app-sidebar-width: 240px;
  --app-header-height: 64px;
  
  /* Use design tokens as base values */
  --app-card-background: var(--ds-color-neutral-background-subtle);
  --app-card-padding: var(--ds-size-6);
  --app-card-border-radius: var(--ds-border-radius-lg);
}
```

### Component-Scoped Tokens

For complex components, you can create local token overrides:

```css
.special-button {
  /* Define local tokens */
  --button-bg: var(--ds-color-accent-background-default);
  --button-text: var(--ds-color-accent-text-default);
  --button-padding-x: var(--ds-size-4);
  --button-padding-y: var(--ds-size-2);
  
  /* Use local tokens */
  background: var(--button-bg);
  color: var(--button-text);
  padding: var(--button-padding-y) var(--button-padding-x);
}

.special-button--large {
  --button-padding-x: var(--ds-size-6);
  --button-padding-y: var(--ds-size-3);
}
```

## Integration with JavaScript/TypeScript

While tokens are primarily for CSS, you can access them in JavaScript if needed:

```typescript
// Get computed token value
const accentColor = getComputedStyle(document.documentElement)
  .getPropertyValue('--ds-color-accent-background-default')
  .trim();

console.log(accentColor); // e.g., "#0062BA"
```

## Troubleshooting

### Tokens Not Applying

1. **Check Import**: Ensure `@import '@statsbygg/design-tokens';` is in your global CSS.
2. **Build Your App**: If using a build tool, make sure you've run `npm run dev` or `npm run build`.
3. **Clear Cache**: Try clearing your browser cache or Next.js cache (`.next/` folder).

### Dark Mode Not Working

1. **Check HTML Attribute**: Verify `data-color-scheme` is set on the `<html>` element.
2. **Check OS Settings**: If relying on auto-detection, ensure your OS is set to dark mode.
3. **Inspect in DevTools**: Check computed values in browser DevTools to see which tokens are active.

### Wrong Colors in Production

If colors look different in production vs. development:

1. **Rebuild Tokens**: Run `npm install @statsbygg/design-tokens@latest` to get the latest version.
2. **Check CSS Order**: Ensure design tokens are imported *before* your component styles.

## Learn More

- [DigDir Designsystemet Documentation](https://designsystemet.no/)
- [Design Tokens Specification](https://designtokens.org/)
- [CSS Custom Properties (MDN)](https://developer.mozilla.org/en-US/docs/Web/CSS/--*)

---

**Created with ❤️ as Part of the Statsbygg Component System.**