Lesson 05 / 19
Design Language
Testing design principles with a distinctiveness check, deriving idle principles and unsupported decisions from a principle-decision matrix, reading principle conflicts, and checking a tone-of-voice contract.
Contents
The previous four lessons built the system’s numeric skeleton: scope, justification, inventory, and scale. The skeleton says what can be used; it does not say which option is right. Two separate interfaces can be built with the same spacing scale; one dense and quiet, the other airy and directive. Both conform to the scale.
Design language is the set of decision grounds that fills the gap the scales leave behind: principles, tone of voice, and brand expression. This lesson’s question is whether these grounds are checkable. A principle is a principle only if it can reject an option; a tone of voice is a contract only if a violation of it can be pointed to.
A Principle Is a Sentence Whose Opposite Is Defensible
A design principle’s job is to force a decision. The criterion for forcing a decision is this: the principle’s opposite must also be a defensible position. “We care about the user” is not a principle, because no one defends its opposite; it rules out no option and therefore settles no argument. “Record first, tools second” is a principle, because its opposite — the interface showing its own tools first — is a position genuinely defended somewhere.
The same criterion applies to consistency. The Repetition and Consistency lesson showed consistency’s value, but consistency is not a design principle; it is the system’s condition of existing. Principles determine which option is taken within the system.
The second criterion is showing that the principle actually touches decisions. The program below runs two checks at once: it tests principles by the defensibility of their opposite and extracts the overlap between principles and decisions. The third block checks the tone-of-voice contract.
// language.mjs — distinctiveness of design principles, principle-decision overlap, and tone-of-voice audit // 1) Distinctiveness: a principle forces a decision only if its opposite is defensible. // "opposite" is the written form of the principle's counterpart; "defensible" is a human judgment. const PRINCIPLES = [ { name: "record first", opposite: "tools first", defensible: true }, { name: "quiet interface", opposite: "directive interface", defensible: true }, { name: "reversibility", opposite: "confirmation-based protection", defensible: true }, { name: "dense list", opposite: "airy list", defensible: true }, { name: "we care about the user", opposite: "we do not care about the user", defensible: false }, { name: "being consistent", opposite: "being inconsistent", defensible: false }, { name: "accessibility is non-negotiable", opposite: "accessibility depends on the feature", defensible: true }, ]; console.log("principle opposite distinctive?"); for (const i of PRINCIPLES) { console.log(`${i.name.padEnd(33)} ${i.opposite.padEnd(30)} ${i.defensible ? "yes" : "NO"}`); } const distinctive = PRINCIPLES.filter((i) => i.defensible); console.log(`distinctive principle count: ${distinctive.length} / ${PRINCIPLES.length}`); // 2) Principle-decision matrix. For each decision, which principle affects it and in which direction. // direction: +1 supports the decision, -1 opposes it. const DECISIONS = [ { name: "record title larger than cover image", effect: { "record first": 1, "dense list": 1 } }, { name: "results list laid out densely", effect: { "dense list": 1, "quiet interface": 1 } }, { name: "borrowing is one click, reversible", effect: { reversibility: 1, "quiet interface": 1 } }, { name: "record deletion asks for confirmation", effect: { reversibility: -1, "quiet interface": -1 } }, { name: "filter panel always open", effect: { "dense list": -1, "record first": 1 } }, { name: "focus indicator on every component", effect: { "accessibility is non-negotiable": 1 } }, { name: "suggestion list shown in the empty state", effect: { "quiet interface": -1 } }, { name: "cover images shown as small thumbnails", effect: { "record first": 1, "dense list": 1 } }, { name: "top menu stays fixed", effect: {} }, { name: "continuous scroll instead of pagination", effect: {} }, ]; console.log("\nprinciple supports opposes total"); for (const i of PRINCIPLES) { const plus = DECISIONS.filter((k) => k.effect[i.name] === 1).length; const minus = DECISIONS.filter((k) => k.effect[i.name] === -1).length; console.log( `${i.name.padEnd(33)} ${String(plus).padStart(8)} ${String(minus).padStart(8)} ${String(plus + minus).padStart(6)}` ); } const idlePrinciples = PRINCIPLES.filter((i) => !DECISIONS.some((k) => i.name in k.effect)); const unsupported = DECISIONS.filter((k) => Object.keys(k.effect).length === 0); const conflicting = DECISIONS.filter((k) => { const y = Object.values(k.effect); return y.includes(1) && y.includes(-1); }); const tension = DECISIONS.filter((k) => Object.values(k.effect).every((v) => v === -1) && Object.keys(k.effect).length > 0); console.log(`\nidle principle (determined no decision): ${idlePrinciples.map((i) => i.name).join(", ") || "none"}`); console.log(`unsupported decision (tied to no principle): ${unsupported.map((k) => k.name).join(", ") || "none"}`); console.log(`decision carrying an internal conflict: ${conflicting.map((k) => k.name).join(", ") || "none"}`); console.log(`decision made despite the principles: ${tension.map((k) => k.name).join(", ") || "none"}`); // 3) Tone-of-voice contract audit. Rules must be checkable. const TEXTS = [ { location: "search empty result", text: "Your search returned no results. Search by author name or ISBN." }, { location: "borrow successful", text: "Borrowed. Due back March 12." }, { location: "borrow error", text: "We are sorry, unfortunately an error occurred. Please try again." }, { location: "overdue warning", text: "The due date has passed. Use the extend button to renew." }, { location: "field validation", text: "You entered an invalid value." }, { location: "delete confirmation", text: "The record will be deleted. This action cannot be undone. Confirm to delete." }, { location: "empty shelf state", text: "This shelf has no records. To add a record, select the shelf and use the add button, then select a title from the list." }, ]; const FORBIDDEN = ["sorry", "unfortunately", "invalid", "you entered", "please"]; const ACTION_VERB = ["search", "use", "confirm", "select", "try", "add"]; const MAX_WORDS = 14; console.log("\nlocation words forbidden word action exclaim result"); let violating = 0; for (const m of TEXTS) { const lower = m.text.toLowerCase(); const words = m.text.trim().split(/\s+/).length; const forbidden = FORBIDDEN.filter((y) => lower.includes(y)); const action = ACTION_VERB.some((f) => lower.includes(f)); const exclaim = m.text.includes("!"); const violations = []; if (words > MAX_WORDS) violations.push("long"); if (forbidden.length) violations.push("forbidden"); if (!action) violations.push("no action"); if (exclaim) violations.push("exclaim"); if (violations.length) violating++; console.log( `${m.location.padEnd(19)} ${String(words).padStart(5)} ${(forbidden.join(",") || "-").padEnd(26)} ` + `${(action ? "yes" : "NO").padEnd(6)} ${(exclaim ? "yes" : "-").padEnd(7)} ${violations.join("+") || "pass"}` ); } console.log(`text with a violation: ${violating} / ${TEXTS.length}`);
principle opposite distinctive? record first tools first yes quiet interface directive interface yes reversibility confirmation-based protection yes dense list airy list yes we care about the user we do not care about the user NO being consistent being inconsistent NO accessibility is non-negotiable accessibility depends on the feature yes distinctive principle count: 5 / 7 principle supports opposes total record first 3 0 3 quiet interface 2 2 4 reversibility 1 1 2 dense list 3 1 4 we care about the user 0 0 0 being consistent 0 0 0 accessibility is non-negotiable 1 0 1 idle principle (determined no decision): we care about the user, being consistent unsupported decision (tied to no principle): top menu stays fixed, continuous scroll instead of pagination decision carrying an internal conflict: filter panel always open decision made despite the principles: record deletion asks for confirmation, suggestion list shown in the empty state location words forbidden word action exclaim result search empty result 11 - yes - pass borrow successful 5 - NO - no action borrow error 10 sorry,unfortunately,please yes - forbidden overdue warning 11 - yes - pass field validation 5 invalid,you entered NO - forbidden+no action delete confirmation 13 - yes - pass empty shelf state 24 - yes - long text with a violation: 4 / 7
Two Checks, Four Findings
The first table eliminates two of seven candidate principles. “We care about the user” and “being consistent” are not distinctive, because their opposites cannot be defended. The second table eliminates the same two principles a second time: they support no decision and oppose none, their total effect is zero. Two independent criteria flagging the same two principles is not a coincidence; a sentence whose opposite cannot be defended can already rule out no option.
An idle principle does not make it onto the list. Every line in a principles document has a cost: time to read, the burden of memorizing it, and a newcomer taking it seriously and trying to apply it for nothing. An ineffective principle dilutes the document and lowers the credibility of the ones that do work.
An unsupported decision is the finding in the opposite direction: the top menu staying fixed and using continuous scroll instead of pagination cannot be tied to any principle. This does not mean the decisions are wrong; it means their grounds are not written down. Two possibilities follow. Either the decisions are genuinely unsupported and fall at the first objection, or the principles list is incomplete and an unwritten principle is what determines these decisions. In the second case, the missing principle is found and written down; this is the audit’s most productive output.
A Conflict Is Not a Flaw
The third finding is the filter panel staying always open. This decision supports one principle (record first: filters speed up reaching a record) and opposes another (dense list: the panel narrows the list area).
A conflict like this is not a flaw in the system, it is proof that the principles are working. A set of principles that never conflict is usually a set of independent sentences that names no real trade-off. What is needed is not to remove the conflict but to write down the priority order: which principle outranks which. At the catalog institution, accessibility is non-negotiable, record first comes next, density ranks last. Once that order is written down, the filter panel decision becomes uncontested.
The fourth finding is a separate category: the decisions that record deletion asks for confirmation and that a suggestion list is shown in the empty state only stand against principles. This shows that the decisions’ rationale comes from somewhere outside the principles — the deletion confirmation comes from a data-loss risk, the suggestion list from a usability finding. These are legitimate rationales, but because they do not appear in the principles document, they need to be recorded. Otherwise, someone applying the principles will find these decisions “against the system” and remove them.
Tone of Voice Becomes a Contract
The final table takes up the second part of design language. Tone of voice is described in most documents with adjectives — clear, respectful, helpful — and these adjectives can reject no text. Converting it into a contract means reducing the adjectives to checkable rules: a maximum word count, which words are not used, whether every message proposes an action, whether exclamation marks are used.
Four of the seven texts carry a violation. The “borrow error” message contains three forbidden words: apology and pleading phrases carry no information, lengthen the message, and blur rather than reduce the impression that the error originated with the user. The “field validation” message both carries a forbidden word and does not say what to do: two violations in five words. The “empty shelf state” text exceeds the limit at twenty-four words.
The fourth violation, though, calls the rule itself into question. The message “Borrowed. Due back March 12.” is flagged because it proposes no action, but this message is a confirmation; it asks nothing of the user. Here the rule produces a false positive.
This is the general limit of a tone-of-voice audit. Rules do not know the text’s type. The fix is not to loosen the rule but to tie it to the type: the action-proposal requirement applies to error and empty-state messages, not to confirmation messages. When audit rules are not defined together with the text type they apply to, they either produce unnecessary warnings or miss real violations.
The Language’s Counterpart in Tokens
The final part of design language is brand expression, and here it ties back to the system’s numeric layer. A principle having a counterpart in the system means that principle constrains a family of tokens.
The “dense list” principle constrains which steps of the spacing scale get used in a list context. “Quiet interface” constrains the saturation choices of the color system and the number of accent roles. “Accessibility is non-negotiable” removes contrast thresholds from being a matter of preference.
Some principles, though, have no token counterpart: “reversibility” is not a number but a behavior rule, and it lives in the rule layer defined in an earlier lesson. This distinction has to be made, because trying to express, through a token, a principle that does not fit the token layer produces tokens that carry no meaning.
Brand expression is the sum of these two channels: constrained values in the numeric layer, written behaviors in the rule layer. An institution’s voice comes from both together; a color on its own, or a sentence pattern on its own, does not produce a brand.
Summary
- A design principle is a principle only if its opposite is a defensible position; a sentence whose opposite cannot be defended rules out no option and shows zero effect in the principle-decision matrix. An idle principle is dropped from the document; an unsupported decision either has no rationale or points to an unwritten principle, and the second case is the audit’s most productive output.
- A principle conflict is not a flaw, it is proof that the principles name real trade-offs; the fix is not to remove the conflict but to write down the priority order.
- Decisions that stand only against principles come from a different rationale, and if that rationale is not recorded, the decisions later get judged as against the system and removed.
- Tone of voice becomes a contract once it is reduced from adjectives to checkable rules: a word limit, a forbidden-word list, an action-proposal requirement, and a punctuation rule.
- Audit rules produce a false positive when they are not tied to text type; expecting an action proposal from a confirmation message is an example.
- A principle’s counterpart in the system is either constraining a family of tokens or being written into the rule layer; a principle that fits neither cannot be applied.
Next Step
The system’s founding decisions are complete at this point: scope was drawn, justification computed, the inventory extracted, a scale strategy chosen, and design language made checkable. What follows is these decisions’ counterpart living in the machine. The scale steps, color roles, and layout decisions need to turn into named values; which layer those names sit in, how they reference each other, and which references are forbidden is a separate architectural question. The next topic starts with tokens: its first lesson defines the three layers, sets the cross-layer reference rules, and checks the token graph for cycles, idle tokens, and layer violations.
To keep your progress and take notes, Log in
My notes
Log in to take notes.