Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion docs/02-design-tokens-reference.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Design Tokens Reference

**Last Updated:** March 5, 2026
**Last Updated:** March 15, 2026

Complete reference for all design tokens in the Design System Starter Kit.

Expand All @@ -14,6 +14,7 @@ Complete reference for all design tokens in the Design System Starter Kit.
4. [Colors](#colors)
5. [Borders](#borders)
6. [Focus States](#focus-states)
7. [Motion](#motion)

---

Expand Down Expand Up @@ -308,6 +309,50 @@ Focus indicators use a dual-outline technique: a primary `outline` for the main

---

## Motion

### Transition Duration

Five semantic durations for UI transitions. All are set to `0ms` under `@media (prefers-reduced-motion: reduce)`.

| Token | CSS Variable | Value |
| ------- | ----------------------------------- | ----- |
| instant | `--dsn-transition-duration-instant` | 0ms |
| fast | `--dsn-transition-duration-fast` | 100ms |
| normal | `--dsn-transition-duration-normal` | 200ms |
| slow | `--dsn-transition-duration-slow` | 350ms |
| slower | `--dsn-transition-duration-slower` | 500ms |

### Transition Easing

Five semantic easing curves for consistent motion feel.

| Token | CSS Variable | Value |
| ------- | --------------------------------- | ---------------------------------- |
| default | `--dsn-transition-easing-default` | `cubic-bezier(0.25, 0.1, 0.25, 1)` |
| enter | `--dsn-transition-easing-enter` | `cubic-bezier(0, 0, 0.2, 1)` |
| exit | `--dsn-transition-easing-exit` | `cubic-bezier(0.4, 0, 1, 1)` |
| move | `--dsn-transition-easing-move` | `cubic-bezier(0.4, 0, 0.2, 1)` |
| linear | `--dsn-transition-easing-linear` | `linear` |

**Usage in components:**

```css
.dsn-button {
transition:
background-color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
border-color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
}
```

**Reduced motion:** All duration tokens resolve to `0ms` via a central `@media (prefers-reduced-motion: reduce)` block appended to every full CSS configuration — no component-level media queries needed.

---

## Token Statistics

**Total Tokens (as of v4.9.0):**
Expand Down
45 changes: 44 additions & 1 deletion docs/05-storybook-configuration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Storybook Configuration

**Last Updated:** March 13, 2026
**Last Updated:** March 15, 2026

Documentation for the Storybook setup, runtime theme switching, UI components, and documentation structure.

Expand Down Expand Up @@ -398,6 +398,49 @@ const meta: Meta<typeof Button> = {
/>
```

### TokenTable

**Location:** `packages/storybook/src/components/TokenTable.tsx`

**Purpose:** Renders a table of design tokens with optional live preview visuals and computed CSS values.

**Props:**

| Prop | Type | Default | Description |
| --------------- | ------------- | -------- | ----------------------------------- |
| `tokens` | `Token[]` | — | Array of `{ name, cssVar, value? }` |
| `previewType` | `PreviewType` | `'none'` | Visual preview type |
| `showLiveValue` | `boolean` | `true` | Show computed CSS value |

**`previewType` values:**

| Value | Preview |
| ----------------------- | ------------------------------------------------------------- |
| `'color'` | Gekleurd vlak 32×32px |
| `'spacing'` | Horizontale balk (breedte = tokenwaarde) |
| `'typography-size'` | "Aa" in de tokengrootte |
| `'border-radius'` | Gevuld vlak 40×40px met border-radius toegepast |
| `'shadow'` | Kaartje met `box-shadow` toegepast |
| `'transition-duration'` | Animerende sweep-balk (animationDuration = token) |
| `'transition-easing'` | Stip op track (animationTimingFunction = token, vaste 1200ms) |
| `'none'` | Geen preview kolom |

Alle kleur-previews gebruiken `--dsn-color-accent-1-inverse-bg-default` als accentkleur.

### TocLink

**Location:** `packages/storybook/src/components/TocLink.tsx`

**Purpose:** Anchor-navigatie binnen een Storybook docs-pagina zonder de Storybook URL te breken.

Storybook gebruikt `?path=`-gebaseerde URL-routing. Een gewone `<a href="#section">` vervangt de hele URL en laat de sidebar verdwijnen. `TocLink` onderschept de klik via `e.preventDefault()` en roept `document.getElementById(targetId)?.scrollIntoView({ behavior: 'smooth' })` aan.

```tsx
<TocLink targetId="colors">Colors</TocLink>
// rendert als: <a class="dsn-link" href="#colors">Colors</a>
// klik: scrollt naar element met id="colors", geen URL-verandering
```

---

## Documentation Structure
Expand Down
14 changes: 14 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ All notable changes to this project are documented in this file.

---

## Version 5.8.0 (March 15, 2026)

### Motion tokens: transition duration & easing (PR #85)

- **10 nieuwe design tokens** — 5 duration (`instant/fast/normal/slow/slower`) en 5 easing (`default/enter/exit/move/linear`) in `base.json` van het Start-thema
- **Centrale `prefers-reduced-motion` media query** — toegevoegd via `build.js` post-processing aan alle 8 volledige CSS-configuraties; alle duration tokens worden `0ms`; geen component-level media queries nodig
- **5 component CSS-bestanden bijgewerkt** — hardcoded `0.2s ease` vervangen door `var(--dsn-transition-duration-normal)` en `var(--dsn-transition-easing-default)` in `button.css`, `link.css`, `text-input.css`, `text-area.css`, `details.css`
- **Storybook Design Tokens pagina uitgebreid** — Motion-sectie toegevoegd onderaan met `## Motion`, `### Transition Duration` en `### Transition Easing` tabellen
- **`TokenTable` nieuwe `previewType` waarden** — `transition-duration` (animated sweep bar) en `transition-easing` (dot op track) tonen live animatie-previews in de documentatie
- **Navigatie-index** toegevoegd aan de Design Tokens pagina — genummerde `OrderedList` met `TocLink` componenten (gebruikt `scrollIntoView` i.p.v. URL-navigatie zodat de Storybook sidebar intact blijft)
- **Preview kleuren** geüniformeerd — spacing, border-radius en motion previews gebruiken allemaal `--dsn-color-accent-1-inverse-bg-default`

---

## Version 5.7.0 (March 13, 2026)

### Body component: document-level cascade basisstijlen (PR #84, issue #83)
Expand Down
9 changes: 6 additions & 3 deletions packages/components-html/src/button/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
cursor: pointer;
user-select: none;
transition:
background-color 0.2s ease,
color 0.2s ease,
border-color 0.2s ease;
background-color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
border-color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);

/* Accessibility - WCAG pointer target */
min-block-size: var(--dsn-button-min-block-size);
Expand Down
3 changes: 2 additions & 1 deletion packages/components-html/src/details/details.css
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
width: var(--dsn-details-icon-size);
height: var(--dsn-details-icon-size);
color: var(--dsn-details-summary-color);
transition: transform 0.2s ease;
transition: transform var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
}

.dsn-details[open] .dsn-details__icon {
Expand Down
6 changes: 4 additions & 2 deletions packages/components-html/src/link/link.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
/* Interaction */
cursor: pointer;
transition:
color 0.2s ease,
text-decoration-color 0.2s ease;
color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
text-decoration-color var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
}

/* Icon sizing */
Expand Down
4 changes: 2 additions & 2 deletions packages/components-html/src/text-area/text-area.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@

/* Transitions */
transition-property: border-color, box-shadow, background-color;
transition-duration: 0.2s;
transition-timing-function: ease-in-out;
transition-duration: var(--dsn-transition-duration-normal);
transition-timing-function: var(--dsn-transition-easing-default);
}

/* Placeholder */
Expand Down
4 changes: 2 additions & 2 deletions packages/components-html/src/text-input/text-input.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@

/* Transitions */
transition-property: border-color, box-shadow, background-color;
transition-duration: 0.2s;
transition-timing-function: ease-in-out;
transition-duration: var(--dsn-transition-duration-normal);
transition-timing-function: var(--dsn-transition-easing-default);
}

/* Placeholder */
Expand Down
30 changes: 30 additions & 0 deletions packages/design-tokens/src/config/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ fullConfigNames.forEach((name, index) => {

console.log(`\n✅ Built ${fullConfigNames.length} full configurations\n`);

// =============================================================================
// APPEND PREFERS-REDUCED-MOTION MEDIA QUERY
// =============================================================================

console.log(
'🎬 Appending prefers-reduced-motion media query to CSS files...\n'
);

const reducedMotionBlock = `
@media (prefers-reduced-motion: reduce) {
:root {
--dsn-transition-duration-instant: 0ms;
--dsn-transition-duration-fast: 0ms;
--dsn-transition-duration-normal: 0ms;
--dsn-transition-duration-slow: 0ms;
--dsn-transition-duration-slower: 0ms;
}
}
`;

fullConfigNames.forEach((name) => {
const cssFilePath = path.join(__dirname, '..', '..', `dist/css/${name}.css`);
if (fs.existsSync(cssFilePath)) {
fs.appendFileSync(cssFilePath, reducedMotionBlock);
console.log(` ✅ dist/css/${name}.css`);
}
});

console.log('\n✅ prefers-reduced-motion media query appended\n');

// =============================================================================
// BUILD SCOPED CONFIGURATIONS (for runtime switching)
// =============================================================================
Expand Down
46 changes: 46 additions & 0 deletions packages/design-tokens/src/tokens/themes/start/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,52 @@
"value": "0 4px 8px 0 {dsn.color.shadow.direct}, 0 16px 32px 0 {dsn.color.shadow.ambient}, 0 0 0 1px {dsn.color.shadow.highlight}",
"comment": "Grote elevatie — modals, dialogen, side panels"
}
},
"transition": {
"duration": {
"instant": {
"value": "0ms",
"comment": "State-changes die onmiddellijk moeten aanvoelen"
},
"fast": {
"value": "100ms",
"comment": "Subtiele hover-states, kleur-transitions"
},
"normal": {
"value": "200ms",
"comment": "Standaard UI-transitions"
},
"slow": {
"value": "350ms",
"comment": "Grotere bewegingen, accordions"
},
"slower": {
"value": "500ms",
"comment": "Complexe animaties, page-level transitions"
}
},
"easing": {
"default": {
"value": "cubic-bezier(0.25, 0.1, 0.25, 1)",
"comment": "Algemeen — equivalent van CSS ease"
},
"enter": {
"value": "cubic-bezier(0, 0, 0.2, 1)",
"comment": "Elementen die het scherm binnenkomen (decelereren)"
},
"exit": {
"value": "cubic-bezier(0.4, 0, 1, 1)",
"comment": "Elementen die het scherm verlaten (accelereren)"
},
"move": {
"value": "cubic-bezier(0.4, 0, 0.2, 1)",
"comment": "Elementen die van positie wisselen"
},
"linear": {
"value": "linear",
"comment": "Progress bars, loaders"
}
}
}
}
}
51 changes: 51 additions & 0 deletions packages/storybook/src/DesignTokens.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Meta } from '@storybook/blocks';
import { TokenTable } from './components/TokenTable';
import { TokenControls } from './components/TokenControls';
import { OrderedList } from '@dsn/components-react';
import { TocLink } from './components/TocLink';

