@designtools/docs 0.1.0 → 0.2.0

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 (55) hide show
  1. package/CHANGELOG.md +10 -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 +932 -743
  30. package/dist/swatches.js +10 -4
  31. package/dist/variant-matrix.js +11 -6
  32. package/dist/voice-terms.js +6 -5
  33. package/dist/workbench.js +2 -1
  34. package/package.json +1 -1
  35. package/src/anatomy.tsx +6 -1
  36. package/src/glossary.tsx +39 -40
  37. package/src/index.ts +2 -1
  38. package/src/lib/live.tsx +15 -0
  39. package/src/lib/lookup.tsx +3 -2
  40. package/src/lib/status.tsx +3 -3
  41. package/src/lib/terms.tsx +53 -0
  42. package/src/next/config.ts +25 -4
  43. package/src/next/index.tsx +3 -0
  44. package/src/next/markdown.ts +1 -1
  45. package/src/next/pages.tsx +172 -59
  46. package/src/next/prose.tsx +16 -6
  47. package/src/pattern.tsx +42 -37
  48. package/src/playground.tsx +7 -2
  49. package/src/rule.tsx +108 -59
  50. package/src/shell.tsx +30 -16
  51. package/src/styles.css +4 -2
  52. package/src/swatches.tsx +68 -57
  53. package/src/variant-matrix.tsx +63 -80
  54. package/src/voice-terms.tsx +20 -29
  55. package/src/workbench.tsx +6 -3
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { Live } from "./lib/live";
3
4
  import { Grid3x3, Moon, Sun } from "lucide-react";
4
5
  import { type ReactNode, useEffect, useState } from "react";
5
6
  import { cx } from "./lib/cx";
