@designtools/docs 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +24 -2
  3. package/dist/anatomy.js +2 -1
  4. package/dist/cli.js +1 -1
  5. package/dist/glossary.d.ts +1 -1
  6. package/dist/glossary.js +13 -6
  7. package/dist/index.d.ts +2 -1
  8. package/dist/index.js +2 -1
  9. package/dist/lib/live.d.ts +10 -0
  10. package/dist/lib/live.js +10 -0
  11. package/dist/lib/lookup.js +3 -2
  12. package/dist/lib/status.d.ts +2 -3
  13. package/dist/lib/terms.d.ts +15 -0
  14. package/dist/lib/terms.js +20 -0
  15. package/dist/next/config.d.ts +24 -4
  16. package/dist/next/index.d.ts +3 -0
  17. package/dist/next/index.js +3 -0
  18. package/dist/next/markdown.js +1 -1
  19. package/dist/next/pages.js +82 -16
  20. package/dist/next/prose.d.ts +2 -2
  21. package/dist/next/prose.js +6 -4
  22. package/dist/pattern.d.ts +4 -1
  23. package/dist/pattern.js +11 -8
  24. package/dist/playground.js +1 -1
  25. package/dist/rule.d.ts +9 -5
  26. package/dist/rule.js +14 -9
  27. package/dist/shell.d.ts +4 -1
  28. package/dist/shell.js +13 -11
  29. package/dist/styles.css +961 -754
  30. package/dist/swatches.d.ts +7 -6
  31. package/dist/swatches.js +50 -16
  32. package/dist/variant-matrix.js +11 -6
  33. package/dist/voice-terms.js +6 -5
  34. package/dist/workbench.js +2 -1
  35. package/package.json +1 -1
  36. package/src/anatomy.tsx +6 -1
  37. package/src/glossary.tsx +39 -40
  38. package/src/index.ts +2 -1
  39. package/src/lib/live.tsx +15 -0
  40. package/src/lib/lookup.tsx +3 -2
  41. package/src/lib/status.tsx +3 -3
  42. package/src/lib/terms.tsx +53 -0
  43. package/src/next/config.ts +25 -4
  44. package/src/next/index.tsx +3 -0
  45. package/src/next/markdown.ts +1 -1
  46. package/src/next/pages.tsx +172 -59
  47. package/src/next/prose.tsx +16 -6
  48. package/src/pattern.tsx +42 -37
  49. package/src/playground.tsx +7 -2
  50. package/src/rule.tsx +108 -59
  51. package/src/shell.tsx +30 -16
  52. package/src/styles.css +4 -2
  53. package/src/swatches.tsx +189 -120
  54. package/src/variant-matrix.tsx +63 -80
  55. package/src/voice-terms.tsx +20 -29
  56. package/src/workbench.tsx +6 -3
package/src/rule.tsx CHANGED
@@ -1,24 +1,26 @@
1
1
  "use client";
2
2
 
3
+ import { Live } from "./lib/live";
3
4
  import { Bot, Eye, Hash, ShieldCheck } from "lucide-react";
4
- import type { ReactNode } from "react";
5
+ import { type ReactNode, useState } from "react";
5
6
  import { CodeView } from "./code-view";
6
7
  import { cx } from "./lib/cx";
7
8
  import { ruleMarkdown } from "./lib/markdown";
8
9
  import type { RuleEntry } from "./lib/manifest-types";
9
10
  import { StatusBadge } from "./lib/status";
10
11
  import { inline, Prose } from "./lib/text";
11
- import { Eyebrow, Segmented, SegmentedList, SegmentedPanel, Stage } from "./lib/ui";
12
+ import { Eyebrow } from "./lib/ui";
12
13
 
13
14
  const CHECK: Record<string, string> = { test: "Tested", lint: "Linted", audit: "Audited", manual: "Checked by a person" };
14
15
 
15
16
  /**
16
- * One rule, brand or interface, written for people: the statement set large, the
17
- * line it draws, what it applies to and the check that proves it, then why. A
18
- * switch shows the same rule as an agent reads it. Pass a demonstration as
19
- * children where the rule needs persuading; it is shown on a stage.
17
+ * One rule, brand or interface, written for people. On a wide screen, its name, status and the check
18
+ * that proves it hold the left column while the right reads: the statement set large, the
19
+ * demonstration (pass it as children, for a rule that needs persuading), the facts, then why. A small
20
+ * switch shows the same rule as an agent reads it.
20
21
  */
