Lesson 01 / 19
What Is a Design System
How a design system differs from a component library, how decisions split into value, component, pattern, and rule layers, and how to compute the share of those decisions a library actually answers.
Contents
The two courses so far taught how to get the catalog interface’s decisions right one at a time. The Fundamentals of Interface Design course established the grid, the spacing scale, the typographic scale, and the color roles; the User Experience and Behavior Design course showed which research finding each of those decisions rests on and how to measure its outcome. In both courses the unit was a single decision: how many pixels this gap is, how many steps this flow takes, whether this change lowered task time.
A decision can be made correctly. Making that same decision the same way a second, tenth, and hundredth time is a separate problem, and getting each one right individually does not solve it. The catalog interface is no longer just four screens: the admin panel, the member profile, the shelf layout screen, and the mobile app all have to speak the same language as products of the same institution. This lesson defines the structure that turns repetition itself into a design object, and separates it from what it is most often confused with — the component library.
The System Is the Named Form of Decisions
A design system is the structure that names, documents, and distributes an institution’s interface decisions so they can be referenced instead of remade. All three predicates of that definition are mandatory, and none substitutes for another.
Naming makes a decision legible from a name. “The Borrow button’s fill is neutral-600
over primary-600” is a decision; --action-primary is a name. As long as the name is used,
the decision is not remade, it is referenced.
Documentation carries the decision’s rationale along with its name. The Color System lesson showed by calculation that the primary and secondary actions cannot be separated by tone alone. If that finding is not written down, someone six months later gives the secondary action a purple fill and has to redo the same calculation from scratch.
Distribution makes the decision usable. A scale sitting in a design file that no one can install is not a decision, it is a wish.
A component library, by contrast, is only one delivery form of that structure: a packaged set of reusable interface parts. The library is the system’s output, not the system itself. The fastest way to sense the difference is to count how many decisions the interface actually carries.
Decisions Sit in Four Layers
The decisions made across the catalog interface’s four screens split into four layers. The value layer states which raw magnitude to use: a size step, a color role, a spacing step. The component layer defines a single part’s internal structure: a button’s inner padding, a text field’s border. The pattern layer sets how multiple components line up together: the ratio between the filter panel and the results list, the relationship between a form field and its label. The rule layer is the behavior contract that holds everywhere: a destructive action asks for confirmation, a focus indicator cannot be removed.
This split is clarified here so its name is not confused with the term interface pattern: a pattern is the name for how components are arranged relative to each other; a single component’s internal structure belongs to the component layer.
The program below counts these four layers and computes which ones a component library answers.
// scope.mjs — how many of the catalog interface's decisions a component library answers // Decisions actually made across the catalog interface's four screens. // layer: value -> which raw value to use (color, spacing, size) // layer: component -> a single component's internal structure // layer: pattern -> how multiple components are arranged together // layer: rule -> a behavior rule that holds everywhere const DECISIONS = [ { name: "body text size", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "heading size step", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "primary action fill", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "border color", layer: "value", screens: ["search", "results", "detail"] }, { name: "card inner padding", layer: "value", screens: ["results", "detail"] }, { name: "group inner spacing", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "corner radius", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "focus ring thickness", layer: "value", screens: ["search", "results", "detail", "confirmation"] }, { name: "button internal structure", layer: "component", screens: ["search", "results", "detail", "confirmation"] }, { name: "text field internal structure", layer: "component", screens: ["search"] }, { name: "record card internal structure", layer: "component", screens: ["results"] }, { name: "tag internal structure", layer: "component", screens: ["results", "detail"] }, { name: "confirmation dialog internal structure", layer: "component", screens: ["confirmation"] }, { name: "pagination internal structure", layer: "component", screens: ["results"] }, { name: "filter panel to results list ratio", layer: "pattern", screens: ["results"] }, { name: "empty results screen layout", layer: "pattern", screens: ["results"] }, { name: "form field and label arrangement", layer: "pattern", screens: ["search", "confirmation"] }, { name: "confirmation action placement", layer: "pattern", screens: ["confirmation"] }, { name: "record metadata order", layer: "pattern", screens: ["results", "detail"] }, { name: "destructive action requires confirmation", layer: "rule", screens: ["detail", "confirmation"] }, { name: "focus indicator cannot be removed", layer: "rule", screens: ["search", "results", "detail", "confirmation"] }, { name: "error message sits below the field", layer: "rule", screens: ["search", "confirmation"] }, { name: "loading state reserves space", layer: "rule", screens: ["results", "detail"] }, { name: "date format", layer: "rule", screens: ["results", "detail", "confirmation"] }, ]; // A component library packages only the "component" layer. const LIBRARY_LAYERS = new Set(["component"]); const layers = ["value", "component", "pattern", "rule"]; console.log("layer decision count total usage library answers it?"); let totalDecisions = 0; let totalUsage = 0; let covered = 0; for (const l of layers) { const group = DECISIONS.filter((d) => d.layer === l); const usage = group.reduce((t, d) => t + d.screens.length, 0); totalDecisions += group.length; totalUsage += usage; if (LIBRARY_LAYERS.has(l)) covered += group.length; console.log( `${l.padEnd(10)} ${String(group.length).padStart(14)} ${String(usage).padStart(12)} ${LIBRARY_LAYERS.has(l) ? "yes" : "no"}` ); } console.log(`total ${String(totalDecisions).padStart(14)} ${String(totalUsage).padStart(12)}`); console.log(`share of decisions the library covers: ${((100 * covered) / totalDecisions).toFixed(1)}%`); // When the value layer is unnamed: every value is rewritten in each component that uses it. const COMPONENTS = DECISIONS.filter((d) => d.layer === "component"); const valueUsage = { "body text size": ["button internal structure", "text field internal structure", "record card internal structure", "tag internal structure", "confirmation dialog internal structure", "pagination internal structure"], "heading size step": ["record card internal structure", "confirmation dialog internal structure"], "primary action fill": ["button internal structure", "confirmation dialog internal structure"], "border color": ["text field internal structure", "record card internal structure", "tag internal structure", "confirmation dialog internal structure"], "card inner padding": ["record card internal structure", "confirmation dialog internal structure"], "group inner spacing": ["button internal structure", "text field internal structure", "record card internal structure", "tag internal structure", "confirmation dialog internal structure", "pagination internal structure"], "corner radius": ["button internal structure", "text field internal structure", "record card internal structure", "tag internal structure", "confirmation dialog internal structure"], "focus ring thickness": ["button internal structure", "text field internal structure", "record card internal structure", "pagination internal structure"], }; console.log("\nvalue decision unnamed: how many components named: how many places"); let unnamedTotal = 0; for (const [name, users] of Object.entries(valueUsage)) { unnamedTotal += users.length; console.log(`${name.padEnd(24)} ${String(users.length).padStart(28)} ${"1".padStart(23)}`); } console.log(`${"total".padEnd(24)} ${String(unnamedTotal).padStart(28)} ${String(Object.keys(valueUsage).length).padStart(23)}`); console.log(`component count: ${COMPONENTS.length}`); console.log(`change-site ratio: ${(unnamedTotal / Object.keys(valueUsage).length).toFixed(2)} times`); console.log("\nchanging a single decision (example: corner radius 4 -> 8)"); console.log(` unnamed: ${valueUsage["corner radius"].length} component files change`); console.log(" named : 1 token definition changes, component files do not change");
layer decision count total usage library answers it? value 8 29 no component 6 10 yes pattern 5 7 no rule 5 13 no total 24 59 share of decisions the library covers: 25.0% value decision unnamed: how many components named: how many places body text size 6 1 heading size step 2 1 primary action fill 2 1 border color 4 1 card inner padding 2 1 group inner spacing 6 1 corner radius 5 1 focus ring thickness 4 1 total 31 8 component count: 6 change-site ratio: 3.88 times changing a single decision (example: corner radius 4 -> 8) unnamed: 5 component files change named : 1 token definition changes, component files do not change
The Library Covers a Quarter of the Decisions
The first table gives the lesson’s main finding. Six of twenty-four decisions sit in the component layer: 25%. Even if a component library is delivered complete, three-quarters of the interface’s decisions are still remade on every screen.
That share is itself misleadingly optimistic. The second column shows usage counts: the six components are used 10 times in total, while the eight value decisions are used 29 times. The value layer consists of both fewer decisions and more frequently referenced ones. Failing to hold a frequently referenced decision in one place is the most efficient producer of inconsistency.
The rule layer carries a separate warning. Five rules apply 13 times, and none of them lives in a component file. The rule “a destructive action requires confirmation” cannot be written into a button; a button does not know what happens when it is clicked. These rules can exist only as documentation, and when they are not documented, each screen rediscovers them on its own.
Naming Reduces Change Sites to One
The second table counts the cost of leaving the value layer unnamed. Eight value decisions appear in a total of 31 separate places across six components. When the same eight decisions are named, the number of definitions drops to 8: the number of change sites shrinks by a factor of 3.88.
The final block makes this concrete through a single change. Raising the corner radius from 4 pixels to 8 means five separate edits in five separate component files if the value is unnamed. Every one of those edits has to be found; any one that is not found is left alone in the interface and produces inconsistency. When the name is used, the change site is one, and components inherit the change automatically.
This is the system-level justification for the mechanism built in the Custom Properties lesson. There, the adjustment points a component exposed outward were defined as custom properties; the calculation here shows why that architecture is not a convenience but a necessity.
Five Differences Between a System and a Library
The numbers sharpen the definition. Turning a component library into a design system takes five more things.
Values are named. The numbers and colors components read are defined in a separate layer, independent of the components. This layer’s name will be design token, and it fills the entirety of the next topic.
Patterns are written down. How two components stand side by side cannot be written into the components; it stands as a separate document.
Rules become a contract. Behaviors that hold everywhere must rest on text that can be pointed to when violated.
Decision rationale is kept. Why a threshold is 4.5, why a ratio of 1.25 was chosen, stands alongside the decision. A decision without a rationale gets reargued at the next review.
Change is managed. We saw that when a token’s value changes, every place that uses it is affected; that is the power itself, and it is also the risk itself. Versioning, the contribution process, and governance are the answer to that risk.
A System Is Not a Product, It Is an Addition to Products
One final distinction is needed. A design system does not produce value for a user on its own; products do. The system’s measure is not its own completeness, but how much products benefit from it.
The practical consequence is that the system measures its own success through adoption: how many products, how many screens, what percentage of decisions come from the system. A system that is 100% complete but used in no product is more of a failure than one that is 40% incomplete but used on every screen. Adoption measurement is taken up separately in this course’s final topic; what matters here is that the system’s reason for existing lies not in itself but in its use.
This distinction also determines the scope decision. The system covers decisions that products actually repeat; a layout that appears once, on a single screen, belongs to that screen, not to the system. How scope is drawn depends on the justification calculation that is the subject of the next lesson.
Summary
- A design system is the named, documented, and distributed form of repeated interface decisions; a component library is only one delivery form of that structure.
- Interface decisions sit in four layers: value, component, pattern, and rule. A component library packages only one layer.
- In the measured interface, 6 of 24 decisions sit in the component layer; the library’s coverage is 25%, and the value layer is the most frequently referenced layer, with both fewer decisions and more usage.
- Eight unnamed value decisions appear in 31 places across six components; naming reduces the number of change sites by a factor of 3.88.
- The rule layer cannot live in any component file; it exists only as documentation, and when undocumented, each screen rediscovers it on its own.
- The system’s measure is not its own completeness but its adoption in products; scope is limited to the decisions products actually repeat.
Next Step
This lesson defined what a system is and measured the area the library does not cover. But the existence of an uncovered area does not prove that closing it pays off. Building a system is a cost: defining tokens, writing components, maintaining documentation, and migrating existing screens all take time. The next lesson computes that cost in terms of screen count, team count, and change frequency; it finds the screen count at which the systemless and systematic paths cross, and it also names the conditions under which a system cannot be justified.
To keep your progress and take notes, Log in
My notes
Log in to take notes.