Semantic Versioning for UI: What Counts as Breaking In short: A component's contract is bigger than its TypeScript. It includes CSS custom properties, accessible behaviour, and roughly how much space it occupies. Write down which of those you version, or every release becomes an argument. Semantic versioning is well understood on the backend. Change a payload shape, bump major. Add an optional endpoint, bump minor. Fix a query, bump patch. Applying it to a UI library produces immediate grey areas, because a component's API is not only its inputs. It is also , the fact that it announces as a listbox, and the fact that its header is 48px tall — because a consumer's layout is built around all three. The fix is not cleverness. It is a documented table your team applies mechanically. Patch Internal fixes that require nothing from consumers and change nothing visible. Refactoring internals — Chapter 4's Version 2 stepper rewrite is a patch. Fixing a bug where a dropdown was clipped behind a data grid. Adding a missing to an internal icon. Performance work with no visual outcome. The test: a consumer upgrades and their visual regression suite shows zero unexpected diffs. That test is precise and checkable — which is why Chapter 8's visual gate is what makes this table enforceable rather than aspirational. Minor Backwards-compatible additions. Existing code keeps working unchanged. A new optional input: . A new component or a new projection slot. A new value in a union that consumers read — adding to . A new CSS custom property. Marking something deprecated. It still works; the clock starts. A design change that alters appearance but not layout structure. That last one is the contentious case and it deserves the explicit rule below. Major Anything that breaks compilation, breaks layout, or breaks behaviour consumers rely on. TypeScript breaks — the ones Chapter 8's API diff catches automatically: Removing or renaming an input, output, or component. Changing an input's type, or an output's payload. Making an optional input required. Renaming a component selector. Removing a value from a union that consumers pass in . CSS contract breaks: Removing or renaming a documented custom property. Changing what a semantic token means — repurposing from amber to red. Chapter 6 made tokens part of the API, so this follows. It also means the token snapshot from Chapter 8 is not optional. Behaviour breaks: A component that announced as a listbox now announces as a group. Keyboard interaction changes — used to confirm, now it does not. An output that fired once now fires on every keystroke. Layout breaks: The component's minimum height or width changes materially. Its default changes from to . It starts requiring a positioned ancestor. The design-change rule The hardest recurring question: the brand refresh changes card corners from 4px to 8px and shifts the primary blue. Visual regression fails in all twenty consumers. Is that major? No. It is minor — and the reasoning is what matters. Design evolution is the purpose of a centralised platform. If every visual refinement were a major version, the platform would be unusable: twenty teams would need a coordinated migration to change a border radius, so nobody would ever change one, and the design system would freeze. The line is between appearance and structure : Change Version Why --- --- --- Border radius 4px → 8px Minor Occupies the same space Primary blue shifts one step Minor Same footprint Font size 14px → 15px Minor Reflows text, does not restructure Card header 48px → 80px Major Pushes everything below it down Card → Major Changes how it sits among siblings Card gains a required footer region Major Changes its shape Appearance changes are minor; footprint changes are major. The consumer workflow for a minor design change is documented and cheap: 1. The library publishes the minor release. 2. The consumer upgrades. 3. Their visual regression suite fails — as designed. 4. They review the image diffs, confirm it is the intended refresh, and approve the new baselines through the labelled CI job from Chapter 8. That is fifteen minutes, not a migration. The whole reason it is fifteen minutes is that they have a visual gate — which is why this chapter comes after that one. Write it down Put the table in the library's README and reference it in every release note. Its value is not that it is the only defensible answer; it is that everyone applies the same answer. The failure mode without it is not a wrong decision, it is an inconsistent one — a border radius shipped as a patch in March and as a major in June, and consumers who learn that your version numbers do not mean anything. "But I thought any visible change should be a major version" This position is genuinely defensible and it comes from taking consumers seriously: if their screenshots change, something changed for them, so warn them properly. Follow it through, though, and it produces the opposite of what it intends. It make…