@designtools/docs 0.2.1 → 0.2.3
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.
- package/CHANGELOG.md +12 -0
- package/dist/lib/handlers.d.ts +7 -0
- package/dist/lib/handlers.js +11 -0
- package/dist/next/pages.js +2 -24
- package/dist/styles.css +37 -54
- package/dist/workbench.js +2 -1
- package/package.json +1 -1
- package/src/lib/handlers.ts +14 -0
- package/src/next/pages.tsx +13 -74
- package/src/workbench.tsx +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @designtools/docs
|
|
2
2
|
|
|
3
|
+
## 0.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 62af842: The workbench no longer freezes on a component with a function prop it calls while rendering (Base UI's Meter and Progress, through `getAriaValueText`): only event handlers (`on…`) are logged to Actions, so logging can never re-render the component into calling it again. The overview's parts of the system are a typographic list: the name, why it exists and an arrow, with no glimpses or counts.
|
|
8
|
+
|
|
9
|
+
## 0.2.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- c4b61fb: The workbench no longer freezes on a component with a function prop it calls while rendering (Base UI's Meter and Progress, through `getAriaValueText`): only event handlers (`on…`) are logged to Actions now, so logging can never re-render the component into calling it again. The overview's section list loses its glimpses (colour dots, the logo, sample rules): each part is its name, its count and why it exists.
|
|
14
|
+
|
|
3
15
|
## 0.2.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PropEntry } from "./manifest-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The props the workbench logs to its Actions tab: event handlers only. A function prop that is not a
|
|
4
|
+
* handler (getAriaValueText, a formatter, a render function) is called while the component renders, and
|
|
5
|
+
* logging it re-renders the component, which calls it again, for ever.
|
|
6
|
+
*/
|
|
7
|
+
export declare function handlerNames(props: Record<string, PropEntry>): string[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const isFunction = (name, p) => /=>|^\(|Function|Handler/.test(p.type) || /^on[A-Z]/.test(name);
|
|
2
|
+
/**
|
|
3
|
+
* The props the workbench logs to its Actions tab: event handlers only. A function prop that is not a
|
|
4
|
+
* handler (getAriaValueText, a formatter, a render function) is called while the component renders, and
|
|
5
|
+
* logging it re-renders the component, which calls it again, for ever.
|
|
6
|
+
*/
|
|
7
|
+
export function handlerNames(props) {
|
|
8
|
+
return Object.entries(props)
|
|
9
|
+
.filter(([name, p]) => isFunction(name, p) && /^on[A-Z]/.test(name))
|
|
10
|
+
.map(([name]) => name);
|
|
11
|
+
}
|
package/dist/next/pages.js
CHANGED
|
@@ -8,7 +8,6 @@ import { Examples } from "../examples.js";
|
|
|
8
8
|
import { Glossary } from "../glossary.js";
|
|
9
9
|
import { Imagery } from "../imagery.js";
|
|
10
10
|
import { groupFamilies, slugOf } from "../lib/manifest.js";
|
|
11
|
-
import { StatusBadge } from "../lib/status.js";
|
|
12
11
|
import { LogoUsage } from "../logo-usage.js";
|
|
13
12
|
import { PageActions } from "../page-actions.js";
|
|
14
13
|
import { Pattern } from "../pattern.js";
|
|
@@ -112,69 +111,48 @@ function Overview({ site }) {
|
|
|
112
111
|
const count = families.reduce((n, g) => n + g.families.length, 0);
|
|
113
112
|
const brandPages = site.editorial.filter((p) => (p.section ?? "brand") === "brand");
|
|
114
113
|
const brandFirst = brandPages[0];
|
|
115
|
-
|
|
116
|
-
const example = products[0] ?? site.taxonomy.terms.find((t) => t.wrong?.length);
|
|
117
|
-
const fills = ["--primary", "--neutral", "--success", "--warning", "--destructive"].filter((n) => site.tokens.tokens.some((t) => t.name === n));
|
|
118
|
-
const share = config.adherence?.summary.share;
|
|
119
|
-
// each section of the system, why it exists, how much is in it, and a glimpse of it, live from the manifest
|
|
114
|
+
// each section of the system, and why it exists
|
|
120
115
|
const sections = [];
|
|
121
116
|
if (brandFirst || site.shows("logo"))
|
|
122
117
|
sections.push({
|
|
123
118
|
title: "Brand",
|
|
124
119
|
href: `${base}/${brandFirst?.slug ?? "brand/logo"}`,
|
|
125
120
|
why: "What the brand believes, how it sounds and how it looks, so every screen and sentence comes from the same place.",
|
|
126
|
-
count: `${brandPages.length + (site.assets.assets.some((a) => a.kind === "logo") ? 1 : 0)} pages`,
|
|
127
|
-
preview: config.logo ? _jsx("span", { className: "flex h-10 items-center [&_img]:h-8 [&_svg]:h-8", children: config.logo }) : null,
|
|
128
121
|
});
|
|
129
122
|
sections.push({
|
|
130
123
|
title: "Foundations",
|
|
131
124
|
href: `${base}/colour`,
|
|
132
125
|
why: "Colour, type and the scale, generated from the tokens and measured in both modes, so nothing is a guess.",
|
|
133
|
-
count: `${site.tokens.tokens.length} tokens`,
|
|
134
|
-
preview: (_jsxs("span", { className: "flex items-center gap-4", children: [_jsx("span", { className: "flex -space-x-1.5", children: fills.map((n) => (_jsx("span", { "aria-hidden": true, className: "size-8 rounded-full ring-2 ring-canvas", style: { background: `var(${n})` } }, n))) }), _jsx("span", { "aria-hidden": true, className: cx(display, "text-3xl leading-none tracking-tight"), children: "Aa" })] })),
|
|
135
126
|
});
|
|
136
127
|
if (site.rules.rules.length)
|
|
137
128
|
sections.push({
|
|
138
129
|
title: "Rules",
|
|
139
130
|
href: `${base}/rules`,
|
|
140
131
|
why: "The lines the brand and the interface hold, each written for people, with the check that proves it.",
|
|
141
|
-
count: `${site.rules.rules.length} rules, ${site.rules.rules.filter((r) => r.status === "confirmed").length} confirmed`,
|
|
142
|
-
preview: (_jsx("span", { className: "flex flex-col gap-1.5 text-sm", children: site.rules.rules
|
|
143
|
-
.filter((r) => r.kind === "brand")
|
|
144
|
-
.slice(0, 2)
|
|
145
|
-
.map((r) => (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx(StatusBadge, { status: r.status }), _jsx("span", { className: "truncate", children: r.title })] }, r.id))) })),
|
|
146
132
|
});
|
|
147
133
|
if (site.shows("components") && count)
|
|
148
134
|
sections.push({
|
|
149
135
|
title: "Components",
|
|
150
136
|
href: `${base}/components/${slugOf(families[0].families[0].head)}`,
|
|
151
137
|
why: "The real components the product is built from, each with when to use it, a live workbench and an accessibility report.",
|
|
152
|
-
count: `${count} components`,
|
|
153
|
-
preview: (_jsx("span", { className: "flex flex-wrap gap-1.5", children: families.slice(0, 6).map((g) => (_jsxs("span", { className: "inline-flex min-h-7 items-center rounded-md bg-muted px-2 text-xs", children: [g.category, " ", _jsx("span", { className: "ml-1.5 text-muted-foreground tabular-nums", children: g.families.length })] }, g.category))) })),
|
|
154
138
|
});
|
|
155
139
|
if (site.patterns.patterns.length)
|
|
156
140
|
sections.push({
|
|
157
141
|
title: "Patterns",
|
|
158
142
|
href: `${base}/patterns/${site.patterns.patterns[0].id}`,
|
|
159
143
|
why: "The screens the product keeps making, composed of the components, so a recurring problem is solved once.",
|
|
160
|
-
count: `${site.patterns.patterns.length} patterns`,
|
|
161
|
-
preview: _jsx("span", { className: "text-sm text-muted-foreground", children: site.patterns.patterns.slice(0, 3).map((p) => p.name).join(" · ") }),
|
|
162
144
|
});
|
|
163
145
|
if (site.shows("standards") && (config.baselines || config.adherence))
|
|
164
146
|
sections.push({
|
|
165
147
|
title: "Standards",
|
|
166
148
|
href: `${base}/standards`,
|
|
167
149
|
why: "The bar the product is held to, and how closely it follows the system today, reported on every change.",
|
|
168
|
-
count: share == null ? "Baselines agreed" : `${Math.round(share * 100)}% of the product on the system`,
|
|
169
|
-
preview: share == null ? null : (_jsxs("span", { className: "flex w-full max-w-56 items-center gap-3", children: [_jsx("span", { className: "h-1.5 flex-1 overflow-hidden rounded-full bg-muted", children: _jsx("span", { className: "block h-full rounded-full bg-canvas-foreground", style: { width: `${Math.round(share * 100)}%` } }) }), _jsxs("span", { className: "text-sm tabular-nums", children: [Math.round(share * 100), "%"] })] })),
|
|
170
150
|
});
|
|
171
151
|
if (site.shows("vocabulary") && site.taxonomy.terms.length)
|
|
172
152
|
sections.push({
|
|
173
153
|
title: "Vocabulary",
|
|
174
154
|
href: `${base}/vocabulary`,
|
|
175
155
|
why: "One name for each thing, and the names people reach for instead, so people and agents mean the same thing.",
|
|
176
|
-
count: `${site.taxonomy.terms.length} terms`,
|
|
177
|
-
preview: example ? (_jsxs("span", { className: "text-sm", children: ["Say ", _jsx("strong", { className: "font-semibold", children: example.name }), ", ", _jsx("span", { className: "text-muted-foreground line-through decoration-current/40", children: example.wrong?.[0] })] })) : null,
|
|
178
156
|
});
|
|
179
157
|
const loop = [
|
|
180
158
|
["Written once", "The components, tokens and rules live in the product's own code. Nobody keeps a second copy in a slide deck or a wiki."],
|
|
@@ -183,6 +161,6 @@ function Overview({ site }) {
|
|
|
183
161
|
["Checked", "Each rule names the check that proves it. Stale docs stop a commit; everything else is reported."],
|
|
184
162
|
["Measured", "A report on every change shows how closely the product follows the system. It informs the conversation; it never blocks the work."],
|
|
185
163
|
];
|
|
186
|
-
return (_jsxs(_Fragment, { children: [!config.hero && (_jsx(DocsHeader, { title: site.title, lead: config.lead ?? "The brand and the design system in one place, for the people who make the product and the agents that build it with them.", children: _jsx(PageActions, { basePath: base }) })), _jsx(DocsSection, { title: "What's here, and why", lead: "Each part of the system has one job. Together they mean the product, its people and its agents work from the same source.", children: _jsx("ul", { "data-slot": "overview-sections", className: "
|
|
164
|
+
return (_jsxs(_Fragment, { children: [!config.hero && (_jsx(DocsHeader, { title: site.title, lead: config.lead ?? "The brand and the design system in one place, for the people who make the product and the agents that build it with them.", children: _jsx(PageActions, { basePath: base }) })), _jsx(DocsSection, { title: "What's here, and why", lead: "Each part of the system has one job. Together they mean the product, its people and its agents work from the same source.", children: _jsx("ul", { "data-slot": "overview-sections", className: "flex flex-col border-b border-border", children: sections.map((sec) => (_jsx("li", { className: "border-t border-border", children: _jsxs(Link, { href: sec.href, className: "group grid items-baseline gap-x-10 gap-y-2 py-6 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring md:grid-cols-[13rem_minmax(0,1fr)_auto]", children: [_jsx("span", { className: cx(display, "text-2xl leading-snug tracking-tight underline-offset-4 group-hover:underline"), children: sec.title }), _jsx("span", { className: "max-w-2xl text-base leading-relaxed text-muted-foreground", children: sec.why }), _jsx(ArrowUpRight, { "aria-hidden": true, className: "hidden size-(--dt-size-sm) translate-y-0.5 self-start text-muted-foreground transition duration-(--dt-duration-base) ease-(--dt-ease-out) group-hover:translate-x-1 group-hover:-translate-y-0.5 group-hover:text-canvas-foreground md:mt-1.5 md:block" })] }) }, sec.title))) }) }), config.overview?.agentic !== false && (_jsxs(DocsSection, { title: "Why this is agentic", lead: config.overview?.agenticLead ??
|
|
187
165
|
"A design system used to be a document people were asked to follow. This one is the source the product, its people and its AI agents all work from, and it checks itself.", children: [_jsx("ol", { "data-slot": "overview-loop", className: "grid gap-x-6 gap-y-8 sm:grid-cols-2 xl:grid-cols-5", children: loop.map(([title, body], i) => (_jsxs("li", { className: "relative flex flex-col gap-3 xl:pr-2", children: [_jsxs("span", { className: "flex items-center gap-3", children: [_jsx("span", { className: "grid size-8 shrink-0 place-items-center rounded-full bg-canvas-foreground text-sm font-medium text-canvas tabular-nums", children: i + 1 }), i < loop.length - 1 && _jsx("span", { "aria-hidden": true, className: "hidden h-px flex-1 bg-border xl:block" })] }), _jsx("span", { className: "text-lg leading-snug tracking-tight", children: title }), _jsx("span", { className: "text-sm leading-relaxed text-muted-foreground", children: body })] }, title))) }), _jsxs("p", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-sm text-muted-foreground", children: ["See it the way an agent does:", _jsxs("a", { href: `${base}.md`, className: "inline-flex items-center gap-1 font-medium text-canvas-foreground underline underline-offset-4 hover:decoration-2", children: ["this page as markdown ", _jsx(ArrowUpRight, { "aria-hidden": true, className: "size-3.5" })] })] })] })), _jsx(DocsFooter, { provenance: config.provenance })] }));
|
|
188
166
|
}
|
package/dist/styles.css
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
--tw-rotate-z: initial;
|
|
11
11
|
--tw-skew-x: initial;
|
|
12
12
|
--tw-skew-y: initial;
|
|
13
|
-
--tw-space-x-reverse: 0;
|
|
14
13
|
--tw-divide-y-reverse: 0;
|
|
15
14
|
--tw-border-style: solid;
|
|
16
15
|
--tw-gradient-position: initial;
|
|
@@ -630,10 +629,6 @@
|
|
|
630
629
|
margin-left: .25rem;
|
|
631
630
|
}
|
|
632
631
|
|
|
633
|
-
:where([data-designtools]) .ml-1\.5:not([data-docs-content] *), .ml-1\.5:where([data-designtools]):not([data-docs-content] *) {
|
|
634
|
-
margin-left: .375rem;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
632
|
:where([data-designtools]) .ml-3:not([data-docs-content] *), .ml-3:where([data-designtools]):not([data-docs-content] *) {
|
|
638
633
|
margin-left: .75rem;
|
|
639
634
|
}
|
|
@@ -783,10 +778,6 @@
|
|
|
783
778
|
height: .125rem;
|
|
784
779
|
}
|
|
785
780
|
|
|
786
|
-
:where([data-designtools]) .h-1\.5:not([data-docs-content] *), .h-1\.5:where([data-designtools]):not([data-docs-content] *) {
|
|
787
|
-
height: .375rem;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
781
|
:where([data-designtools]) .h-2:not([data-docs-content] *), .h-2:where([data-designtools]):not([data-docs-content] *) {
|
|
791
782
|
height: .5rem;
|
|
792
783
|
}
|
|
@@ -903,10 +894,6 @@
|
|
|
903
894
|
min-height: 2.25rem;
|
|
904
895
|
}
|
|
905
896
|
|
|
906
|
-
:where([data-designtools]) .min-h-10:not([data-docs-content] *), .min-h-10:where([data-designtools]):not([data-docs-content] *) {
|
|
907
|
-
min-height: 2.5rem;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
897
|
:where([data-designtools]) .min-h-11:not([data-docs-content] *), .min-h-11:where([data-designtools]):not([data-docs-content] *) {
|
|
911
898
|
min-height: 2.75rem;
|
|
912
899
|
}
|
|
@@ -1027,10 +1014,6 @@
|
|
|
1027
1014
|
max-width: 7rem;
|
|
1028
1015
|
}
|
|
1029
1016
|
|
|
1030
|
-
:where([data-designtools]) .max-w-56:not([data-docs-content] *), .max-w-56:where([data-designtools]):not([data-docs-content] *) {
|
|
1031
|
-
max-width: 14rem;
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
1017
|
:where([data-designtools]) .max-w-64:not([data-docs-content] *), .max-w-64:where([data-designtools]):not([data-docs-content] *) {
|
|
1035
1018
|
max-width: 16rem;
|
|
1036
1019
|
}
|
|
@@ -1117,6 +1100,11 @@
|
|
|
1117
1100
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1118
1101
|
}
|
|
1119
1102
|
|
|
1103
|
+
:where([data-designtools]) .translate-y-0\.5:not([data-docs-content] *), .translate-y-0\.5:where([data-designtools]):not([data-docs-content] *) {
|
|
1104
|
+
--tw-translate-y: calc(.25rem * .5);
|
|
1105
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1120
1108
|
:where([data-designtools]) .transform:not([data-docs-content] *), .transform:where([data-designtools]):not([data-docs-content] *) {
|
|
1121
1109
|
transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
|
|
1122
1110
|
}
|
|
@@ -1345,12 +1333,6 @@
|
|
|
1345
1333
|
column-gap: 3rem;
|
|
1346
1334
|
}
|
|
1347
1335
|
|
|
1348
|
-
:where([data-designtools]) :where(.-space-x-1\.5 > :not(:last-child)):not([data-docs-content] *), :where(.-space-x-1\.5 > :not(:last-child)):where([data-designtools]):not([data-docs-content] *) {
|
|
1349
|
-
--tw-space-x-reverse: 0;
|
|
1350
|
-
margin-inline-start: calc(calc(.25rem * -1.5) * var(--tw-space-x-reverse));
|
|
1351
|
-
margin-inline-end: calc(calc(.25rem * -1.5) * calc(1 - var(--tw-space-x-reverse)));
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
1336
|
:where([data-designtools]) .gap-y-1:not([data-docs-content] *), .gap-y-1:where([data-designtools]):not([data-docs-content] *) {
|
|
1355
1337
|
row-gap: .25rem;
|
|
1356
1338
|
}
|
|
@@ -1403,6 +1385,10 @@
|
|
|
1403
1385
|
align-self: flex-end;
|
|
1404
1386
|
}
|
|
1405
1387
|
|
|
1388
|
+
:where([data-designtools]) .self-start:not([data-docs-content] *), .self-start:where([data-designtools]):not([data-docs-content] *) {
|
|
1389
|
+
align-self: flex-start;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1406
1392
|
:where([data-designtools]) .justify-self-end:not([data-docs-content] *), .justify-self-end:where([data-designtools]):not([data-docs-content] *) {
|
|
1407
1393
|
justify-self: flex-end;
|
|
1408
1394
|
}
|
|
@@ -1865,10 +1851,6 @@
|
|
|
1865
1851
|
padding-block: 1.5rem;
|
|
1866
1852
|
}
|
|
1867
1853
|
|
|
1868
|
-
:where([data-designtools]) .py-7:not([data-docs-content] *), .py-7:where([data-designtools]):not([data-docs-content] *) {
|
|
1869
|
-
padding-block: 1.75rem;
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
1854
|
:where([data-designtools]) .py-8:not([data-docs-content] *), .py-8:where([data-designtools]):not([data-docs-content] *) {
|
|
1873
1855
|
padding-block: 2rem;
|
|
1874
1856
|
}
|
|
@@ -2323,10 +2305,6 @@
|
|
|
2323
2305
|
text-underline-offset: 4px;
|
|
2324
2306
|
}
|
|
2325
2307
|
|
|
2326
|
-
:where([data-designtools]) .underline-offset-\[6px\]:not([data-docs-content] *), .underline-offset-\[6px\]:where([data-designtools]):not([data-docs-content] *) {
|
|
2327
|
-
text-underline-offset: 6px;
|
|
2328
|
-
}
|
|
2329
|
-
|
|
2330
2308
|
:where([data-designtools]) .opacity-0:not([data-docs-content] *), .opacity-0:where([data-designtools]):not([data-docs-content] *) {
|
|
2331
2309
|
opacity: 0;
|
|
2332
2310
|
}
|
|
@@ -2423,11 +2401,6 @@
|
|
|
2423
2401
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2424
2402
|
}
|
|
2425
2403
|
|
|
2426
|
-
:where([data-designtools]) .ring-2:not([data-docs-content] *), .ring-2:where([data-designtools]):not([data-docs-content] *) {
|
|
2427
|
-
--tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
2428
|
-
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2429
|
-
}
|
|
2430
|
-
|
|
2431
2404
|
:where([data-designtools]) .ring-\(--border\):not([data-docs-content] *), .ring-\(--border\):where([data-designtools]):not([data-docs-content] *) {
|
|
2432
2405
|
--tw-ring-color: var(--border);
|
|
2433
2406
|
}
|
|
@@ -2446,10 +2419,6 @@
|
|
|
2446
2419
|
--tw-ring-color: var(--border, #e2e4e8);
|
|
2447
2420
|
}
|
|
2448
2421
|
|
|
2449
|
-
:where([data-designtools]) .ring-canvas:not([data-docs-content] *), .ring-canvas:where([data-designtools]):not([data-docs-content] *) {
|
|
2450
|
-
--tw-ring-color: var(--canvas, #fff);
|
|
2451
|
-
}
|
|
2452
|
-
|
|
2453
2422
|
:where([data-designtools]) .ring-current\/15:not([data-docs-content] *), .ring-current\/15:where([data-designtools]):not([data-docs-content] *) {
|
|
2454
2423
|
--tw-ring-color: currentcolor;
|
|
2455
2424
|
}
|
|
@@ -2490,6 +2459,12 @@
|
|
|
2490
2459
|
backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
|
|
2491
2460
|
}
|
|
2492
2461
|
|
|
2462
|
+
:where([data-designtools]) .transition:not([data-docs-content] *), .transition:where([data-designtools]):not([data-docs-content] *) {
|
|
2463
|
+
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
|
|
2464
|
+
transition-timing-function: var(--tw-ease, cubic-bezier(.4, 0, .2, 1));
|
|
2465
|
+
transition-duration: var(--tw-duration, .15s);
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2493
2468
|
:where([data-designtools]) .transition-\[height\]:not([data-docs-content] *), .transition-\[height\]:where([data-designtools]):not([data-docs-content] *) {
|
|
2494
2469
|
transition-property: height;
|
|
2495
2470
|
transition-timing-function: var(--tw-ease, cubic-bezier(.4, 0, .2, 1));
|
|
@@ -2596,11 +2571,21 @@
|
|
|
2596
2571
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
2597
2572
|
}
|
|
2598
2573
|
|
|
2574
|
+
:where([data-designtools]) .group-hover\:translate-x-1:is(:where(.group):hover *):not([data-docs-content] *), .group-hover\:translate-x-1:is(:where(.group):hover *):where([data-designtools]):not([data-docs-content] *) {
|
|
2575
|
+
--tw-translate-x: .25rem;
|
|
2576
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2599
2579
|
:where([data-designtools]) .group-hover\:translate-x-full:is(:where(.group):hover *):not([data-docs-content] *), .group-hover\:translate-x-full:is(:where(.group):hover *):where([data-designtools]):not([data-docs-content] *) {
|
|
2600
2580
|
--tw-translate-x: 100%;
|
|
2601
2581
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
2602
2582
|
}
|
|
2603
2583
|
|
|
2584
|
+
:where([data-designtools]) .group-hover\:-translate-y-0\.5:is(:where(.group):hover *):not([data-docs-content] *), .group-hover\:-translate-y-0\.5:is(:where(.group):hover *):where([data-designtools]):not([data-docs-content] *) {
|
|
2585
|
+
--tw-translate-y: calc(.25rem * -.5);
|
|
2586
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2604
2589
|
:where([data-designtools]) .group-hover\:text-canvas-foreground:is(:where(.group):hover *):not([data-docs-content] *), .group-hover\:text-canvas-foreground:is(:where(.group):hover *):where([data-designtools]):not([data-docs-content] *) {
|
|
2605
2590
|
color: var(--canvas-foreground, #1c1f26);
|
|
2606
2591
|
}
|
|
@@ -2823,6 +2808,10 @@
|
|
|
2823
2808
|
outline-offset: 2px;
|
|
2824
2809
|
}
|
|
2825
2810
|
|
|
2811
|
+
:where([data-designtools]) .focus-visible\:outline-offset-4:focus-visible:not([data-docs-content] *), .focus-visible\:outline-offset-4:focus-visible:where([data-designtools]):not([data-docs-content] *) {
|
|
2812
|
+
outline-offset: 4px;
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2826
2815
|
:where([data-designtools]) .focus-visible\:outline-offset-\[-2px\]:focus-visible:not([data-docs-content] *), .focus-visible\:outline-offset-\[-2px\]:focus-visible:where([data-designtools]):not([data-docs-content] *) {
|
|
2827
2816
|
outline-offset: -2px;
|
|
2828
2817
|
}
|
|
@@ -3042,6 +3031,10 @@
|
|
|
3042
3031
|
grid-column-start: 4;
|
|
3043
3032
|
}
|
|
3044
3033
|
|
|
3034
|
+
:where([data-designtools]) .md\:mt-1\.5:not([data-docs-content] *), .md\:mt-1\.5:where([data-designtools]):not([data-docs-content] *) {
|
|
3035
|
+
margin-top: .375rem;
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3045
3038
|
:where([data-designtools]) .md\:block:not([data-docs-content] *), .md\:block:where([data-designtools]):not([data-docs-content] *) {
|
|
3046
3039
|
display: block;
|
|
3047
3040
|
}
|
|
@@ -3070,6 +3063,10 @@
|
|
|
3070
3063
|
grid-template-columns: 12rem minmax(0, 1fr);
|
|
3071
3064
|
}
|
|
3072
3065
|
|
|
3066
|
+
:where([data-designtools]) .md\:grid-cols-\[13rem_minmax\(0\,1fr\)_auto\]:not([data-docs-content] *), .md\:grid-cols-\[13rem_minmax\(0\,1fr\)_auto\]:where([data-designtools]):not([data-docs-content] *) {
|
|
3067
|
+
grid-template-columns: 13rem minmax(0, 1fr) auto;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3073
3070
|
:where([data-designtools]) .md\:grid-cols-\[minmax\(9rem\,0\.9fr\)_minmax\(0\,1\.6fr\)_minmax\(5rem\,0\.6fr\)_1\.25rem\]:not([data-docs-content] *), .md\:grid-cols-\[minmax\(9rem\,0\.9fr\)_minmax\(0\,1\.6fr\)_minmax\(5rem\,0\.6fr\)_1\.25rem\]:where([data-designtools]):not([data-docs-content] *) {
|
|
3074
3071
|
grid-template-columns: minmax(9rem, .9fr) minmax(0, 1.6fr) minmax(5rem, .6fr) 1.25rem;
|
|
3075
3072
|
}
|
|
@@ -3312,10 +3309,6 @@
|
|
|
3312
3309
|
font-size: .875em;
|
|
3313
3310
|
}
|
|
3314
3311
|
|
|
3315
|
-
:where([data-designtools]) .\[\&_img\]\:h-8 img:not([data-docs-content] *), .\[\&_img\]\:h-8 img:where([data-designtools]):not([data-docs-content] *) {
|
|
3316
|
-
height: 2rem;
|
|
3317
|
-
}
|
|
3318
|
-
|
|
3319
3312
|
:where([data-designtools]) .\[\&_pre\]\:break-words pre:not([data-docs-content] *), .\[\&_pre\]\:break-words pre:where([data-designtools]):not([data-docs-content] *) {
|
|
3320
3313
|
overflow-wrap: break-word;
|
|
3321
3314
|
}
|
|
@@ -3324,10 +3317,6 @@
|
|
|
3324
3317
|
white-space: pre-wrap;
|
|
3325
3318
|
}
|
|
3326
3319
|
|
|
3327
|
-
:where([data-designtools]) .\[\&_svg\]\:h-8 svg:not([data-docs-content] *), .\[\&_svg\]\:h-8 svg:where([data-designtools]):not([data-docs-content] *) {
|
|
3328
|
-
height: 2rem;
|
|
3329
|
-
}
|
|
3330
|
-
|
|
3331
3320
|
:where([data-designtools]) .\[\&\:\:-webkit-details-marker\]\:hidden:not([data-docs-content] *)::-webkit-details-marker, .\[\&\:\:-webkit-details-marker\]\:hidden:where([data-designtools]):not([data-docs-content] *)::-webkit-details-marker {
|
|
3332
3321
|
display: none;
|
|
3333
3322
|
}
|
|
@@ -3380,12 +3369,6 @@
|
|
|
3380
3369
|
inherits: false
|
|
3381
3370
|
}
|
|
3382
3371
|
|
|
3383
|
-
@property --tw-space-x-reverse {
|
|
3384
|
-
syntax: "*";
|
|
3385
|
-
inherits: false;
|
|
3386
|
-
initial-value: 0;
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
3372
|
@property --tw-divide-y-reverse {
|
|
3390
3373
|
syntax: "*";
|
|
3391
3374
|
inherits: false;
|
package/dist/workbench.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { handlerNames } from "./lib/handlers.js";
|
|
3
4
|
import { Live } from "./lib/live.js";
|
|
4
5
|
import { Tabs } from "@base-ui/react/tabs";
|
|
5
6
|
import { Toggle } from "@base-ui/react/toggle";
|
|
@@ -75,7 +76,7 @@ export function Workbench({ entry, props: base = {}, children: initialText = ent
|
|
|
75
76
|
const own = Object.entries(entry.props).filter(([name, p]) => !axisNames.has(name) && !PLUMBING.has(name) && p.deprecated === undefined);
|
|
76
77
|
// disabled is a pinned state ("Off"), not a prop control
|
|
77
78
|
const settable = own.filter(([name, p]) => !isFunction(name, p) && !p.from && name !== "disabled");
|
|
78
|
-
const handlers =
|
|
79
|
+
const handlers = handlerNames(Object.fromEntries(own));
|
|
79
80
|
const canDisable = "disabled" in entry.props;
|
|
80
81
|
const [variants, setVariants] = useState({});
|
|
81
82
|
const [values, setValues] = useState({});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@designtools/docs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Design system docs as a package: pages, navigation, search, a workbench per component, rules, patterns, brand pages and markdown for agents, generated from the @designtools/manifest and themed by your tokens. One Next adapter serves them inside your app or as a standalone site.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PropEntry } from "./manifest-types";
|
|
2
|
+
|
|
3
|
+
const isFunction = (name: string, p: PropEntry) => /=>|^\(|Function|Handler/.test(p.type) || /^on[A-Z]/.test(name);
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The props the workbench logs to its Actions tab: event handlers only. A function prop that is not a
|
|
7
|
+
* handler (getAriaValueText, a formatter, a render function) is called while the component renders, and
|
|
8
|
+
* logging it re-renders the component, which calls it again, for ever.
|
|
9
|
+
*/
|
|
10
|
+
export function handlerNames(props: Record<string, PropEntry>): string[] {
|
|
11
|
+
return Object.entries(props)
|
|
12
|
+
.filter(([name, p]) => isFunction(name, p) && /^on[A-Z]/.test(name))
|
|
13
|
+
.map(([name]) => name);
|
|
14
|
+
}
|
package/src/next/pages.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ArrowRight, ArrowUpRight } from "lucide-react";
|
|
2
2
|
import Link from "next/link";
|
|
3
|
-
import type { ReactNode } from "react";
|
|
4
3
|
import { cx, display } from "../lib/cx";
|
|
5
4
|
import { AdherenceSummary } from "../adherence-summary";
|
|
6
5
|
import { Anatomy } from "../anatomy";
|
|
@@ -307,112 +306,49 @@ function Overview({ site }: { site: Site }) {
|
|
|
307
306
|
const count = families.reduce((n, g) => n + g.families.length, 0);
|
|
308
307
|
const brandPages = site.editorial.filter((p) => (p.section ?? "brand") === "brand");
|
|
309
308
|
const brandFirst = brandPages[0];
|
|
310
|
-
const products = site.taxonomy.terms.filter((t) => t.kind === "product" && t.wrong?.length);
|
|
311
|
-
const example = products[0] ?? site.taxonomy.terms.find((t) => t.wrong?.length);
|
|
312
|
-
const fills = ["--primary", "--neutral", "--success", "--warning", "--destructive"].filter((n) =>
|
|
313
|
-
site.tokens.tokens.some((t) => t.name === n),
|
|
314
|
-
);
|
|
315
|
-
const share = config.adherence?.summary.share;
|
|
316
309
|
|
|
317
|
-
// each section of the system, why it exists
|
|
318
|
-
const sections: { title: string; href: string; why: string
|
|
310
|
+
// each section of the system, and why it exists
|
|
311
|
+
const sections: { title: string; href: string; why: string }[] = [];
|
|
319
312
|
if (brandFirst || site.shows("logo"))
|
|
320
313
|
sections.push({
|
|
321
314
|
title: "Brand",
|
|
322
315
|
href: `${base}/${brandFirst?.slug ?? "brand/logo"}`,
|
|
323
316
|
why: "What the brand believes, how it sounds and how it looks, so every screen and sentence comes from the same place.",
|
|
324
|
-
count: `${brandPages.length + (site.assets.assets.some((a) => a.kind === "logo") ? 1 : 0)} pages`,
|
|
325
|
-
preview: config.logo ? <span className="flex h-10 items-center [&_img]:h-8 [&_svg]:h-8">{config.logo}</span> : null,
|
|
326
317
|
});
|
|
327
318
|
sections.push({
|
|
328
319
|
title: "Foundations",
|
|
329
320
|
href: `${base}/colour`,
|
|
330
321
|
why: "Colour, type and the scale, generated from the tokens and measured in both modes, so nothing is a guess.",
|
|
331
|
-
count: `${site.tokens.tokens.length} tokens`,
|
|
332
|
-
preview: (
|
|
333
|
-
<span className="flex items-center gap-4">
|
|
334
|
-
<span className="flex -space-x-1.5">
|
|
335
|
-
{fills.map((n) => (
|
|
336
|
-
<span key={n} aria-hidden className="size-8 rounded-full ring-2 ring-canvas" style={{ background: `var(${n})` }} />
|
|
337
|
-
))}
|
|
338
|
-
</span>
|
|
339
|
-
<span aria-hidden className={cx(display, "text-3xl leading-none tracking-tight")}>
|
|
340
|
-
Aa
|
|
341
|
-
</span>
|
|
342
|
-
</span>
|
|
343
|
-
),
|
|
344
322
|
});
|
|
345
323
|
if (site.rules.rules.length)
|
|
346
324
|
sections.push({
|
|
347
325
|
title: "Rules",
|
|
348
326
|
href: `${base}/rules`,
|
|
349
327
|
why: "The lines the brand and the interface hold, each written for people, with the check that proves it.",
|
|
350
|
-
count: `${site.rules.rules.length} rules, ${site.rules.rules.filter((r) => r.status === "confirmed").length} confirmed`,
|
|
351
|
-
preview: (
|
|
352
|
-
<span className="flex flex-col gap-1.5 text-sm">
|
|
353
|
-
{site.rules.rules
|
|
354
|
-
.filter((r) => r.kind === "brand")
|
|
355
|
-
.slice(0, 2)
|
|
356
|
-
.map((r) => (
|
|
357
|
-
<span key={r.id} className="flex items-center gap-2">
|
|
358
|
-
<StatusBadge status={r.status} />
|
|
359
|
-
<span className="truncate">{r.title}</span>
|
|
360
|
-
</span>
|
|
361
|
-
))}
|
|
362
|
-
</span>
|
|
363
|
-
),
|
|
364
328
|
});
|
|
365
329
|
if (site.shows("components") && count)
|
|
366
330
|
sections.push({
|
|
367
331
|
title: "Components",
|
|
368
332
|
href: `${base}/components/${slugOf(families[0].families[0].head)}`,
|
|
369
333
|
why: "The real components the product is built from, each with when to use it, a live workbench and an accessibility report.",
|
|
370
|
-
count: `${count} components`,
|
|
371
|
-
preview: (
|
|
372
|
-
<span className="flex flex-wrap gap-1.5">
|
|
373
|
-
{families.slice(0, 6).map((g) => (
|
|
374
|
-
<span key={g.category} className="inline-flex min-h-7 items-center rounded-md bg-muted px-2 text-xs">
|
|
375
|
-
{g.category} <span className="ml-1.5 text-muted-foreground tabular-nums">{g.families.length}</span>
|
|
376
|
-
</span>
|
|
377
|
-
))}
|
|
378
|
-
</span>
|
|
379
|
-
),
|
|
380
334
|
});
|
|
381
335
|
if (site.patterns.patterns.length)
|
|
382
336
|
sections.push({
|
|
383
337
|
title: "Patterns",
|
|
384
338
|
href: `${base}/patterns/${site.patterns.patterns[0].id}`,
|
|
385
339
|
why: "The screens the product keeps making, composed of the components, so a recurring problem is solved once.",
|
|
386
|
-
count: `${site.patterns.patterns.length} patterns`,
|
|
387
|
-
preview: <span className="text-sm text-muted-foreground">{site.patterns.patterns.slice(0, 3).map((p) => p.name).join(" · ")}</span>,
|
|
388
340
|
});
|
|
389
341
|
if (site.shows("standards") && (config.baselines || config.adherence))
|
|
390
342
|
sections.push({
|
|
391
343
|
title: "Standards",
|
|
392
344
|
href: `${base}/standards`,
|
|
393
345
|
why: "The bar the product is held to, and how closely it follows the system today, reported on every change.",
|
|
394
|
-
count: share == null ? "Baselines agreed" : `${Math.round(share * 100)}% of the product on the system`,
|
|
395
|
-
preview:
|
|
396
|
-
share == null ? null : (
|
|
397
|
-
<span className="flex w-full max-w-56 items-center gap-3">
|
|
398
|
-
<span className="h-1.5 flex-1 overflow-hidden rounded-full bg-muted">
|
|
399
|
-
<span className="block h-full rounded-full bg-canvas-foreground" style={{ width: `${Math.round(share * 100)}%` }} />
|
|
400
|
-
</span>
|
|
401
|
-
<span className="text-sm tabular-nums">{Math.round(share * 100)}%</span>
|
|
402
|
-
</span>
|
|
403
|
-
),
|
|
404
346
|
});
|
|
405
347
|
if (site.shows("vocabulary") && site.taxonomy.terms.length)
|
|
406
348
|
sections.push({
|
|
407
349
|
title: "Vocabulary",
|
|
408
350
|
href: `${base}/vocabulary`,
|
|
409
351
|
why: "One name for each thing, and the names people reach for instead, so people and agents mean the same thing.",
|
|
410
|
-
count: `${site.taxonomy.terms.length} terms`,
|
|
411
|
-
preview: example ? (
|
|
412
|
-
<span className="text-sm">
|
|
413
|
-
Say <strong className="font-semibold">{example.name}</strong>, <span className="text-muted-foreground line-through decoration-current/40">{example.wrong?.[0]}</span>
|
|
414
|
-
</span>
|
|
415
|
-
) : null,
|
|
416
352
|
});
|
|
417
353
|
|
|
418
354
|
const loop = [
|
|
@@ -432,16 +368,19 @@ function Overview({ site }: { site: Site }) {
|
|
|
432
368
|
)}
|
|
433
369
|
|
|
434
370
|
<DocsSection title="What's here, and why" lead="Each part of the system has one job. Together they mean the product, its people and its agents work from the same source.">
|
|
435
|
-
<ul data-slot="overview-sections" className="
|
|
371
|
+
<ul data-slot="overview-sections" className="flex flex-col border-b border-border">
|
|
436
372
|
{sections.map((sec) => (
|
|
437
373
|
<li key={sec.title} className="border-t border-border">
|
|
438
|
-
<Link
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
</span>
|
|
443
|
-
<span className="max-w-
|
|
444
|
-
|
|
374
|
+
<Link
|
|
375
|
+
href={sec.href}
|
|
376
|
+
className="group grid items-baseline gap-x-10 gap-y-2 py-6 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring md:grid-cols-[13rem_minmax(0,1fr)_auto]"
|
|
377
|
+
>
|
|
378
|
+
<span className={cx(display, "text-2xl leading-snug tracking-tight underline-offset-4 group-hover:underline")}>{sec.title}</span>
|
|
379
|
+
<span className="max-w-2xl text-base leading-relaxed text-muted-foreground">{sec.why}</span>
|
|
380
|
+
<ArrowUpRight
|
|
381
|
+
aria-hidden
|
|
382
|
+
className="hidden size-(--dt-size-sm) translate-y-0.5 self-start text-muted-foreground transition duration-(--dt-duration-base) ease-(--dt-ease-out) group-hover:translate-x-1 group-hover:-translate-y-0.5 group-hover:text-canvas-foreground md:mt-1.5 md:block"
|
|
383
|
+
/>
|
|
445
384
|
</Link>
|
|
446
385
|
</li>
|
|
447
386
|
))}
|
package/src/workbench.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { handlerNames } from "./lib/handlers";
|
|
3
4
|
import { Live } from "./lib/live";
|
|
4
5
|
import { Tabs } from "@base-ui/react/tabs";
|
|
5
6
|
import { Toggle } from "@base-ui/react/toggle";
|
|
@@ -133,7 +134,7 @@ export function Workbench({
|
|
|
133
134
|
const own = Object.entries(entry.props).filter(([name, p]) => !axisNames.has(name) && !PLUMBING.has(name) && p.deprecated === undefined);
|
|
134
135
|
// disabled is a pinned state ("Off"), not a prop control
|
|
135
136
|
const settable = own.filter(([name, p]) => !isFunction(name, p) && !p.from && name !== "disabled");
|
|
136
|
-
const handlers =
|
|
137
|
+
const handlers = handlerNames(Object.fromEntries(own));
|
|
137
138
|
const canDisable = "disabled" in entry.props;
|
|
138
139
|
|
|
139
140
|
const [variants, setVariants] = useState<Record<string, string>>({});
|