21
22
  export function Rule({ rule, children }: { rule: RuleEntry; children?: ReactNode }) {
23
+ const [view, setView] = useState<"people" | "agents">("people");
22
24
  const chips = (items: string[], mono = false) => (
23
25
  <span className="flex flex-wrap gap-1.5">
24
26
  {items.map((t) => (
@@ -33,46 +35,75 @@ export function Rule({ rule, children }: { rule: RuleEntry; children?: ReactNode
33
35
  if (rule.appliesTo?.length) facts.push(["Applies to", chips(rule.appliesTo)]);
34
36
  if (rule.exceptions?.length) facts.push(["Exceptions", <span key="e">{rule.exceptions.join("; ")}</span>]);
35
37
  if (rule.tokens?.length) facts.push(["Tokens", chips(rule.tokens, true)]);
38
+ const toggle = (value: "people" | "agents", label: string, Icon: typeof Eye) => (
39
+ <button
40
+ type="button"
41
+ aria-pressed={view === value}
42
+ onClick={() => setView(value)}
43
+ className={cx(
44
+ "inline-flex min-h-8 cursor-pointer items-center gap-1.5 rounded-md px-2 text-xs font-medium transition-colors duration-(--dt-duration-fast) focus-visible:outline-2 focus-visible:outline-ring",
45
+ view === value ? "bg-muted text-canvas-foreground" : "text-muted-foreground hover:text-canvas-foreground",
46
+ )}
47
+ >
48
+ <Icon aria-hidden className="size-3.5" />
49
+ {label}
50
+ </button>
51
+ );
36
52
 
37
53
  return (
38
- <article id={rule.id} data-slot="rule" className="scroll-mt-24 border-t border-border pt-8">
39
- <Segmented defaultValue="rendered">
40
- <header className="flex flex-wrap items-start justify-between gap-3">
41
- <div className="flex min-w-0 flex-col gap-2">
42
- <span className="flex flex-wrap items-center gap-2">
43
- <StatusBadge status={rule.status} />
44
- <span className="text-xs font-medium text-muted-foreground">{rule.kind === "brand" ? "Brand rule" : "Interface rule"}</span>
54
+ <article id={rule.id} data-slot="rule" className="grid scroll-mt-24 gap-x-12 gap-y-6 border-t border-border pt-10 xl:grid-cols-[15rem_minmax(0,1fr)]">
55
+ <header data-slot="rule-header" className="flex flex-col gap-4 xl:sticky xl:top-24 xl:self-start">
56
+ <div className="flex flex-col gap-2.5">
57
+ <span className="text-xs font-medium text-muted-foreground">{rule.kind === "brand" ? "Brand rule" : "Interface rule"}</span>
58
+ <h3 className="group flex items-start gap-1 text-2xl leading-tight tracking-tight">
59
+ {rule.title}
60
+ <a
61
+ href={`#${rule.id}`}
62
+ aria-label={`Link to ${rule.title}`}
63
+ className="relative mt-0.5 inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground opacity-0 group-hover:opacity-100 hover:bg-muted focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-ring after:absolute after:-inset-2 after:content-['']"
64
+ >
65
+ <Hash aria-hidden className="size-4" />
66
+ </a>
67
+ </h3>
68
+ <span>
69
+ <StatusBadge status={rule.status} />
70
+ </span>
71
+ </div>
72
+ {rule.check && (
73
+ <p data-slot="rule-check" className="flex items-start gap-2 text-sm">
74
+ <ShieldCheck aria-hidden className="mt-0.5 size-(--dt-size-xs) shrink-0 text-muted-foreground" />
75
+ <span className="flex flex-col gap-0.5">
76
+ <span className="font-medium">
77
+ {CHECK[rule.check.kind] ?? rule.check.kind}
78
+ {rule.check.ref && (
79
+ <>
80
+ {" "}
81
+ by <code className="font-mono text-xs">{rule.check.ref}</code>
82
+ </>
83
+ )}
84
+ </span>
85
+ {rule.check.description && <span className="text-muted-foreground">{inline(rule.check.description)}</span>}
45
86
  </span>
46
- <h3 className="group flex items-center gap-2 text-3xl tracking-tight">
47
- {rule.title}
48
- <a
49
- href={`#${rule.id}`}
50
- aria-label={`Link to ${rule.title}`}
51
- className="relative inline-flex size-7 items-center justify-center rounded-md text-muted-foreground opacity-0 group-hover:opacity-100 hover:bg-muted focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-ring after:absolute after:-inset-2 after:content-['']"
52
- >
53
- <Hash aria-hidden className="size-4" />
54
- </a>
55
- </h3>
56
- </div>
57
- <SegmentedList
58
- label={`${rule.title}, two ways`}
59
- items={[
60
- { value: "rendered", label: "For people", icon: Eye },
61
- { value: "agent", label: "For agents", icon: Bot },
62
- ]}
63
- />
64
- </header>
65
- <SegmentedPanel value="rendered" className="flex flex-col gap-6 pt-4">
66
- <p data-slot="rule-statement" className="max-w-3xl text-xl leading-snug tracking-tight">
87
+ </p>
88
+ )}
89
+ <div role="group" aria-label={`Read ${rule.title}`} className="-ml-2 flex gap-1">
90
+ {toggle("people", "For people", Eye)}
91
+ {toggle("agents", "For agents", Bot)}
92
+ </div>
93
+ </header>
94
+
95
+ {view === "people" ? (
96
+ <div data-slot="rule-body" className="flex min-w-0 flex-col gap-8">
97
+ <p data-slot="rule-statement" className="max-w-3xl text-2xl leading-snug tracking-tight">
67
98
  {inline(rule.statement)}
68
99
  </p>
69
100
  {children && (
70
- <div data-slot="rule-demonstration" className="overflow-hidden rounded-xl border border-border">
71
- <Stage className="min-h-40">{children}</Stage>
101
+ <div data-slot="rule-demonstration" data-docs-stage="" className="flex min-h-40 items-center justify-center rounded-2xl bg-muted/60 p-8 sm:p-10">
102
+ <Live>{children}</Live>
72
103
  </div>
73
104
  )}
74
105
  {facts.length > 0 && (
75
- <dl className="grid gap-x-10 gap-y-5 sm:grid-cols-2">
106
+ <dl className="grid max-w-3xl gap-x-10 gap-y-4 sm:grid-cols-2">
76
107
  {facts.map(([term, detail]) => (
77
108
  <div key={term} className="flex flex-col gap-1.5">
78
109
  <dt className="text-xs font-medium text-muted-foreground">{term}</dt>
@@ -81,36 +112,54 @@ export function Rule({ rule, children }: { rule: RuleEntry; children?: ReactNode
81
112
  ))}
82
113
  </dl>
83
114
  )}
84
- {rule.check && (
85
- <div className="flex items-start gap-2.5 text-sm">
86
- <ShieldCheck aria-hidden className="mt-0.5 size-(--dt-size-xs) shrink-0 text-muted-foreground" />
87
- <p className="flex flex-col gap-0.5">
88
- <span className="font-medium">
89
- {CHECK[rule.check.kind] ?? rule.check.kind}
90
- {rule.check.ref && (
91
- <>
92
- {" "}
93
- by <code className="font-mono text-xs">{rule.check.ref}</code>
94
- </>
95
- )}
96
- </span>
97
- {rule.check.description && <span className="text-muted-foreground">{inline(rule.check.description)}</span>}
98
- </p>
99
- </div>
100
- )}
101
115
  {rule.rationale && (
102
116
  <div className="flex max-w-3xl flex-col gap-2">
103
117
  <Eyebrow>Why</Eyebrow>
104
- <div className="flex flex-col gap-2 text-sm text-muted-foreground">
118
+ <div className="flex flex-col gap-2 text-base leading-relaxed text-muted-foreground">
105
119
  <Prose text={rule.rationale} />
106
120
  </div>
107
121
  </div>
108
122
  )}
109
- </SegmentedPanel>
110
- <SegmentedPanel value="agent" className="pt-4">
123
+ </div>
124
+ ) : (
125
+ <div className="min-w-0">
111
126
  <CodeView code={ruleMarkdown(rule)} lang="markdown" label={`${rule.id}.md`} wrap />
112
- </SegmentedPanel>
113
- </Segmented>
127
+ </div>
128
+ )}
114
129
  </article>
115
130
  );
116
131
  }
132
+
133
+ /** Every rule on one screen, a line each, linking to the rule: what it is, how settled, how it is checked. */
134
+ export function RuleIndex({ rules }: { rules: RuleEntry[] }) {
135
+ return (
136
+ <div data-slot="rule-index" className="-mx-1 overflow-x-auto px-1">
137
+ <table className="w-full min-w-[34rem] border-collapse text-left text-sm">
138
+ <thead>
139
+ <tr className="text-xs text-muted-foreground">
140
+ <th scope="col" className="pr-4 pb-3 font-medium">Rule</th>
141
+ <th scope="col" className="px-4 pb-3 font-medium">Kind</th>
142
+ <th scope="col" className="px-4 pb-3 font-medium">Status</th>
143
+ <th scope="col" className="pb-3 pl-4 font-medium">Checked</th>
144
+ </tr>
145
+ </thead>
146
+ <tbody>
147
+ {rules.map((r) => (
148
+ <tr key={r.id} className="border-t border-border">
149
+ <th scope="row" className="py-3 pr-4 font-normal">
150
+ <a href={`#${r.id}`} className="font-medium underline-offset-4 hover:underline focus-visible:outline-2 focus-visible:outline-ring">
151
+ {r.title}
152
+ </a>
153
+ </th>
154
+ <td className="px-4 py-3 text-muted-foreground capitalize">{r.kind}</td>
155
+ <td className="px-4 py-3">
156
+ <StatusBadge status={r.status} />
157
+ </td>
158
+ <td className="py-3 pl-4 text-muted-foreground">{r.check ? (CHECK[r.check.kind] ?? r.check.kind) : "Not yet"}</td>
159
+ </tr>
160
+ ))}
161
+ </tbody>
162
+ </table>
163
+ </div>
164
+ );
165
+ }
package/src/shell.tsx CHANGED
@@ -6,7 +6,9 @@ import { ArrowLeft, ArrowRight, BookOpen, ChevronRight, Component, Gauge, House,
6
6
  import Link from "next/link";
7
7
  import { usePathname } from "next/navigation";
8
8
  import { createContext, type ReactNode, useContext, useEffect, useMemo, useState } from "react";
9
+ import { Live } from "./lib/live";
9
10
  import { accent, cx, display, target } from "./lib/cx";
11
+ import { type Status, StatusBadge } from "./lib/status";
10
12
  import { groupFamilies, slugOf } from "./lib/manifest";
11
13
  import type { ComponentsManifest, PatternsManifest, RulesManifest, TaxonomyManifest } from "./lib/manifest-types";
12
14
  import { searchIndex } from "./lib/search";
@@ -157,7 +159,7 @@ export function DocsShell({
157
159
  <Link href={basePath} data-slot="docs-title" className={cx(target, "flex min-w-0 items-center gap-3 rounded-md focus-visible:outline-2 focus-visible:outline-ring")}>
158
160
  {logo && (
159
161
  <span data-slot="docs-logo" className="shrink-0">
160
- {logo}
162
+ <Live>{logo}</Live>
161
163
  </span>
162
164
  )}
163
165
  <span className={cx(logo ? "sr-only" : "truncate text-base font-semibold tracking-tight")}>{title}</span>
@@ -207,7 +209,7 @@ export function DocsShell({
207
209
  <X aria-hidden className="size-(--dt-size-sm)" />
208
210
  </Dialog.Close>
209
211
  </div>
210
- <Nav sections={sections} current={current} title={title} />
212
+ <Nav sections={sections} current={current} title={title} className="pt-4" />
211
213
  {themeSwitch && (
212
214
  <div className="flex items-center justify-between gap-3 border-t border-border px-4 py-3">
213
215
  <span className="text-xs font-medium text-muted-foreground">Appearance</span>
@@ -224,7 +226,7 @@ export function DocsShell({
224
226
 
225
227
  {hero && current === basePath && (
226
228
  <div data-slot="docs-hero" className="w-full">
227
- {hero}
229
+ <Live>{hero}</Live>
228
230
  </div>
229
231
  )}
230
232
  <div className="mx-auto flex w-full max-w-[90rem] gap-16 px-5 pt-12 pb-20 sm:px-8 lg:px-12 lg:pt-20 xl:px-20">
@@ -244,7 +246,7 @@ const iconButton =
244
246
  "inline-flex size-(--docs-target,2.75rem) shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-ring";
245
247
 
246
248
  /** The sections, each a link or a fold that opens where the current page is. */
247
- function Nav({ sections, current, title }: { sections: Section[]; current: string; title: string }) {
249
+ function Nav({ sections, current, title, className }: { sections: Section[]; current: string; title: string; className?: string }) {
248
250
  const holds = (s: Section) => s.groups.some((g) => g.links.some((l) => l.href === current || l.children?.some((c) => c.href === current)));
249
251
  const [open, setOpen] = useState<Record<string, boolean>>(() => Object.fromEntries(sections.map((s) => [s.id, holds(s)])));
250
252
  // moving to a page opens its section; nothing closes on its own
@@ -255,7 +257,7 @@ function Nav({ sections, current, title }: { sections: Section[]; current: strin
255
257
  }, [current, sections]);
256
258
 
257
259
  return (
258
- <nav aria-label={title} data-slot="docs-nav" className="min-h-0 flex-1 overflow-y-auto px-3 pb-4 text-sm">
260
+ <nav aria-label={title} data-slot="docs-nav" className={cx("min-h-0 flex-1 overflow-y-auto px-3 pb-4 text-sm", className)}>
259
261
  <ul className="flex flex-col gap-0.5">
260
262
  {sections.map((s) => {
261
263
  const Icon = s.icon;
@@ -294,7 +296,7 @@ function Nav({ sections, current, title }: { sections: Section[]; current: strin
294
296
  {s.groups.map((g, i) => (
295
297
  <div key={g.heading ?? i} className="flex flex-col">
296
298
  {g.heading && (
297
- <p data-slot="docs-nav-heading" className="px-2.5 pt-1 pb-1 text-xs font-medium tracking-wide text-muted-foreground uppercase">
299
+ <p data-slot="docs-nav-heading" className="px-2.5 pt-3 pb-1.5 text-[0.6875rem] font-semibold tracking-[0.08em] text-muted-foreground uppercase first:pt-1">
298
300
  {g.heading}
299
301
  </p>
300
302
  )}
@@ -339,7 +341,7 @@ function NavLink({ link, current }: { link: DocsLink; current: string }) {
339
341
  data-slot="docs-nav-link"
340
342
  className={cx(
341
343
  target,
342
- "relative flex items-center rounded-md px-2.5 text-muted-foreground hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring",
344
+ "relative flex items-center rounded-md px-2.5 text-canvas-foreground/80 hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring",
343
345
  active && "bg-muted font-medium text-canvas-foreground",
344
346
  )}
345
347
  >
@@ -416,7 +418,7 @@ function Pager({ prev, next }: { prev?: DocsLink; next?: DocsLink }) {
416
418
  "group flex flex-col gap-1 rounded-lg border border-border p-5 transition-colors duration-(--dt-duration-fast) hover:bg-muted focus-visible:outline-2 focus-visible:outline-ring",
417
419
  );
418
420
  return (
419
- <nav aria-label="Previous and next" data-slot="docs-pager" className="grid gap-3 border-t border-border pt-10 sm:grid-cols-2">
421
+ <nav aria-label="Previous and next" data-slot="docs-pager" className="-mt-4 grid gap-3 sm:grid-cols-2 lg:-mt-8">
420
422
  {prev ? (
421
423
  <Link href={prev.href} className={card}>
422
424
  <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
@@ -448,24 +450,32 @@ export function DocsHeader({
448
450
  title,
449
451
  lead,
450
452
  eyebrow,
453
+ status,
451
454
  children,
452
455
  }: {
453
456
  title: string;
454
457
  lead?: string;
455
458
  /** Above the title. Defaults to the section the page sits in. */
456
459
  eyebrow?: string;
460
+ /** How settled the thing the page documents is, beside the eyebrow: a pattern's status. */
461
+ status?: Status;
457
462
  /** The page's actions, beside the title: `PageActions`. */
458
463
  children?: ReactNode;
459
464
  }) {
460
465
  const { section } = useContext(DocsPage);
461
466
  const over = eyebrow ?? (section && section !== title ? section : undefined);
462
467
  return (
463
- <header data-slot="docs-header" className="flex flex-col gap-6 border-b border-border pb-12 lg:pb-16">
468
+ <header data-slot="docs-header" className="flex flex-col gap-6">
464
469
  <div className="flex flex-wrap items-center justify-between gap-4">
465
- {over ? (
466
- <p data-slot="docs-eyebrow" className="text-xs font-medium tracking-[var(--tracking-widest,0.16em)] text-muted-foreground uppercase">
467
- {over}
468
- </p>
470
+ {over || status ? (
471
+ <span className="flex flex-wrap items-center gap-3">
472
+ {over && (
473
+ <p data-slot="docs-eyebrow" className="text-xs font-medium tracking-[var(--tracking-widest,0.16em)] text-muted-foreground uppercase">
474
+ {over}
475
+ </p>
476
+ )}
477
+ {status && <StatusBadge status={status} />}
478
+ </span>
469
479
  ) : (
470
480
  <span />
471
481
  )}
@@ -508,7 +518,11 @@ export function DocsFooter({
508
518
  }) {
509
519
  if (!provenance && !editorial && !source) return null;
510
520
  return (
511
- <footer data-slot="docs-footer" className="flex flex-wrap items-center gap-x-6 gap-y-2 text-xs text-muted-foreground">
521
+ // order-last: the page renders its footer before the shell adds the pager, and where a page comes from is the last thing on it
522
+ <footer
523
+ data-slot="docs-footer"
524
+ className="order-last -mt-8 flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border pt-6 text-xs text-muted-foreground lg:-mt-14"
525
+ >
512
526
  {(provenance || editorial) && (
513
527
  <p data-slot="docs-provenance" className="flex items-center gap-2">
514
528
  <span
@@ -539,11 +553,11 @@ export function DocsSection({ title, lead, children }: { title: string; lead?: s
539
553
  <section data-slot="docs-section" aria-labelledby={id} className="grid gap-x-10 gap-y-8 [counter-increment:docs-section] xl:grid-cols-[5rem_minmax(0,1fr)]">
540
554
  <span
541
555
  aria-hidden
542
- className="pt-2 font-mono text-xs tracking-[var(--tracking-widest,0.16em)] text-muted-foreground before:content-[counter(docs-section,decimal-leading-zero)]"
556
+ className="font-mono text-xs tracking-[var(--tracking-widest,0.16em)] text-muted-foreground [text-box:trim-both_cap_alphabetic] before:content-[counter(docs-section,decimal-leading-zero)]"
543
557
  />
544
558
  <div className="flex min-w-0 flex-col gap-10">
545
559
  <div className="flex flex-col gap-4">
546
- <h2 id={id} data-slot="docs-section-title" className={cx(display, "scroll-mt-24 text-4xl leading-[1.1] tracking-tight md:text-5xl")}>
560
+ <h2 id={id} data-slot="docs-section-title" className={cx(display, "scroll-mt-24 text-4xl leading-[1.1] tracking-tight [text-box:trim-both_cap_alphabetic] md:text-5xl")}>
547
561
  {title}
548
562
  </h2>
549
563
  {lead && <p className="max-w-2xl text-lg leading-relaxed text-muted-foreground">{lead}</p>}
package/src/styles.css CHANGED
@@ -1,7 +1,9 @@
1
1
  /*
2
2
  * The docs' styles, compiled at build and scoped to `[data-designtools]`, so they
3
- * style the docs and nothing else on the page, and add no specificity: a
4
- * project's own CSS always wins a tie.
3
+ * style the docs and nothing else on the page. They never match inside the
4
+ * project's own components shown in the docs (`Live`, `[data-docs-content]`), and
5
+ * on the docs' own elements they carry one attribute more than a project utility,
6
+ * so neither side's utilities leak into the other, whichever loads last.
5
7
  *
6
8
  * Themed by the project's own variables. Colours are @designtools/tokens'
7
9
  * semantic names (--canvas, --surface, --primary, …), so a project on our tokens