<Meta title="Foundations/Design Tokens" />

Expand All @@ -12,6 +14,21 @@ Design tokens are the single source of truth for colors, typography, spacing, bo

---

<OrderedList>
<li><TocLink targetId="colors">Colors</TocLink></li>
<li><TocLink targetId="inverse-colors">Inverse Colors</TocLink></li>
<li><TocLink targetId="typography">Typography</TocLink></li>
<li><TocLink targetId="spacing">Spacing</TocLink></li>
<li><TocLink targetId="borders">Borders</TocLink></li>
<li><TocLink targetId="focus-indicators">Focus Indicators</TocLink></li>
<li><TocLink targetId="icon-sizes">Icon Sizes</TocLink></li>
<li><TocLink targetId="pointer-target-sizing">Pointer Target Sizing</TocLink></li>
<li><TocLink targetId="box-shadows">Box Shadows</TocLink></li>
<li><TocLink targetId="motion">Motion</TocLink></li>
</OrderedList>

---

## Colors

Each color scale provides a full set of tokens for backgrounds, borders, and text — including document, elevated, subtle, default, hover, and active states. The **elevated** token is intended for floating UI layers (modals, popovers, dropdowns) that appear above the document surface.
Expand Down Expand Up @@ -675,3 +692,37 @@ The three primitives that power all elevation shadows. In light mode `highlight`
{ name: 'lg — Modals, dialogs', cssVar: '--dsn-box-shadow-lg' },
]}
/>

