From 4521a19cb5bedeeb836323ed4a2ae13ffd2a3e76 Mon Sep 17 00:00:00 2001 From: xkxx Date: Thu, 8 Oct 2026 00:53:51 -0700 Subject: [PATCH] docs(spec): add Voice & Content Strategy section to DESIGN.md --- README.md | 5 +- docs/spec.md | 29 +++++++++- packages/cli/src/linter/index.test.ts | 53 +++++++++++++++++++ .../linter/linter/rules/section-order.test.ts | 2 +- packages/cli/src/linter/spec-config.yaml | 1 + packages/cli/src/linter/spec-gen/spec.mdx | 24 +++++++++ 6 files changed, 109 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ed855c52..45f00874 100644 --- a/README.md +++ b/README.md @@ -148,8 +148,9 @@ Sections use `##` headings. They can be omitted, but those present must appear i | 4 | Layout | Layout & Spacing | | 5 | Elevation & Depth | Elevation | | 6 | Shapes | | -| 7 | Components | | -| 8 | Do's and Don'ts | | +| 7 | Voice & Content Strategy | | +| 8 | Components | | +| 9 | Do's and Don'ts | | ### Component Tokens diff --git a/docs/spec.md b/docs/spec.md index 5995e548..cfdd4073 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -109,8 +109,9 @@ Every `DESIGN.md` follows the same structure. Sections can be omitted if they're 4. **Layout** (also: "Layout & Spacing") 5. **Elevation & Depth** (also: "Elevation") 6. **Shapes** -7. **Components** -8. **Do's and Don'ts** +7. **Voice & Content Strategy** +8. **Components** +9. **Do's and Don'ts** ### Prose and Tokens @@ -296,6 +297,30 @@ rounded: full: 9999px ``` +## Voice & Content Strategy + +This section defines how the product writes. Interface copy is part of the design system: inconsistent tense, capitalization, or terminology degrades visual cohesion just as clearly as inconsistent spacing does. This section is prose-only and covers: + +* **Tone of voice**: Two or three adjectives describing the brand voice, with a short explanation of what they sound like in practice and what they rule out. +* **Capitalization**: Sentence case or title case, applied consistently across headings, buttons, form labels, and menu items. +* **Terminology**: The product's canonical names for its own concepts and the synonyms to avoid. +* **Button and action labels**: The grammar of interactive labels (e.g., verb phrases naming the outcome rather than generic labels like "OK" or "Submit"). +* **Empty, loading, and error states**: What an empty list says, what an error message says, and whether an error suggests a specific next action. +* **Numbers, dates, and units**: Conventions for date/time formats, relative time, number rounding, and unit spacing. + +Example: + +```markdown +## Voice & Content Strategy + +- **Tone of voice:** Precise, calm, and utilitarian. Avoid exclamation marks, marketing hyperbole, and conversational filler. +- **Capitalization:** Sentence case applied consistently across all headings, buttons, form labels, and menu items. +- **Terminology:** Use "Workspace" (never "Project" or "Repo") and "Member" (never "User" or "Collaborator"). Pick one word per concept and keep it. +- **Button and action labels:** Use a verb phrase naming the outcome (e.g., "Save changes", "Create workspace"), never vague labels like "OK" or "Submit". +- **Empty, loading, and error states:** Empty states explain what belongs in the list and provide a direct creation CTA. Error messages state what failed and suggest a specific next action. +- **Numbers, dates, and units:** Format dates as `YYYY-MM-DD` in tables, use relative time ("3m ago") in activity feeds, and separate numeric values from units with a space (`16 px`). +``` + ## Components This section provides style guidance for component atoms within the design system. The following are common component types. Design systems are encouraged to define additional components relevant to their domain. diff --git a/packages/cli/src/linter/index.test.ts b/packages/cli/src/linter/index.test.ts index ba12e98b..7932dc47 100644 --- a/packages/cli/src/linter/index.test.ts +++ b/packages/cli/src/linter/index.test.ts @@ -163,4 +163,57 @@ motion: ); expect(unknownKeyFindings).toEqual([]); }); + + it('processes a DESIGN.md with a prose-only Voice & Content Strategy section in canonical order', () => { + const content = `--- +name: Daylight Prestige + +colors: + primary: "#1A1C1E" + +typography: + body-md: + fontFamily: Public Sans + fontSize: 16px + fontWeight: 400 + lineHeight: 1.6 +--- + +## Overview + +Editorial design system with high-contrast neutrals. + +## Colors + +Primary ink palette. + +## Typography + +Public Sans for body text. + +## Shapes + +Sharp 4px corner radius. + +## Voice & Content Strategy + +- **Tone of voice:** Precise, calm, and utilitarian. Avoid exclamation marks, marketing hyperbole, and conversational filler. +- **Capitalization:** Sentence case applied consistently across all headings, buttons, form labels, and menu items. +- **Terminology:** Use "Workspace" (never "Project" or "Repo") and "Member" (never "User" or "Collaborator"). Pick one word per concept and keep it. +- **Button and action labels:** Use a verb phrase naming the outcome (e.g., "Save changes", "Create workspace"), never vague labels like "OK" or "Submit". +- **Empty, loading, and error states:** Empty states explain what belongs in the list and provide a direct creation CTA. Error messages state what failed and suggest a specific next action. +- **Numbers, dates, and units:** Format dates as \`YYYY-MM-DD\` in tables, use relative time ("3m ago") in activity feeds, and separate numeric values from units with a space (\`16 px\`). + +## Components + +Core component library. +`; + + const result = lint(content); + + expect(result.summary.errors).toBe(0); + expect(result.designSystem.sections).toContain('Voice & Content Strategy'); + const orderFindings = result.findings.filter(f => f.rule === 'section-order'); + expect(orderFindings).toEqual([]); + }); }); diff --git a/packages/cli/src/linter/linter/rules/section-order.test.ts b/packages/cli/src/linter/linter/rules/section-order.test.ts index 4e94ebef..dd204fac 100644 --- a/packages/cli/src/linter/linter/rules/section-order.test.ts +++ b/packages/cli/src/linter/linter/rules/section-order.test.ts @@ -91,7 +91,7 @@ describe('sectionOrder', () => { it('should handle mixed aliases and canonical names', () => { const state = { - sections: ['Brand & Style', 'Colors', 'Typography', 'Layout & Spacing', 'Elevation & Depth', 'Shapes', 'Components'], + sections: ['Brand & Style', 'Colors', 'Typography', 'Layout & Spacing', 'Elevation & Depth', 'Shapes', 'Voice & Content Strategy', 'Components'], } as unknown as DesignSystemState; const findings = sectionOrder(state); diff --git a/packages/cli/src/linter/spec-config.yaml b/packages/cli/src/linter/spec-config.yaml index 6b1e90fd..7e50063d 100644 --- a/packages/cli/src/linter/spec-config.yaml +++ b/packages/cli/src/linter/spec-config.yaml @@ -59,6 +59,7 @@ sections: aliases: - Elevation - canonical: Shapes + - canonical: Voice & Content Strategy - canonical: Components - canonical: "Do's and Don'ts" diff --git a/packages/cli/src/linter/spec-gen/spec.mdx b/packages/cli/src/linter/spec-gen/spec.mdx index c9e417d6..31dd974e 100644 --- a/packages/cli/src/linter/spec-gen/spec.mdx +++ b/packages/cli/src/linter/spec-gen/spec.mdx @@ -228,6 +228,30 @@ rounded: full: 9999px ``` +## Voice & Content Strategy + +This section defines how the product writes. Interface copy is part of the design system: inconsistent tense, capitalization, or terminology degrades visual cohesion just as clearly as inconsistent spacing does. This section is prose-only and covers: + +- **Tone of voice**: Two or three adjectives describing the brand voice, with a short explanation of what they sound like in practice and what they rule out. +- **Capitalization**: Sentence case or title case, applied consistently across headings, buttons, form labels, and menu items. +- **Terminology**: The product's canonical names for its own concepts and the synonyms to avoid. +- **Button and action labels**: The grammar of interactive labels (e.g., verb phrases naming the outcome rather than generic labels like "OK" or "Submit"). +- **Empty, loading, and error states**: What an empty list says, what an error message says, and whether an error suggests a specific next action. +- **Numbers, dates, and units**: Conventions for date/time formats, relative time, number rounding, and unit spacing. + +Example: + +```markdown +## Voice & Content Strategy + +- **Tone of voice:** Precise, calm, and utilitarian. Avoid exclamation marks, marketing hyperbole, and conversational filler. +- **Capitalization:** Sentence case applied consistently across all headings, buttons, form labels, and menu items. +- **Terminology:** Use "Workspace" (never "Project" or "Repo") and "Member" (never "User" or "Collaborator"). Pick one word per concept and keep it. +- **Button and action labels:** Use a verb phrase naming the outcome (e.g., "Save changes", "Create workspace"), never vague labels like "OK" or "Submit". +- **Empty, loading, and error states:** Empty states explain what belongs in the list and provide a direct creation CTA. Error messages state what failed and suggest a specific next action. +- **Numbers, dates, and units:** Format dates as `YYYY-MM-DD` in tables, use relative time ("3m ago") in activity feeds, and separate numeric values from units with a space (`16 px`). +``` + ## Components This section provides style guidance for component atoms within the design system. The following are common component types. Design systems are encouraged to define additional components relevant to their domain.