Skip to content

Quality

Every claim on this page is one of two things: a number counted out of this repository when the page was built, or a gate you can run yourself in one command. Nothing here is a badge somebody drew.

That is a narrower promise than "high quality", and it is deliberate. A design system is adopted by people who will be blamed if it breaks, and what convinces them is not an adjective - it is knowing exactly what is checked, how often, and what is not checked at all. The last section on this page is the second half of that bargain.

What runs, and when

Every gate, the command that runs it, and where it runs. Read from the manifest, the git hooks and the CI workflow at build time.
Command What it checks Where it runs
pnpm lint:tokens Every foundation token a stylesheet references without a fallback is defined somewhere every build
pnpm lint:readmes Every component README follows the template the docs are generated from, and documents the events its code dispatches every build
pnpm lint:selectors Every is selector, and every is in markup, names the element that component upgrades every build
pnpm lint Biome, across the whole repository every commit, CI
pnpm test Component behavior, in a real browser rather than a DOM emulation every commit
pnpm test:coverage The same suite, against the coverage floors below CI
pnpm test:e2e The built site: the shell, the demos, the roadmap, and the axe accessibility gate every push, CI
pnpm build The site itself - which runs the three lint gates above before it writes anything CI

Nothing in that table is optional. The build refuses to produce a site when a token does not resolve, when a README does not follow the template, or when a stylesheet paints a component onto an element that component cannot be. The commit hook runs the linters and the unit suite; the push hook runs the browser suites; the pipeline runs all of it again on a machine that has never seen this working copy.

What the numbers are

WCAG 2.2 AA21/54

components whose live example is scanned by axe on every push, against the built site

Test suites65

component behavior files, run in a real browser

Statement coverage floor93%

the build fails below it, so the number cannot drift down quietly

Browser test files

65

One or more per component, plus the shared form-control suites

End-to-end specs

10

The built site: shell, demos, readiness and the roadmap

Accessibility specs

4

axe against dist/, per component and per shell surface

Coverage floors

93/82

Statements and branches, from vitest.config.mjs - functions and lines sit between them

CSS classes

0

Counted across everything that ships, not asserted

Third-party runtime dependencies

0

Across every package manifest in the workspace

Design tokens

451

Plus 1471 declared by components

Component stylesheets

217

Element and attribute selectors only

Two of those deserve a sentence. Zero CSS classes is counted, not claimed: the figure is the number of class selectors found in everything that ships, and if somebody writes one it stops being zero on the next build. Zero third-party runtime dependencies is counted the same way, across every package manifest in the workspace - the platform is the dependency, and that is a measurement rather than a slogan.

What it costs to load

Median component

1.8 kB

Gzipped, which is what the network carries

Heaviest component

3.8 kB

Range, the largest single import

All of Ready for Dev

58.7 kB

Every one of the 21 finished components at once, which no page needs

The face

216.0 kB

Inter, roman and italic, subset to Latin - a page fetches the roman

The five heaviest bundles, measured off the published files.
Component Transfer (gzip) On disk
Range 3.8 kB 14.1 kB
Paginator 3.4 kB 11.4 kB
Number 3.2 kB 12.5 kB
Tag 3.1 kB 15.9 kB
DataTable 2.8 kB 10.5 kB

A component is a file. There is no runtime to load first, no framework to reconcile with, and nothing shared to warm up: a page that uses one component pays for one component. The figures are the built bundles as they are published, and the transfer column is what the network actually carries.

The face costs more than all of them together, and that is worth saying plainly rather than leaving in a waterfall: Inter ships as two unsubset variable files, and on this site they are about two fifths of what a page transfers. Subsetting them is not done.

What this site costs is not what your page costs. Every page here loads every component, because any example may use any of them - 57 JavaScript files, around 900 kB on the wire. A product built on root imports the components it uses and nothing else.

What it must not exceed

Every ceiling this repository refuses to exceed, from perf.budgets.json, beside what it measures today.
Budget Ceiling Today Gated by
Heaviest component, gzipped 20 kB 3.8 kB pnpm perf:budget
Every Ready for Dev component at once 220 kB 58.7 kB pnpm perf:budget
Foundation stylesheet, gzipped 10 kB 7.8 kB pnpm perf:budget
What one page of this site transfers 750 kB measured on every run pnpm test:e2e
Requests one page makes 90 measured on every run pnpm test:e2e
Largest Contentful Paint 2500 ms measured on every run pnpm test:e2e
Cumulative Layout Shift 0.1 measured on every run pnpm test:e2e

Budgets are ceilings with headroom, committed in perf.budgets.json and enforced in two places: pnpm perf:budget weighs the built bundles in every build, and e2e/performance.spec.js measures the pages on every run of the browser suite. The two page metrics are the Core Web Vitals thresholds for "good", measured headless over a loopback interface - they catch a regression, and they say nothing about a reader on a train. No number here is field data, and none of them is presented as one.

Accessibility

Rule sets

5

wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22aa - read from the spec itself

Component pages scanned

21

Each at its first live example, in the built site

Overlays re-scanned open

5

A dialog scanned closed is a dialog nobody scanned

The gate runs against dist/ - the built artefact that deploys - rather than against a development server, so what is tested is what ships. Every component flagged Ready for Dev has its live example scanned for WCAG 2.2 A and AA violations, overlays are re-opened and scanned in their open state, and the shell's own surfaces are scanned on top of that. Beyond axe, each component's package carries keyboard and focus tests that run in a real browser.

The formal claim - what conforms, what does not, and where to report what this misses - is the accessibility statement. This section is the measurement behind it.

Where this stops

The honest half. None of the following is checked, and a team adopting this should know it:

  • The axe scan reaches one example per component page, the first one, plus the shell surfaces named above. A violation in a component's third example is not caught by this gate.
  • Components that are not flagged Ready for Dev are not gated at all - not by axe, not by the release. They are on this site with a warning on every page, which is a different promise from being safe to use.
  • Automated accessibility testing finds a fraction of what a person finds. WCAG 2.2 AA as checked by axe is a floor: it catches contrast, names, roles and structure, and it cannot tell you whether a flow makes sense with a screen reader.
  • There is no visual regression suite. A change that keeps every test green and moves a component four pixels ships.
  • Nothing here measures a single component's render. ADR-004 specified a Container Timing harness for exactly that, was never built, and is superseded by ADR-035: the budgets above are per bundle and per page, so a component that gets slow to paint without getting bigger passes every gate on this site.
  • The page metrics are local. LCP and CLS are measured headless, on the machine running the suite, over a loopback interface. They catch a regression against yesterday; they are not a claim about anybody's connection, and there is no field data here.
  • The fonts are not subset, and no gate objects: they are outside the bundle ceilings because they are the foundations' own files, and they are the largest thing a page fetches.
  • Coverage floors are floors. They stop the number falling; they do not mean the uncovered lines are unimportant.