---

## Motion

Motion tokens beheren timing en easing op één centrale plek. Alle componenten gebruiken deze tokens — waardoor `prefers-reduced-motion` automatisch en consistent wordt gerespecteerd.

Bij `prefers-reduced-motion: reduce` worden alle duration-tokens naar `0ms` gezet via een centrale media query in het theme CSS-bestand. Componenten hoeven zelf geen media query te implementeren.

### Transition Duration

<TokenTable
previewType="transition-duration"
tokens={[
{ name: 'Instant', cssVar: '--dsn-transition-duration-instant', value: '0ms' },
{ name: 'Fast', cssVar: '--dsn-transition-duration-fast', value: '100ms' },
{ name: 'Normal', cssVar: '--dsn-transition-duration-normal', value: '200ms' },
{ name: 'Slow', cssVar: '--dsn-transition-duration-slow', value: '350ms' },
{ name: 'Slower', cssVar: '--dsn-transition-duration-slower', value: '500ms' },
]}
/>

### Transition Easing

<TokenTable
previewType="transition-easing"
tokens={[
{ name: 'Default', cssVar: '--dsn-transition-easing-default', value: 'cubic-bezier(0.25, 0.1, 0.25, 1)' },
{ name: 'Enter', cssVar: '--dsn-transition-easing-enter', value: 'cubic-bezier(0, 0, 0.2, 1)' },
{ name: 'Exit', cssVar: '--dsn-transition-easing-exit', value: 'cubic-bezier(0.4, 0, 1, 1)' },
{ name: 'Move', cssVar: '--dsn-transition-easing-move', value: 'cubic-bezier(0.4, 0, 0.2, 1)' },
{ name: 'Linear', cssVar: '--dsn-transition-easing-linear', value: 'linear' },
]}
/>
20 changes: 20 additions & 0 deletions packages/storybook/src/components/TocLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { Link } from '@dsn/components-react';

interface TocLinkProps {
targetId: string;
children: React.ReactNode;
}

export function TocLink({ targetId, children }: TocLinkProps) {
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
document.getElementById(targetId)?.scrollIntoView({ behavior: 'smooth' });
};

return (
<Link href={`#${targetId}`} onClick={handleClick}>
{children}
</Link>
);
}
Loading
Loading