Design System for the City of Amsterdam http://designsystem.amsterdam
  • TypeScript 75.2%
  • MDX 13.9%
  • SCSS 6.4%
  • JavaScript 3.5%
  • CSS 0.8%
  • Other 0.2%
Find a file
Vincent Smedinga 6596b00fd7
chore(Storybook): Snapshot CSS utilities in Chromatic (#2816)
## Links

- Follows #2815, which did the same for page templates.
- [Test
stories](https://github.com/Amsterdam/design-system/blob/chore/DES-1801-chromatic-css-utilities/documentation/storybook.md#test-stories)
in the Storybook documentation.

## What

Adds Chromatic coverage for the seven CSS utilities, which had none.
`onlyStoryNames` matched `Components` and `Pages` only, so nothing under
`Utilities/` was ever snapshotted. Each utility now has a Test story,
matched by a new `Utilities/**/**/Test` pattern.

Also renames `storybook/src/utils/` to `storybook/src/utilities/`, so
the directory matches the section its stories appear in.

## Why

These utilities are pure styling — `ams-prose`, `ams-visually-hidden`,
and the gap and margin helpers — so a visual diff is the only test that
catches a regression in them. `ams-prose` in particular leans on
`:has()`-based pairwise spacing between headings, tables and paragraphs,
which nothing else guards.

## How

With test stories, rather than by widening the glob to `Utilities/**`.
Widening it looks like the cheaper option, but it isn’t: a page story is
the whole artefact, whereas a utility story is one arg permutation of a
parameterised demo, and Chromatic only ever renders the default arg.
Snapshotting the presentation stories would have captured one of five
gaps, one of six margins, one of six aspect ratios, and the container
query never firing. A Test story holds the whole scale in one image, so
it costs the same seven stories while covering roughly 25 states.

`renderComponentVariants` can’t help here. The component next to each
utility is a mock that renders a bare element, and the utility class
comes from the story’s `render`, so a generated matrix would show
elements without the class on them. The matrices are built by hand
instead, taking their scales from the CSS rather than from the mock
components’ props — which is why Margin covers a `2xl` that its own
control doesn’t offer.

Body, Prose and Visually Hidden have no variants. Their `render` moved
onto the meta and the Test story inherits it, so the snapshot can’t
drift away from the story we document.

## Checklist

- [x] Add or update unit tests
- [x] Add or update documentation
- [x] Add or update stories
- [x] Add or update exports in index.\* files
- [x] Comment `/chromatic test` and verify visual regression tests pass
- [x] Start the PR title with a Conventional Commit prefix, [as
explained
here](https://github.com/Amsterdam/design-system/blob/main/documentation/publishing.md?plain=1#L11)

## Additional notes

I checked the glob against the built `index.json` with picomatch before
committing: the seven Test stories match, the seven presentation stories
don’t — so nothing gets snapshotted twice — and the existing patterns
still return 78 components and 22 pages.

Two things worth a look while reviewing.

`margin.scss` ships a `2xl` size that both the mock type and
`shortSize.ts` omit, so it is undocumented and unreachable from the
controls. I left it alone here, since `shortSize` is exported from
`packages/react` and changing it is a bigger call, but it deserves a
follow-up.

`ams-visually-hidden` is built on the same `:not(:active, :focus)` shape
that the Chromatic pseudo-state addon is documented to break for the
Skip Link. It renders correctly locally, but its first baseline is worth
looking at rather than accepting straight away.
2026-07-21 08:12:23 +02:00
.github chore(deps): Bump actions/setup-node from 6.4.0 to 7.0.0 (#2800) 2026-07-17 14:45:09 +02:00
.husky chore(deps): Adopt nano-staged instead of lint-staged (#2740) 2026-07-02 17:56:36 +02:00
documentation chore(Storybook): Snapshot CSS utilities in Chromatic (#2816) 2026-07-21 08:12:23 +02:00
packages feat(Icon Button): Give the disabled contrast variant a grey background (#2814) 2026-07-20 17:03:10 +02:00
packages-proprietary feat(Icon Button): Give the disabled contrast variant a grey background (#2814) 2026-07-20 17:03:10 +02:00
plop-templates chore(plop): Add missing blank lines between import groups in templates (#2742) 2026-07-03 01:02:17 +02:00
storybook chore(Storybook): Snapshot CSS utilities in Chromatic (#2816) 2026-07-21 08:12:23 +02:00
stylelint fix(Description List): Let tokenised grid tracks shrink below the minimum content size (#2806) 2026-07-18 16:10:48 +02:00
.editorconfig Initial commit 2022-11-18 11:19:08 +01:00
.gitattributes Initial commit 2022-11-18 11:19:08 +01:00
.gitignore chore(deps): Upgrade TypeScript to 6.0.3 (#2790) 2026-07-12 22:16:29 +02:00
.nano-staged.json chore: Check staged YAML with Prettier (#2759) 2026-07-06 21:57:19 +02:00
.npmpackagejsonlintrc.json chore: Publish all packages with provenance statements (#2619) 2026-05-13 16:53:32 +02:00
.nvmrc chore: Use npm trusted publishing (#2278) 2025-10-31 12:18:37 +00:00
.prettierignore chore: Add instructions for AI coding agents (#2511) 2026-04-24 13:40:27 +02:00
.prettierrc.json Fix prettier issues (#462) 2023-08-03 16:48:09 +02:00
.release-please-manifest.json chore: release main (#2787) 2026-07-12 12:16:38 +02:00
.stylelintignore chore: Remove unnecessary entries from ignore files, use pnpm in contributor docs (#2489) 2026-03-27 15:35:02 +01:00
.stylelintrc.json fix(Description List): Let tokenised grid tracks shrink below the minimum content size (#2806) 2026-07-18 16:10:48 +02:00
AGENTS.md chore(Storybook): Add a Release notes page (#2801) 2026-07-17 23:48:54 +02:00
CONTRIBUTING.md chore(pnpm): Post-v11 cleanup and explicit build step (#2639) 2026-05-22 13:58:43 +00:00
eslint.config.mjs chore(ESLint): Enable Markdown linting and declare plugins explicitly (#2739) 2026-07-02 17:52:49 +02:00
eslint.rules.mjs chore(storybook): introduce #storybook and #tokens path aliases 2026-06-16 14:41:39 +02:00
LICENSE.md chore: Translate all documentation to English (#1054) 2024-01-26 15:55:19 +01:00
LICENSE.txt Initial commit 2022-11-18 11:19:08 +01:00
NOTICE.md chore(docs): Improve documentation on Spacious and Compact Mode (#2289) 2025-11-21 12:34:52 +01:00
package.json chore: Add defensive CSS linting with token-aware rules and a full audit (#2803) 2026-07-18 14:57:30 +02:00
plopfile.mjs chore: Insert scaffolded index entries in sorted order (#2743) 2026-07-03 01:17:16 +02:00
pnpm-lock.yaml chore: Add defensive CSS linting with token-aware rules and a full audit (#2803) 2026-07-18 14:57:30 +02:00
pnpm-workspace.yaml chore: Add defensive CSS linting with token-aware rules and a full audit (#2803) 2026-07-18 14:57:30 +02:00
publiccode.yml chore: Enable indexing on oss.developer.overheid.nl (#2737) 2026-07-10 22:40:29 +02:00
README.md feat(Storybook): Add an MCP server for AI assistants (#2760) 2026-07-06 23:36:04 +02:00
release-please-config.json chore: Rename ‘proprietary’ directory to ‘packages-proprietary’ (#1969) 2025-04-04 11:42:07 +02:00
tsconfig.json chore(deps): Upgrade TypeScript to 6.0.3 (#2790) 2026-07-12 22:16:29 +02:00

Amsterdam Design System

This is the guide for the user interfaces of all digital products and services provided by the City of Amsterdam.

We offer reusable components, patterns and guides for teams that work on our websites. This helps everyone work faster and better, with more time to create value. To our citizens and businesses, all our channels look the same and work similarly; they are broadly accessible and evoke trust.

We aim to create libraries for, or support otherwise, Figma, CSS, React, React Native, and Mendix.

A Storybook portal demonstrates our components and documentation.

Our Figma Library contains the design of our components and patterns.

Getting started

See the getting started documentation for developers on how to use our React components.

AI assistance

If you build with an AI coding assistant, connect it to our Model Context Protocol (MCP) server. Your assistant then works with real Amsterdam Design System components and their correct properties, instead of inventing markup. See connecting AI assistants to set it up.

Contributing

See the documentation for contributors.

Code of conduct

We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. Read our Code of Conduct if you havent already.

NL Design System

This project is part of a community initiative to use NL Design System components for websites that comply with the Amsterdam Design System.

Join the #nl-design-system Slack via praatmee.codefor.nl for more information and to learn about things happening in our open-source community.

Thanks

Thanks to Chromatic for providing the visual testing platform that helps us review UI changes and catch visual regressions.

Licence

This project is free and open-source software licenced under the European Union Public License (EUPL) v1.2 or higher. Documentation is licenced as Creative Commons Zero 1.0 Universal (CC0-1.0).

The open-source licences do not cover the assets in the packages-proprietary directory. Each directory in the packages-proprietary directory specifies the applicable licence for that directory. Please read the notice for more information about proprietary assets.