@@ -36,9 +37,11 @@ export function VariantMatrix({
36
37
 
37
38
  const content = children ?? entry.name;
38
39
  const render = (extra: Record<string, string>) => (
39
- <Component {...props} {...coerce(extra)}>
40
- {content}
41
- </Component>
40
+ <Live>
41
+ <Component {...props} {...coerce(extra)}>
42
+ {content}
43
+ </Component>
44
+ </Live>
42
45
  );
43
46
  const [rows, cols, ...rest] = axes;
44
47
  const toggle = (
@@ -51,26 +54,28 @@ export function VariantMatrix({
51
54
  );
52
55
 
53
56
  return (
54
- <div data-slot="variant-matrix" className="flex flex-col gap-6">
55
- {cols ? (
56
- <Frame>
57
- <Toolbar>
58
- <span className="flex items-center gap-2 pl-2 font-mono text-xs text-muted-foreground">
59
- <Grid3x3 aria-hidden className="size-(--dt-size-xs)" />
60
- {rows.name} × {cols.name}
61
- </span>
62
- {toggle}
63
- </Toolbar>
64
- <div data-docs-stage="" data-theme={theme} className="overflow-x-auto bg-canvas text-canvas-foreground" tabIndex={0} role="region" aria-label="Variants">
57
+ <Frame data-slot="variant-matrix">
58
+ <Toolbar>
59
+ <span className="flex items-center gap-2 pl-2 font-mono text-xs text-muted-foreground">
60
+ <Grid3x3 aria-hidden className="size-(--dt-size-xs)" />
61
+ {cols ? `${rows.name} × ${cols.name}` : rows.name}
62
+ {rest.length > 0 && `, ${rest.map((a) => a.name).join(", ")}`}
63
+ </span>
64
+ {toggle}
65
+ </Toolbar>
66
+ {/* one stage: the matrix, any further axes and the states, separated by space rather than rules */}
67
+ <div data-docs-stage="" data-theme={theme} className="flex flex-col gap-12 bg-canvas px-6 py-8 text-canvas-foreground sm:px-8">
68
+ {cols ? (
69
+ <div className="overflow-x-auto" tabIndex={0} role="region" aria-label="Variants">
65
70
  <table className="w-full border-collapse text-sm">
66
71
  <caption className="sr-only">
67
72
  {entry.name}: {rows.name} by {cols.name}
68
73
  </caption>
69
74
  <thead>
70
- <tr className="border-b border-border">
75
+ <tr>
71
76
  <th scope="col" className="w-0 p-0" />
72
77
  {cols.options.map((c) => (
73
- <th key={c.name} scope="col" title={c.description} className="px-4 py-3 text-center font-mono text-xs font-medium text-muted-foreground">
78
+ <th key={c.name} scope="col" title={c.description} className="px-4 pb-4 text-center font-mono text-xs font-normal text-muted-foreground">
74
79
  <OptionName axis={cols} option={c.name} />
75
80
  </th>
76
81
  ))}
@@ -78,12 +83,12 @@ export function VariantMatrix({
78
83
  </thead>
79
84
  <tbody>
80
85
  {rows.options.map((r) => (
81
- <tr key={r.name} className="border-b border-border last:border-b-0">
82
- <th scope="row" title={r.description} className="border-r border-border px-4 py-5 text-left font-mono text-xs font-medium whitespace-nowrap text-muted-foreground">
86
+ <tr key={r.name}>
87
+ <th scope="row" title={r.description} className="py-4 pr-6 text-left font-mono text-xs font-normal whitespace-nowrap text-muted-foreground">
83
88
  <OptionName axis={rows} option={r.name} />
84
89
  </th>
85
90
  {cols.options.map((c) => (
86
- <td key={c.name} data-slot="variant-cell" className="px-4 py-5 text-center align-middle">
91
+ <td key={c.name} data-slot="variant-cell" className="px-4 py-4 text-center align-middle">
87
92
  <span className="inline-flex justify-center">{render({ [rows.name]: r.name, [cols.name]: c.name })}</span>
88
93
  </td>
89
94
  ))}
@@ -92,15 +97,25 @@ export function VariantMatrix({
92
97
  </tbody>
93
98
  </table>
94
99
  </div>
95
- </Frame>
96
- ) : (
97
- <AxisRow axis={rows} render={render} theme={theme} toggle={toggle} />
98
- )}
99
- {rest.map((axis) => (
100
- <AxisRow key={axis.name} axis={axis} render={render} theme={theme} toggle={toggle} />
101
- ))}
102
- <States render={render} theme={theme} toggle={toggle} canDisable={"disabled" in entry.props} />
103
- </div>
100
+ ) : (
101
+ <AxisRow axis={rows} render={render} />
102
+ )}
103
+ {rest.map((axis) => (
104
+ <AxisRow key={axis.name} axis={axis} render={render} />
105
+ ))}
106
+ <States render={render} canDisable={"disabled" in entry.props} />
107
+ </div>
108
+ </Frame>
109
+ );
110
+ }
111
+
112
+ /** A titled row of figures inside the variants stage. */
113
+ function Group({ title, slot, children }: { title: string; slot: string; children: ReactNode }) {
114
+ return (
115
+ <section data-slot={slot} className="flex flex-col gap-5">
116
+ <h3 className="font-mono text-xs text-muted-foreground">{title}</h3>
117
+ <div className="flex flex-wrap items-end gap-x-10 gap-y-6">{children}</div>
118
+ </section>
104
119
  );
105
120
  }
106
121
 
@@ -109,17 +124,7 @@ export function VariantMatrix({
109
124
  * pressed and disabled, pinned without a pointer or a keyboard, so states are
110
125
  * reviewed side by side rather than by mousing over each.
111
126
  */
112
- function States({
113
- render,
114
- theme,
115
- toggle,
116
- canDisable,
117
- }: {
118
- render: (extra: Record<string, string>) => ReactNode;
119
- theme?: "light" | "dark";
120
- toggle: ReactNode;
121
- canDisable: boolean;
122
- }) {
127
+ function States({ render, canDisable }: { render: (extra: Record<string, string>) => ReactNode; canDisable: boolean }) {
123
128
  useEffect(() => installPseudoStates(), []);
124
129
  const states: { name: string; pseudo?: string; extra?: Record<string, string> }[] = [
125
130
  { name: "rest" },
@@ -129,51 +134,29 @@ function States({
129
134
  ...(canDisable ? [{ name: "disabled", extra: { disabled: "true" } }] : []),
130
135
  ];
131
136
  return (
132
- <Frame data-slot="variant-states">
133
- <Toolbar>
134
- <span className="pl-2 font-mono text-xs text-muted-foreground">state</span>
135
- {toggle}
136
- </Toolbar>
137
- <div data-docs-stage="" data-theme={theme} className="flex flex-wrap items-end justify-center gap-x-10 gap-y-6 bg-canvas px-6 py-8 text-canvas-foreground">
138
- {states.map((s) => (
139
- <figure key={s.name} className="flex flex-col items-center gap-3">
140
- <div data-pseudo={s.pseudo}>{render(s.extra ?? {})}</div>
141
- <figcaption className="font-mono text-xs text-muted-foreground">{s.name}</figcaption>
142
- </figure>
143
- ))}
144
- </div>
145
- </Frame>
137
+ <Group title="state" slot="variant-states">
138
+ {states.map((s) => (
139
+ <figure key={s.name} className="flex flex-col items-center gap-3">
140
+ <div data-pseudo={s.pseudo}>{render(s.extra ?? {})}</div>
141
+ <figcaption className="font-mono text-xs text-muted-foreground">{s.name}</figcaption>
142
+ </figure>
143
+ ))}
144
+ </Group>
146
145
  );
147
146
  }
148
147
 
149
- function AxisRow({
150
- axis,
151
- render,
152
- theme,
153
- toggle,
154
- }: {
155
- axis: VariantAxis;
156
- render: (extra: Record<string, string>) => ReactNode;
157
- theme?: "light" | "dark";
158
- toggle: ReactNode;
159
- }) {
148
+ function AxisRow({ axis, render }: { axis: VariantAxis; render: (extra: Record<string, string>) => ReactNode }) {
160
149
  return (
161
- <Frame data-slot="variant-axis">
162
- <Toolbar>
163
- <span className="pl-2 font-mono text-xs text-muted-foreground">{axis.name}</span>
164
- {toggle}
165
- </Toolbar>
166
- <div data-docs-stage="" data-theme={theme} className="flex flex-wrap items-end justify-center gap-x-10 gap-y-6 bg-canvas px-6 py-8 text-canvas-foreground">
167
- {axis.options.map((o) => (
168
- <figure key={o.name} className="flex flex-col items-center gap-3">
169
- {render({ [axis.name]: o.name })}
170
- <figcaption className="font-mono text-xs text-muted-foreground" title={o.description}>
171
- <OptionName axis={axis} option={o.name} />
172
- </figcaption>
173
- </figure>
174
- ))}
175
- </div>
176
- </Frame>
150
+ <Group title={axis.name} slot="variant-axis">
151
+ {axis.options.map((o) => (
152
+ <figure key={o.name} className="flex flex-col items-center gap-3">
153
+ {render({ [axis.name]: o.name })}
154
+ <figcaption className="font-mono text-xs text-muted-foreground" title={o.description}>
155
+ <OptionName axis={axis} option={o.name} />
156
+ </figcaption>
157
+ </figure>
158
+ ))}
159
+ </Group>
177
160
  );
178
161
  }
179
162
 
@@ -1,5 +1,6 @@
1
1
  import type { TermEntry } from "./lib/manifest-types";
2
- import { inline } from "./lib/text";
2
+ import { TermHead, TermRow } from "./lib/terms";
3
+ import { DocsSection } from "./shell";
3
4
 
4
5
  /** The words to use, beside the ones not to: the product's words first, then the system's names that have wrong forms. */
5
6
  export function VoiceTerms({ terms }: { terms: TermEntry[] }) {
@@ -7,40 +8,30 @@ export function VoiceTerms({ terms }: { terms: TermEntry[] }) {
7
8
  const system = terms.filter((t) => t.kind !== "product" && t.wrong?.length);
8
9
  if (product.length + system.length === 0) return <p className="text-sm text-muted-foreground">No terms yet. Add them to the taxonomy file.</p>;
9
10
  return (
10
- <div data-slot="voice-terms" className="flex flex-col gap-12">
11
- {product.length > 0 && <Group title="In the product" terms={product} />}
12
- {system.length > 0 && <Group title="In the system" terms={system} />}
13
- </div>
11
+ <>
12
+ {product.length > 0 && (
13
+ <DocsSection title="In the product" lead="The words the product uses with the people it serves, in copy, on screens and in emails.">
14
+ <Terms terms={product} />
15
+ </DocsSection>
16
+ )}
17
+ {system.length > 0 && (
18
+ <DocsSection title="In the system" lead="The names the design system gives its parts, and the ones people reach for instead.">
19
+ <Terms terms={system} />
20
+ </DocsSection>
21
+ )}
22
+ </>
14
23
  );
15
24
  }
16
25
 
17
- function Group({ title, terms }: { title: string; terms: TermEntry[] }) {
26
+ function Terms({ terms }: { terms: TermEntry[] }) {
18
27
  return (
19
- <section className="flex flex-col gap-2">
20
- <h3 className="text-xs font-medium tracking-wide text-muted-foreground uppercase">{title}</h3>
21
- <dl className="grid gap-x-12 sm:grid-cols-2">
28
+ <div data-slot="voice-terms">
29
+ <TermHead />
30
+ <dl>
22
31
  {terms.map((t) => (
23
- <div key={`${t.kind}:${t.name}`} data-slot="term" className="flex flex-col gap-1.5 border-t border-border py-5">
24
- <dt className="text-3xl tracking-tight">
25
- {t.name}
26
- <span className="sr-only">, say this</span>
27
- </dt>
28
- {(t.wrong ?? []).length > 0 && (
29
- <dd className="flex flex-wrap gap-x-3 text-base text-muted-foreground">
30
- <span className="sr-only">not </span>
31
- {(t.wrong ?? []).map((w) => (
32
- <s key={w} className="decoration-destructive decoration-2">
33
- {w}
34
- </s>
35
- ))}
36
- </dd>
37
- )}
38
- {(t.note || t.kind !== "product") && (
39
- <dd className="text-sm text-muted-foreground">{t.note ? inline(t.note) : `The ${t.kind}'s name in the code.`}</dd>
40
- )}
41
- </div>
32
+ <TermRow key={`${t.kind}:${t.name}`} term={t} />
42
33
  ))}
43
34
  </dl>
44
- </section>
35
+ </div>
45
36
  );
46
37
  }
package/src/workbench.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { Live } from "./lib/live";
3
4
  import { Tabs } from "@base-ui/react/tabs";
4
5
  import { Toggle } from "@base-ui/react/toggle";
5
6
  import { ToggleGroup } from "@base-ui/react/toggle-group";
@@ -267,9 +268,11 @@ export function Workbench({
267
268
  const dotted = view.bg === "canvas";
268
269
 
269
270
  const node = (
270
- <Component {...base} {...logged} {...chosen}>
271
- {content ?? (text || undefined)}
272
- </Component>
271
+ <Live>
272
+ <Component {...base} {...logged} {...chosen}>
273
+ {content ?? (text || undefined)}
274
+ </Component>
275
+ </Live>
273
276
  );
274
277
  const scope = [
275
278
  entry.name,