baseline-foundry 0.1.3 → 0.1.4
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/README.md +568 -552
- package/config/experiments/ibm-plex-engine-smoke.json +115 -115
- package/config/experiments/ubuntu-engine-smoke.json +115 -115
- package/config/foundation-theme.json +110 -110
- package/config/tiers/app.json +116 -116
- package/config/tiers/documentation.json +116 -116
- package/config/tiers/editorial.json +116 -116
- package/config/tiers/os.json +116 -116
- package/dist/baseline-grid-overlay.js +43 -43
- package/dist/css-app-tier.js +73 -73
- package/dist/css-components/article-pagination.js +140 -140
- package/dist/css-components/button-actions.js +161 -161
- package/dist/css-components/cards-options.js +176 -176
- package/dist/css-components/chip-badge-status.js +158 -158
- package/dist/css-components/content-card.js +490 -490
- package/dist/css-components/control-row.js +14 -14
- package/dist/css-components/cta-figure-aspect.js +120 -120
- package/dist/css-components/document-navigation.js +390 -390
- package/dist/css-components/editorial-content.js +42 -42
- package/dist/css-components/icon.js +72 -72
- package/dist/css-components/interactive-feedback.js +217 -217
- package/dist/css-components/interactive-tables.js +155 -155
- package/dist/css-components/legacy-navigation.d.ts +9 -0
- package/dist/css-components/legacy-navigation.js +763 -0
- package/dist/css-components/linked-logo-site-layout.js +177 -177
- package/dist/css-components/list-tree.js +94 -94
- package/dist/css-components/logo-media.js +201 -201
- package/dist/css-components/navigation-layout.js +144 -144
- package/dist/css-components/panel.js +144 -144
- package/dist/css-components/search-box-and-filter.js +263 -263
- package/dist/css-components/sites-editorial-ports.js +243 -243
- package/dist/css-components/sites-foundation.js +146 -146
- package/dist/css-components/sites-rich-lists.js +344 -344
- package/dist/css-components/static-content-ports.js +182 -182
- package/dist/css-components/tab-section.js +82 -82
- package/dist/css-components/table.js +75 -75
- package/dist/css-components/tabs-choice-breadcrumbs.js +303 -303
- package/dist/css-components/tiered-list-equal-height-row.js +271 -271
- package/dist/css-components.js +1791 -2542
- package/dist/css-grid.js +172 -172
- package/dist/css.js +240 -240
- package/docs/publishing.md +30 -13
- package/package.json +119 -108
package/README.md
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
# Baseline Foundry
|
|
2
|
-
|
|
3
|
-
Lean baseline-aligned design system focused on:
|
|
4
|
-
|
|
5
|
-
- editorial typescale
|
|
6
|
-
- container-owned semantic spacing
|
|
7
|
-
- grid primitives
|
|
8
|
-
- page and section rhythm
|
|
9
|
-
- a small amount of demo/runtime support
|
|
10
|
-
|
|
11
|
-
This repo is the clean sibling to `portable-vertical-rhythm`.
|
|
12
|
-
That older package remains the compatibility line for `design-foundry`.
|
|
13
|
-
This repo is the forward-looking line: smaller, more versatile, and centered on baseline, prose flow, and grid rather than broad component parity.
|
|
14
|
-
|
|
15
|
-
## Workflow Map
|
|
16
|
-
|
|
17
|
-
- Always-on invariants and cold start: `AGENTS.md`
|
|
18
|
-
- Live state and handover: `AGENT-INBOX.md`
|
|
19
|
-
- Operational commands and source routing: `docs/agent-index.md`
|
|
20
|
-
- Cross-spec order and short backlog: `TODO.md`
|
|
21
|
-
- Spec catalog and status: `docs/specs.md`
|
|
22
|
-
- Durable architecture: `docs/architecture.md`
|
|
23
|
-
- Active feature intent, tasks, and evidence: `specs/<id>-<slug>/`
|
|
24
|
-
- Human async notes: `INBOX.md`
|
|
25
|
-
|
|
26
|
-
Spec Kit packages are the source of truth for feature work. Closed packages move
|
|
27
|
-
to `docs/spec-archive/`; Git is the chronological history.
|
|
28
|
-
|
|
29
|
-
## LLM Efficiency Notes
|
|
30
|
-
|
|
31
|
-
These habits matter more than prompt cleverness when you are using a coding agent in this repo.
|
|
32
|
-
|
|
33
|
-
- Pick one model per task. Model switches often invalidate caches and force the tool to reprocess the same context again.
|
|
34
|
-
- Keep permanent instructions short. Durable invariants belong in `AGENTS.md`;
|
|
35
|
-
task detail and evidence belong in one active Spec Kit package.
|
|
36
|
-
- Keep project memory in the repo, not only in chat, but give each fact one
|
|
37
|
-
owner. Avoid global status, roadmap, and history narratives.
|
|
38
|
-
- Prefer markdown, plain text, and lists over complex pages or dense tables when accuracy matters.
|
|
39
|
-
- Search in smaller passes instead of one giant query, then verify against the owning file or spec.
|
|
40
|
-
- Checkpoint and restart freely. Short resumable sessions are usually cheaper and more reliable than preserving one huge thread.
|
|
41
|
-
|
|
42
|
-
## Source Of Truth
|
|
43
|
-
|
|
44
|
-
When sources disagree, this repo follows:
|
|
45
|
-
|
|
46
|
-
1. Current user direction and the active local spec
|
|
47
|
-
2. `.specify/memory/constitution.md`
|
|
48
|
-
3. `AGENTS.md` and `docs/architecture.md`
|
|
49
|
-
4. Accepted archived local specs
|
|
50
|
-
5. External design references catalogued in `docs/specs.md`
|
|
51
|
-
6. Public README/API documentation
|
|
52
|
-
7. Undocumented local implementation details
|
|
53
|
-
|
|
54
|
-
Pragma and the Canonical official design system are related products, not BF
|
|
55
|
-
authorities. BF's container-owned spacing contract is an explicit local owner
|
|
56
|
-
decision recorded in the active spec and constitution.
|
|
57
|
-
|
|
58
|
-
## Linked Specs
|
|
59
|
-
|
|
60
|
-
See `docs/specs.md` for the concrete linked spec paths and the legacy/reference boundaries.
|
|
61
|
-
|
|
62
|
-
## Principles
|
|
63
|
-
|
|
64
|
-
See `AGENTS.md` and `docs/architecture.md` for the full set. Summary:
|
|
65
|
-
|
|
66
|
-
- Baseline alignment is non-negotiable.
|
|
67
|
-
- Semantic spacing is owned by nested stacks in editorial, documentation, app, and OS.
|
|
68
|
-
- Text keeps metric top-nudge and bottom-margin compensation for baseline alignment.
|
|
69
|
-
- OS is the fourth first-class built-in tier.
|
|
70
|
-
- Grid and layout primitives are small and composable.
|
|
71
|
-
- Dogfooding: demos use only `bf-*` classes.
|
|
72
|
-
|
|
73
|
-
For a longer write-up on empirical nudges, cap-unit alignment, raw metrics, and compensated metrics, see `docs/comparing-baseline-alignment-techniques.md`. Its visual companion lives at `demo/components/engine-illustration.html`.
|
|
74
|
-
|
|
75
|
-
## Output
|
|
76
|
-
|
|
77
|
-
Build output includes:
|
|
78
|
-
|
|
79
|
-
- `dist/styles.css`
|
|
80
|
-
- `dist/tokens.json`
|
|
81
|
-
- `dist/surfaces.json`
|
|
82
|
-
- `dist/experiments/ibm-plex-engine-smoke/styles.css`
|
|
83
|
-
- `dist/experiments/ibm-plex-engine-smoke/tokens.json`
|
|
84
|
-
- `dist/experiments/ibm-plex-engine-smoke/surfaces.json`
|
|
85
|
-
- `dist/tiers/editorial/styles.css`
|
|
86
|
-
- `dist/tiers/editorial/tokens.json`
|
|
87
|
-
- `dist/tiers/editorial/surfaces.json`
|
|
88
|
-
- `dist/tiers/documentation/styles.css`
|
|
89
|
-
- `dist/tiers/documentation/tokens.json`
|
|
90
|
-
- `dist/tiers/documentation/surfaces.json`
|
|
91
|
-
- `dist/tiers/app/styles.css`
|
|
92
|
-
- `dist/tiers/app/tokens.json`
|
|
93
|
-
- `dist/tiers/app/surfaces.json`
|
|
94
|
-
- `dist/tiers/os/styles.css`
|
|
95
|
-
- `dist/tiers/os/tokens.json`
|
|
96
|
-
- `dist/tiers/os/surfaces.json`
|
|
97
|
-
- `dist/presets/prose/styles.css`
|
|
98
|
-
- `dist/presets/prose/tokens.json`
|
|
99
|
-
- `dist/presets/prose/surfaces.json`
|
|
100
|
-
- `dist/presets/app-tier/styles.css`
|
|
101
|
-
- `dist/presets/app-tier/tokens.json`
|
|
102
|
-
- `dist/presets/app-tier/surfaces.json`
|
|
103
|
-
- `dist/index.js`
|
|
104
|
-
- `dist/build.js`
|
|
105
|
-
|
|
1
|
+
# Baseline Foundry
|
|
2
|
+
|
|
3
|
+
Lean baseline-aligned design system focused on:
|
|
4
|
+
|
|
5
|
+
- editorial typescale
|
|
6
|
+
- container-owned semantic spacing
|
|
7
|
+
- grid primitives
|
|
8
|
+
- page and section rhythm
|
|
9
|
+
- a small amount of demo/runtime support
|
|
10
|
+
|
|
11
|
+
This repo is the clean sibling to `portable-vertical-rhythm`.
|
|
12
|
+
That older package remains the compatibility line for `design-foundry`.
|
|
13
|
+
This repo is the forward-looking line: smaller, more versatile, and centered on baseline, prose flow, and grid rather than broad component parity.
|
|
14
|
+
|
|
15
|
+
## Workflow Map
|
|
16
|
+
|
|
17
|
+
- Always-on invariants and cold start: `AGENTS.md`
|
|
18
|
+
- Live state and handover: `AGENT-INBOX.md`
|
|
19
|
+
- Operational commands and source routing: `docs/agent-index.md`
|
|
20
|
+
- Cross-spec order and short backlog: `TODO.md`
|
|
21
|
+
- Spec catalog and status: `docs/specs.md`
|
|
22
|
+
- Durable architecture: `docs/architecture.md`
|
|
23
|
+
- Active feature intent, tasks, and evidence: `specs/<id>-<slug>/`
|
|
24
|
+
- Human async notes: `INBOX.md`
|
|
25
|
+
|
|
26
|
+
Spec Kit packages are the source of truth for feature work. Closed packages move
|
|
27
|
+
to `docs/spec-archive/`; Git is the chronological history.
|
|
28
|
+
|
|
29
|
+
## LLM Efficiency Notes
|
|
30
|
+
|
|
31
|
+
These habits matter more than prompt cleverness when you are using a coding agent in this repo.
|
|
32
|
+
|
|
33
|
+
- Pick one model per task. Model switches often invalidate caches and force the tool to reprocess the same context again.
|
|
34
|
+
- Keep permanent instructions short. Durable invariants belong in `AGENTS.md`;
|
|
35
|
+
task detail and evidence belong in one active Spec Kit package.
|
|
36
|
+
- Keep project memory in the repo, not only in chat, but give each fact one
|
|
37
|
+
owner. Avoid global status, roadmap, and history narratives.
|
|
38
|
+
- Prefer markdown, plain text, and lists over complex pages or dense tables when accuracy matters.
|
|
39
|
+
- Search in smaller passes instead of one giant query, then verify against the owning file or spec.
|
|
40
|
+
- Checkpoint and restart freely. Short resumable sessions are usually cheaper and more reliable than preserving one huge thread.
|
|
41
|
+
|
|
42
|
+
## Source Of Truth
|
|
43
|
+
|
|
44
|
+
When sources disagree, this repo follows:
|
|
45
|
+
|
|
46
|
+
1. Current user direction and the active local spec
|
|
47
|
+
2. `.specify/memory/constitution.md`
|
|
48
|
+
3. `AGENTS.md` and `docs/architecture.md`
|
|
49
|
+
4. Accepted archived local specs
|
|
50
|
+
5. External design references catalogued in `docs/specs.md`
|
|
51
|
+
6. Public README/API documentation
|
|
52
|
+
7. Undocumented local implementation details
|
|
53
|
+
|
|
54
|
+
Pragma and the Canonical official design system are related products, not BF
|
|
55
|
+
authorities. BF's container-owned spacing contract is an explicit local owner
|
|
56
|
+
decision recorded in the active spec and constitution.
|
|
57
|
+
|
|
58
|
+
## Linked Specs
|
|
59
|
+
|
|
60
|
+
See `docs/specs.md` for the concrete linked spec paths and the legacy/reference boundaries.
|
|
61
|
+
|
|
62
|
+
## Principles
|
|
63
|
+
|
|
64
|
+
See `AGENTS.md` and `docs/architecture.md` for the full set. Summary:
|
|
65
|
+
|
|
66
|
+
- Baseline alignment is non-negotiable.
|
|
67
|
+
- Semantic spacing is owned by nested stacks in editorial, documentation, app, and OS.
|
|
68
|
+
- Text keeps metric top-nudge and bottom-margin compensation for baseline alignment.
|
|
69
|
+
- OS is the fourth first-class built-in tier.
|
|
70
|
+
- Grid and layout primitives are small and composable.
|
|
71
|
+
- Dogfooding: demos use only `bf-*` classes.
|
|
72
|
+
|
|
73
|
+
For a longer write-up on empirical nudges, cap-unit alignment, raw metrics, and compensated metrics, see `docs/comparing-baseline-alignment-techniques.md`. Its visual companion lives at `demo/components/engine-illustration.html`.
|
|
74
|
+
|
|
75
|
+
## Output
|
|
76
|
+
|
|
77
|
+
Build output includes:
|
|
78
|
+
|
|
79
|
+
- `dist/styles.css`
|
|
80
|
+
- `dist/tokens.json`
|
|
81
|
+
- `dist/surfaces.json`
|
|
82
|
+
- `dist/experiments/ibm-plex-engine-smoke/styles.css`
|
|
83
|
+
- `dist/experiments/ibm-plex-engine-smoke/tokens.json`
|
|
84
|
+
- `dist/experiments/ibm-plex-engine-smoke/surfaces.json`
|
|
85
|
+
- `dist/tiers/editorial/styles.css`
|
|
86
|
+
- `dist/tiers/editorial/tokens.json`
|
|
87
|
+
- `dist/tiers/editorial/surfaces.json`
|
|
88
|
+
- `dist/tiers/documentation/styles.css`
|
|
89
|
+
- `dist/tiers/documentation/tokens.json`
|
|
90
|
+
- `dist/tiers/documentation/surfaces.json`
|
|
91
|
+
- `dist/tiers/app/styles.css`
|
|
92
|
+
- `dist/tiers/app/tokens.json`
|
|
93
|
+
- `dist/tiers/app/surfaces.json`
|
|
94
|
+
- `dist/tiers/os/styles.css`
|
|
95
|
+
- `dist/tiers/os/tokens.json`
|
|
96
|
+
- `dist/tiers/os/surfaces.json`
|
|
97
|
+
- `dist/presets/prose/styles.css`
|
|
98
|
+
- `dist/presets/prose/tokens.json`
|
|
99
|
+
- `dist/presets/prose/surfaces.json`
|
|
100
|
+
- `dist/presets/app-tier/styles.css`
|
|
101
|
+
- `dist/presets/app-tier/tokens.json`
|
|
102
|
+
- `dist/presets/app-tier/surfaces.json`
|
|
103
|
+
- `dist/index.js`
|
|
104
|
+
- `dist/build.js`
|
|
105
|
+
|
|
106
106
|
## Install
|
|
107
107
|
|
|
108
108
|
Install the public package from npm:
|
|
@@ -128,188 +128,204 @@ The package name stays unscoped so existing imports such as
|
|
|
128
128
|
migration contract.
|
|
129
129
|
|
|
130
130
|
## Repository quick start
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
npm
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
npm
|
|
138
|
-
npm run
|
|
139
|
-
npm run
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
The
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
-
|
|
307
|
-
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
131
|
+
|
|
132
|
+
Repository development and the public build API are supported on Node.js
|
|
133
|
+
22.14 or newer with npm 11.19. The checked-in package metadata is the
|
|
134
|
+
authoritative toolchain contract.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npm install
|
|
138
|
+
npm run setup:demo-font
|
|
139
|
+
npm run playwright:install
|
|
140
|
+
npm run build
|
|
141
|
+
npm run test
|
|
142
|
+
npm run screenshots:components
|
|
143
|
+
npm run demo
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Release maintainers can validate the immutable publication boundary without
|
|
147
|
+
publishing:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm run release:preflight:test
|
|
151
|
+
npm run release:verify -- --pack-current
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The trusted workflow, resume procedure, checksum evidence, and private-source
|
|
155
|
+
provenance limitation are documented in
|
|
156
|
+
[`docs/publishing.md`](docs/publishing.md).
|
|
157
|
+
|
|
158
|
+
List or build tiers directly with:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm run build:theme -- --list-tiers
|
|
162
|
+
npm run build:theme -- --tier=os
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
List or build presets directly with:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm run build:theme -- --list-presets
|
|
169
|
+
npm run build:theme -- --preset=prose
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
While `npm run demo` is running, edits under `config/**/*.json` now rerun `npm run build:theme` automatically and force a full page reload.
|
|
173
|
+
|
|
174
|
+
`npm run setup:demo-font` downloads the Ubuntu Sans development font plus the IBM Plex Sans variable asset required by the engine-smoke experiment.
|
|
175
|
+
|
|
176
|
+
Built-in CSS does not emit `@font-face`: consumers own the runtime font URL and
|
|
177
|
+
must declare the same Ubuntu Sans variable face measured by BF. The repository
|
|
178
|
+
demo declares its downloaded development asset separately. Custom
|
|
179
|
+
`buildThemeFromConfig` outputs may still emit the face declared by a
|
|
180
|
+
consumer-owned config.
|
|
181
|
+
|
|
182
|
+
The demo runs at:
|
|
183
|
+
|
|
184
|
+
- [http://127.0.0.1:4174/](http://127.0.0.1:4174/) — Living spec home
|
|
185
|
+
- [http://127.0.0.1:4174/demo/spec/typography.html](http://127.0.0.1:4174/demo/spec/typography.html)
|
|
186
|
+
- [http://127.0.0.1:4174/demo/panel.html](http://127.0.0.1:4174/demo/panel.html) — OS tier
|
|
187
|
+
- [http://127.0.0.1:4174/demo/components/index.html](http://127.0.0.1:4174/demo/components/index.html) — BF foundations and component primitives
|
|
188
|
+
- [http://127.0.0.1:4174/demo/patterns/index.html](http://127.0.0.1:4174/demo/patterns/index.html) — Patterns, site compositions, recipes, layouts, and documented exclusions
|
|
189
|
+
- [http://127.0.0.1:4174/demo/components/engine-illustration.html](http://127.0.0.1:4174/demo/components/engine-illustration.html) — Three-way raw / compensated / cap comparison
|
|
190
|
+
|
|
191
|
+
Standalone historical Canonical example batches also live under `examples/grid/` and `examples/spacing/`. Each family has one shared stylesheet (`grid-examples.css` / `spacing-examples.css`); current decisions live in the active Spec Kit package rather than one-off root prompts.
|
|
192
|
+
|
|
193
|
+
## Component and pattern QA
|
|
194
|
+
|
|
195
|
+
The repo includes isolated demo pages for visual rhythm and interaction checks.
|
|
196
|
+
`demo/components/index.html` catalogs BF foundations and component primitives;
|
|
197
|
+
`demo/patterns/index.html` catalogs patterns, site compositions, and layouts while
|
|
198
|
+
linking to the same isolated QA routes. The authoritative saved-page inventory
|
|
199
|
+
lives in `scripts/component-demo-shared.ts`, so the README does not mirror that
|
|
200
|
+
detail list.
|
|
201
|
+
|
|
202
|
+
All component/spec/control pages now share the same thin page chrome: hamburger page list plus tone, baseline-grid, and tier controls. That chrome is excluded from screenshot comparisons and disabled during Playwright hit-testing so behavior checks interact with the component under test rather than the surrounding shell.
|
|
203
|
+
|
|
204
|
+
Component QA currently covers:
|
|
205
|
+
|
|
206
|
+
- Playwright screenshot capture for the saved demo inventory
|
|
207
|
+
- baseline verification for baseline-aligned component surfaces across all four built-in tiers and non-tier locked-manifest variants
|
|
208
|
+
- behavior verification for pinned-aside resize, drawer overlay, and application-layout interactions
|
|
209
|
+
- the narrow-panel regression page so dense controls and media must still fit a tight rail
|
|
210
|
+
|
|
211
|
+
The grouped overview pages still exist as convenience entry points:
|
|
212
|
+
|
|
213
|
+
- `demo/components/controls.html`
|
|
214
|
+
- `demo/components/surfaces-navigation.html`
|
|
215
|
+
|
|
216
|
+
Install Playwright once with:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npm run playwright:install
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Then capture the current component screenshots with:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npm run screenshots:components
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Run the browser-enforced baseline verification with:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm run verify:components
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Run the browser-enforced resize behavior verification with:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npm run verify:behavior
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Or do both in one pass:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npm run qa:components
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The screenshots and manifest are written to:
|
|
247
|
+
|
|
248
|
+
- `tmp/screenshots/components/`
|
|
249
|
+
|
|
250
|
+
Those screenshots power both visual atlases at `demo/components/index.html` and
|
|
251
|
+
`demo/patterns/index.html`, so run `npm run screenshots:components` when new
|
|
252
|
+
demos are added or the saved preview set changes. Atlas frames use
|
|
253
|
+
`object-fit: contain`, so saved previews remain legible when different surfaces
|
|
254
|
+
naturally want different capture widths.
|
|
255
|
+
|
|
256
|
+
The baseline verification report is also written to:
|
|
257
|
+
|
|
258
|
+
- `tmp/screenshots/components/baseline-report.json`
|
|
259
|
+
|
|
260
|
+
That report records one entry per verified component surface, not just one per
|
|
261
|
+
route. Shared-tier pages are walked through `editorial`, `documentation`,
|
|
262
|
+
`app`, and `os`; app-authored pages stay app-only unless they explicitly opt
|
|
263
|
+
into a broader tier set.
|
|
264
|
+
|
|
265
|
+
`npm test` now includes this Playwright baseline check, so once Chromium is installed the grid-alignment gate is part of the normal regression suite.
|
|
266
|
+
|
|
267
|
+
## Theme Model
|
|
268
|
+
|
|
269
|
+
The default theme uses Ubuntu Sans Variable and generates metric-driven typography tokens, spacing tokens, layout values, component density tokens, and a published surface manifest. Four first-class tiers plus two legacy preset aliases:
|
|
270
|
+
|
|
271
|
+
| Tier/Preset | Purpose |
|
|
272
|
+
|---|---|
|
|
273
|
+
| `editorial` | Root default, widest long-form composition |
|
|
274
|
+
| `documentation` | Tighter chapter-reading tier |
|
|
275
|
+
| `app` | Canonical-facing application chrome |
|
|
276
|
+
| `os` | Dense OS-style tier with metric alignment and compact control geometry |
|
|
277
|
+
|
|
278
|
+
Legacy aliases: `prose` → editorial, `app-tier` → app.
|
|
279
|
+
|
|
280
|
+
Independent surface contract:
|
|
281
|
+
|
|
282
|
+
- each built-in tier emits a complete scoped token surface instead of inheriting editorial defaults through diffs
|
|
283
|
+
- tier choice is a top-level class on any `.bf-theme` container: `.bf-tier-editorial`, `.bf-tier-documentation`, `.bf-tier-app`, `.bf-tier-os`
|
|
284
|
+
- multiple containers can coexist side by side under the same stylesheet
|
|
285
|
+
- `dist/surfaces.json` stores the runtime tokens and the font-metric artifact that produced each shipped surface — see [docs/surfaces-manifest.md](docs/surfaces-manifest.md) for the full schema, stability guarantees, and consumer recipes
|
|
286
|
+
- the published manifest omits local build-machine config/baseline file paths, so the shipped JSON stays portable
|
|
287
|
+
- every tier keeps metric-derived runtime alignment while nested stacks own semantic spacing
|
|
288
|
+
|
|
289
|
+
Example:
|
|
290
|
+
|
|
291
|
+
```html
|
|
292
|
+
<section class="bf-theme bf-tier-editorial bf-stack is-section">
|
|
293
|
+
<div class="bf-prose bf-stack">
|
|
294
|
+
<h1>Editorial surface</h1>
|
|
295
|
+
<p>Metric-derived nudges stay on.</p>
|
|
296
|
+
</div>
|
|
297
|
+
</section>
|
|
298
|
+
|
|
299
|
+
<section class="bf-theme bf-tier-app bf-stack is-section">
|
|
300
|
+
<div class="bf-prose bf-stack">
|
|
301
|
+
<h1>App surface</h1>
|
|
302
|
+
<p>Metric-derived compensation and container-owned gaps remain active at application density.</p>
|
|
303
|
+
</div>
|
|
304
|
+
</section>
|
|
305
|
+
|
|
306
|
+
<section class="bf-theme bf-tier-os bf-stack is-section">
|
|
307
|
+
<div class="bf-prose bf-stack">
|
|
308
|
+
<h1>OS surface</h1>
|
|
309
|
+
<p>Metrics stay on, but the measure and control geometry compress toward dense system surfaces.</p>
|
|
310
|
+
</div>
|
|
311
|
+
</section>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Engine choice remains separate: `.bf-engine-metrics` is the default production path, `.bf-engine-cap` is demo-only.
|
|
315
|
+
|
|
316
|
+
See `config/tiers/` for the four canonical source configs. Compatibility preset names resolve to those same owners rather than duplicate JSON files.
|
|
317
|
+
|
|
318
|
+
## Public API
|
|
319
|
+
|
|
320
|
+
Package root exports:
|
|
321
|
+
|
|
322
|
+
- `initAccordions`
|
|
323
|
+
- `toggleAccordionButton`
|
|
324
|
+
- `initApplicationLayouts`
|
|
325
|
+
- `initBaselineGridToggles`
|
|
326
|
+
- `setupBaselineGridToggle`
|
|
327
|
+
- `generateBaselineGridOverlayCss`
|
|
328
|
+
- `generateBaselineGridThemeOverrideCss`
|
|
313
329
|
- `initCodeSnippets`
|
|
314
330
|
- `initContextualMenus`
|
|
315
331
|
- `initInPageNavigations`
|
|
@@ -321,268 +337,268 @@ Package root exports:
|
|
|
321
337
|
- `initExpandingTables`
|
|
322
338
|
- `initMobileCardTables`
|
|
323
339
|
- `initListTree`
|
|
324
|
-
- `initPanelDrawers`
|
|
325
|
-
- `initRangeControls`
|
|
326
|
-
- `setupRangeControl`
|
|
327
|
-
- `updateRangeFill`
|
|
328
|
-
- `initResizableAsides`
|
|
329
|
-
- `initSideNavigations`
|
|
330
|
-
- `initTopNavigations`
|
|
331
|
-
- `initTabs`
|
|
332
|
-
- `initTooltips`
|
|
333
|
-
- `tierNames`, `tierDescriptions`, and `isTierName`
|
|
334
|
-
- `TierName`, `BuiltInThemeName`, `ThemeSurfaceManifest`, and related public types
|
|
335
|
-
|
|
336
|
-
Node/build exports:
|
|
337
|
-
|
|
338
|
-
- `buildThemeFromConfig`
|
|
339
|
-
- `buildThemeFromTier`
|
|
340
|
-
- `buildThemeFromPreset`
|
|
341
|
-
- `deriveBaselineTokensFromConfig`
|
|
342
|
-
- `readThemeConfig`
|
|
343
|
-
|
|
344
|
-
Static assets:
|
|
345
|
-
|
|
346
|
-
- `baseline-foundry/styles.css`
|
|
347
|
-
- `baseline-foundry/tokens.json`
|
|
348
|
-
- `baseline-foundry/surfaces.json`
|
|
349
|
-
- `baseline-foundry/tiers/editorial.css`
|
|
350
|
-
- `baseline-foundry/tiers/editorial.tokens.json`
|
|
351
|
-
- `baseline-foundry/tiers/editorial.surfaces.json`
|
|
352
|
-
- `baseline-foundry/tiers/documentation.css`
|
|
353
|
-
- `baseline-foundry/tiers/documentation.tokens.json`
|
|
354
|
-
- `baseline-foundry/tiers/documentation.surfaces.json`
|
|
355
|
-
- `baseline-foundry/tiers/app.css`
|
|
356
|
-
- `baseline-foundry/tiers/app.tokens.json`
|
|
357
|
-
- `baseline-foundry/tiers/app.surfaces.json`
|
|
358
|
-
- `baseline-foundry/tiers/os.css`
|
|
359
|
-
- `baseline-foundry/tiers/os.tokens.json`
|
|
360
|
-
- `baseline-foundry/tiers/os.surfaces.json`
|
|
361
|
-
- `baseline-foundry/presets/prose.css`
|
|
362
|
-
- `baseline-foundry/presets/prose.tokens.json`
|
|
363
|
-
- `baseline-foundry/presets/prose.surfaces.json`
|
|
364
|
-
- `baseline-foundry/presets/app-tier.css`
|
|
365
|
-
- `baseline-foundry/presets/app-tier.tokens.json`
|
|
366
|
-
- `baseline-foundry/presets/app-tier.surfaces.json`
|
|
367
|
-
- `baseline-foundry/presets`
|
|
368
|
-
- `baseline-foundry/types`
|
|
369
|
-
|
|
370
|
-
### Entry point guidance
|
|
371
|
-
|
|
372
|
-
Downstream consumers have two supported ways to load the built-in OS surface, depending on whether they need a neutral shared bundle or an OS-only default surface.
|
|
373
|
-
|
|
374
|
-
- Use `baseline-foundry/styles.css` as the neutral entrypoint when the consumer wants the shared root bundle and will opt into OS with class switching such as `.bf-theme.bf-tier-os`.
|
|
375
|
-
- Use `baseline-foundry/tiers/os.css` only when the consumer wants OS to be the unscoped default surface for that stylesheet import.
|
|
376
|
-
- Do not import `baseline-foundry/presets/app-tier.css` just to preload the shared bundle before switching to `bf-tier-os`; that preset remains the legacy app alias, not the neutral OS entrypoint.
|
|
377
|
-
|
|
378
|
-
Example neutral entrypoint for a downstream such as `a4-generator`:
|
|
379
|
-
|
|
380
|
-
```html
|
|
381
|
-
<link rel="stylesheet" href="baseline-foundry/styles.css" />
|
|
382
|
-
|
|
383
|
-
<section class="bf-theme bf-tier-os">
|
|
384
|
-
<div class="bf-prose">
|
|
385
|
-
<h1>OS surface</h1>
|
|
386
|
-
<p>The shared root bundle is loaded once, and the container opts into the OS tier explicitly.</p>
|
|
387
|
-
</div>
|
|
388
|
-
</section>
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Example OS-default entrypoint when class switching is not needed:
|
|
392
|
-
|
|
393
|
-
```html
|
|
394
|
-
<link rel="stylesheet" href="baseline-foundry/tiers/os.css" />
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
## Downstream Fonts
|
|
398
|
-
|
|
399
|
-
The built-in default is Ubuntu Sans Variable, but downstream repos are not locked to it.
|
|
400
|
-
Point the build at a downstream theme config and derive fresh nudges from that font's real metrics.
|
|
401
|
-
|
|
402
|
-
The npm package does not ship BF's development font file and built-in CSS does
|
|
403
|
-
not guess a URL for it. A consumer using a built-in tier must serve Ubuntu Sans
|
|
404
|
-
Variable and declare one normal variable face covering weights 100 through
|
|
405
|
-
800 and stretches 75% through 100%. The manifest's relative
|
|
406
|
-
`fontFiles[*].path` records the source asset used for metric generation; it is
|
|
407
|
-
not a package runtime URL.
|
|
408
|
-
|
|
409
|
-
The key rule is simple:
|
|
410
|
-
|
|
411
|
-
- **do not reuse nudges from a different font**
|
|
412
|
-
- **do not switch font-family in CSS without regenerating tokens**
|
|
413
|
-
- **derive a fresh `nudgeTop` set for the actual font files that will ship**
|
|
414
|
-
|
|
415
|
-
### What the downstream config needs
|
|
416
|
-
|
|
417
|
-
Create a theme JSON that follows the same shape as the tier configs under `config/tiers/`.
|
|
418
|
-
The font files are resolved relative to that config file, so a downstream repo can keep its own font assets and still use the same build path.
|
|
419
|
-
|
|
420
|
-
At minimum, define:
|
|
421
|
-
|
|
422
|
-
- `baselineUnit`
|
|
423
|
-
- `fontFiles`
|
|
424
|
-
- `fontStacks`
|
|
425
|
-
- `elements`
|
|
426
|
-
- `roles`
|
|
427
|
-
- `layout`
|
|
428
|
-
- `components`
|
|
429
|
-
|
|
430
|
-
Example sketch for a downstream Ubuntu Sans theme:
|
|
431
|
-
|
|
432
|
-
```json
|
|
433
|
-
{
|
|
434
|
-
"baselineUnit": 0.25,
|
|
435
|
-
"fontFiles": [
|
|
436
|
-
{
|
|
437
|
-
"family": "ubuntu-sans",
|
|
438
|
-
"path": "../apps/overlay-preview/public/assets/fonts/UbuntuSans-Regular.ttf",
|
|
439
|
-
"cssFamily": "Ubuntu Sans",
|
|
440
|
-
"fontStyle": "normal",
|
|
441
|
-
"fontWeight": "100 800",
|
|
442
|
-
"fontDisplay": "swap"
|
|
443
|
-
}
|
|
444
|
-
],
|
|
445
|
-
"fontStacks": {
|
|
446
|
-
"ubuntu-sans": "\"Ubuntu Sans\", \"Ubuntu\", system-ui, sans-serif"
|
|
447
|
-
},
|
|
448
|
-
"elements": [
|
|
449
|
-
{
|
|
450
|
-
"identifier": "body",
|
|
451
|
-
"fontSize": 0.75,
|
|
452
|
-
"lineHeight": 4,
|
|
453
|
-
"spaceAfter": 1,
|
|
454
|
-
"fontFamily": "ubuntu-sans",
|
|
455
|
-
"fontWeight": 400,
|
|
456
|
-
"fontStyle": "normal"
|
|
457
|
-
}
|
|
458
|
-
],
|
|
459
|
-
"roles": {
|
|
460
|
-
"body": "body"
|
|
461
|
-
},
|
|
462
|
-
"layout": {
|
|
463
|
-
"contentMaxWidthRem": 90,
|
|
464
|
-
"contentPaddingInlineRem": 1,
|
|
465
|
-
"measureRem": 40,
|
|
466
|
-
"sectionSpaceBaselineUnits": 8,
|
|
467
|
-
"sectionSpaceDeepBaselineUnits": 16,
|
|
468
|
-
"stripSpaceBaselineUnits": 8,
|
|
469
|
-
"gridGapInlineBaselineUnits": 2,
|
|
470
|
-
"gridGapBlockBaselineUnits": 2,
|
|
471
|
-
"pageMarginBaselineUnits": 2
|
|
472
|
-
},
|
|
473
|
-
"components": {
|
|
474
|
-
"borderWidthPx": 1,
|
|
475
|
-
"radiusRem": 0,
|
|
476
|
-
"controlBlockPaddingRem": 0.5,
|
|
477
|
-
"controlCompactBlockPaddingRem": 0.25,
|
|
478
|
-
"controlInlinePaddingRem": 1,
|
|
479
|
-
"controlVisualSizeRem": 0.75,
|
|
480
|
-
"fieldGapBaselineUnits": 1,
|
|
481
|
-
"panelPaddingInlineBaselineUnits": 2,
|
|
482
|
-
"panelPaddingBlockBaselineUnits": 2,
|
|
483
|
-
"accordionIndentBaselineUnits": 3
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### Generate full downstream CSS and tokens
|
|
489
|
-
|
|
490
|
-
Use the Node/build subpath so the downstream repo does not need to duplicate any build logic:
|
|
491
|
-
|
|
492
|
-
```ts
|
|
493
|
-
import { buildThemeFromConfig } from "baseline-foundry/build";
|
|
494
|
-
|
|
495
|
-
await buildThemeFromConfig("config/ubuntu-foundry-theme.json", {
|
|
496
|
-
distDir: "generated/foundry/ubuntu",
|
|
497
|
-
baselineDir: ".generated/baseline/ubuntu"
|
|
498
|
-
});
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
If a downstream surface bundle should ship multiple named fonts or brand variants in one stylesheet, pass a label for the default surface plus sibling named surfaces:
|
|
502
|
-
|
|
503
|
-
Baseline Foundry does not ship IBM Plex as a built-in tier or preset. Ubuntu Sans remains the only built-in tier font. For non-Ubuntu downstream bundles, provide your own config file and treat `config/experiments/ibm-plex-engine-smoke.json` as a reference/example rather than as a published preset.
|
|
504
|
-
|
|
505
|
-
```ts
|
|
506
|
-
await buildThemeFromConfig("config/brand-ibm-plex-theme.json", {
|
|
507
|
-
distDir: "generated/foundry/smoke",
|
|
508
|
-
baselineDir: ".generated/baseline/smoke",
|
|
509
|
-
surfaceLabel: "IBM Plex Sans",
|
|
510
|
-
additionalSurfaces: [
|
|
511
|
-
{
|
|
512
|
-
name: "ubuntu-smoke",
|
|
513
|
-
label: "Ubuntu Sans",
|
|
514
|
-
className: "bf-surface-ubuntu-smoke",
|
|
515
|
-
configPath: "config/ubuntu-foundry-theme.json"
|
|
516
|
-
}
|
|
517
|
-
]
|
|
518
|
-
});
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
That does three things:
|
|
522
|
-
|
|
523
|
-
1. writes the reduced baseline-generator input JSON
|
|
524
|
-
2. runs `@lyubomir-popov/baseline-nudge-generator`
|
|
525
|
-
3. emits `tokens.json`, `styles.css`, and `surfaces.json` for the downstream font or surface set
|
|
526
|
-
|
|
527
|
-
`surfaces.json` will then expose each named surface's runtime tokens, stored metrics, and optional UI label under one manifest-backed bundle.
|
|
528
|
-
|
|
529
|
-
### Derive nudges only
|
|
530
|
-
|
|
531
|
-
If the downstream repo wants the font metrics and `nudgeTop` values but plans to own CSS generation itself, use `deriveBaselineTokensFromConfig`:
|
|
532
|
-
|
|
533
|
-
```ts
|
|
534
|
-
import { deriveBaselineTokensFromConfig } from "baseline-foundry/build";
|
|
535
|
-
|
|
536
|
-
const result = await deriveBaselineTokensFromConfig("config/ubuntu-foundry-theme.json", {
|
|
537
|
-
baselineDir: ".generated/baseline/ubuntu"
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
console.log(result.tokens.elements.body.nudgeTop);
|
|
541
|
-
console.log(result.baselineConfigPath);
|
|
542
|
-
console.log(result.baselineTokensPath);
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
### Direct utility usage
|
|
546
|
-
|
|
547
|
-
`baseline-foundry` uses `@lyubomir-popov/baseline-nudge-generator` under the hood.
|
|
548
|
-
The reduced config passed to that utility contains only:
|
|
549
|
-
|
|
550
|
-
- `baselineUnit`
|
|
551
|
-
- `fontFiles` with build-time font paths
|
|
552
|
-
- `elements` with `identifier`, `fontSize`, `lineHeight`, `spaceAfter`, `fontFamily`, `fontWeight`, and `fontStyle`
|
|
553
|
-
|
|
554
|
-
Equivalent direct usage looks like this:
|
|
555
|
-
|
|
556
|
-
```ts
|
|
557
|
-
import { generateFromConfig } from "@lyubomir-popov/baseline-nudge-generator";
|
|
558
|
-
|
|
559
|
-
await generateFromConfig(".generated/baseline/ubuntu/ubuntu-foundry-theme.baseline.json", ".generated/baseline/ubuntu");
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
The generated `tokens.json` then contains the derived metric nudges per element, including `nudgeTop`, which `baseline-foundry` turns into the scoped `--bf-<role>-nudge-start` / `--bf-<role>-nudge-end` variables inside each emitted surface.
|
|
563
|
-
|
|
564
|
-
### Practical downstream advice
|
|
565
|
-
|
|
566
|
-
- Regenerate tokens whenever the downstream font files change.
|
|
567
|
-
- Regenerate tokens whenever font size, line-height, or baseline unit changes.
|
|
568
|
-
- Keep at least one non-`runtimeOnly` font file in `fontFiles`; that is the file the nudge generator reads for metrics.
|
|
569
|
-
- If a downstream repo ships multiple runtime faces, mark only the non-metric extras as `runtimeOnly`.
|
|
570
|
-
- Keep metrics as the default engine for production fonts; `.bf-engine-cap` remains an opt-in fallback, not the default path.
|
|
571
|
-
|
|
572
|
-
## Demo
|
|
573
|
-
|
|
574
|
-
The demo surface at `/` shows editorial prose rhythm, tier switching, dark
|
|
575
|
-
theme, grid, spacing, and component specimens. BF primitives are indexed at
|
|
576
|
-
`demo/components/index.html`; patterns, site compositions, and layouts are
|
|
577
|
-
indexed separately at `demo/patterns/index.html`. Their isolated test routes
|
|
578
|
-
remain under `demo/components/`, and the authoritative saved-page inventory is
|
|
579
|
-
in `scripts/component-demo-shared.ts`.
|
|
580
|
-
|
|
581
|
-
## Start Here
|
|
582
|
-
|
|
583
|
-
If you resume this repo in a new chat, read:
|
|
584
|
-
|
|
585
|
-
1. `AGENTS.md`
|
|
586
|
-
2. `AGENT-INBOX.md`
|
|
587
|
-
3. `docs/agent-index.md`
|
|
588
|
-
4. `docs/specs.md`
|
|
340
|
+
- `initPanelDrawers`
|
|
341
|
+
- `initRangeControls`
|
|
342
|
+
- `setupRangeControl`
|
|
343
|
+
- `updateRangeFill`
|
|
344
|
+
- `initResizableAsides`
|
|
345
|
+
- `initSideNavigations`
|
|
346
|
+
- `initTopNavigations`
|
|
347
|
+
- `initTabs`
|
|
348
|
+
- `initTooltips`
|
|
349
|
+
- `tierNames`, `tierDescriptions`, and `isTierName`
|
|
350
|
+
- `TierName`, `BuiltInThemeName`, `ThemeSurfaceManifest`, and related public types
|
|
351
|
+
|
|
352
|
+
Node/build exports:
|
|
353
|
+
|
|
354
|
+
- `buildThemeFromConfig`
|
|
355
|
+
- `buildThemeFromTier`
|
|
356
|
+
- `buildThemeFromPreset`
|
|
357
|
+
- `deriveBaselineTokensFromConfig`
|
|
358
|
+
- `readThemeConfig`
|
|
359
|
+
|
|
360
|
+
Static assets:
|
|
361
|
+
|
|
362
|
+
- `baseline-foundry/styles.css`
|
|
363
|
+
- `baseline-foundry/tokens.json`
|
|
364
|
+
- `baseline-foundry/surfaces.json`
|
|
365
|
+
- `baseline-foundry/tiers/editorial.css`
|
|
366
|
+
- `baseline-foundry/tiers/editorial.tokens.json`
|
|
367
|
+
- `baseline-foundry/tiers/editorial.surfaces.json`
|
|
368
|
+
- `baseline-foundry/tiers/documentation.css`
|
|
369
|
+
- `baseline-foundry/tiers/documentation.tokens.json`
|
|
370
|
+
- `baseline-foundry/tiers/documentation.surfaces.json`
|
|
371
|
+
- `baseline-foundry/tiers/app.css`
|
|
372
|
+
- `baseline-foundry/tiers/app.tokens.json`
|
|
373
|
+
- `baseline-foundry/tiers/app.surfaces.json`
|
|
374
|
+
- `baseline-foundry/tiers/os.css`
|
|
375
|
+
- `baseline-foundry/tiers/os.tokens.json`
|
|
376
|
+
- `baseline-foundry/tiers/os.surfaces.json`
|
|
377
|
+
- `baseline-foundry/presets/prose.css`
|
|
378
|
+
- `baseline-foundry/presets/prose.tokens.json`
|
|
379
|
+
- `baseline-foundry/presets/prose.surfaces.json`
|
|
380
|
+
- `baseline-foundry/presets/app-tier.css`
|
|
381
|
+
- `baseline-foundry/presets/app-tier.tokens.json`
|
|
382
|
+
- `baseline-foundry/presets/app-tier.surfaces.json`
|
|
383
|
+
- `baseline-foundry/presets`
|
|
384
|
+
- `baseline-foundry/types`
|
|
385
|
+
|
|
386
|
+
### Entry point guidance
|
|
387
|
+
|
|
388
|
+
Downstream consumers have two supported ways to load the built-in OS surface, depending on whether they need a neutral shared bundle or an OS-only default surface.
|
|
389
|
+
|
|
390
|
+
- Use `baseline-foundry/styles.css` as the neutral entrypoint when the consumer wants the shared root bundle and will opt into OS with class switching such as `.bf-theme.bf-tier-os`.
|
|
391
|
+
- Use `baseline-foundry/tiers/os.css` only when the consumer wants OS to be the unscoped default surface for that stylesheet import.
|
|
392
|
+
- Do not import `baseline-foundry/presets/app-tier.css` just to preload the shared bundle before switching to `bf-tier-os`; that preset remains the legacy app alias, not the neutral OS entrypoint.
|
|
393
|
+
|
|
394
|
+
Example neutral entrypoint for a downstream such as `a4-generator`:
|
|
395
|
+
|
|
396
|
+
```html
|
|
397
|
+
<link rel="stylesheet" href="baseline-foundry/styles.css" />
|
|
398
|
+
|
|
399
|
+
<section class="bf-theme bf-tier-os">
|
|
400
|
+
<div class="bf-prose">
|
|
401
|
+
<h1>OS surface</h1>
|
|
402
|
+
<p>The shared root bundle is loaded once, and the container opts into the OS tier explicitly.</p>
|
|
403
|
+
</div>
|
|
404
|
+
</section>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Example OS-default entrypoint when class switching is not needed:
|
|
408
|
+
|
|
409
|
+
```html
|
|
410
|
+
<link rel="stylesheet" href="baseline-foundry/tiers/os.css" />
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Downstream Fonts
|
|
414
|
+
|
|
415
|
+
The built-in default is Ubuntu Sans Variable, but downstream repos are not locked to it.
|
|
416
|
+
Point the build at a downstream theme config and derive fresh nudges from that font's real metrics.
|
|
417
|
+
|
|
418
|
+
The npm package does not ship BF's development font file and built-in CSS does
|
|
419
|
+
not guess a URL for it. A consumer using a built-in tier must serve Ubuntu Sans
|
|
420
|
+
Variable and declare one normal variable face covering weights 100 through
|
|
421
|
+
800 and stretches 75% through 100%. The manifest's relative
|
|
422
|
+
`fontFiles[*].path` records the source asset used for metric generation; it is
|
|
423
|
+
not a package runtime URL.
|
|
424
|
+
|
|
425
|
+
The key rule is simple:
|
|
426
|
+
|
|
427
|
+
- **do not reuse nudges from a different font**
|
|
428
|
+
- **do not switch font-family in CSS without regenerating tokens**
|
|
429
|
+
- **derive a fresh `nudgeTop` set for the actual font files that will ship**
|
|
430
|
+
|
|
431
|
+
### What the downstream config needs
|
|
432
|
+
|
|
433
|
+
Create a theme JSON that follows the same shape as the tier configs under `config/tiers/`.
|
|
434
|
+
The font files are resolved relative to that config file, so a downstream repo can keep its own font assets and still use the same build path.
|
|
435
|
+
|
|
436
|
+
At minimum, define:
|
|
437
|
+
|
|
438
|
+
- `baselineUnit`
|
|
439
|
+
- `fontFiles`
|
|
440
|
+
- `fontStacks`
|
|
441
|
+
- `elements`
|
|
442
|
+
- `roles`
|
|
443
|
+
- `layout`
|
|
444
|
+
- `components`
|
|
445
|
+
|
|
446
|
+
Example sketch for a downstream Ubuntu Sans theme:
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"baselineUnit": 0.25,
|
|
451
|
+
"fontFiles": [
|
|
452
|
+
{
|
|
453
|
+
"family": "ubuntu-sans",
|
|
454
|
+
"path": "../apps/overlay-preview/public/assets/fonts/UbuntuSans-Regular.ttf",
|
|
455
|
+
"cssFamily": "Ubuntu Sans",
|
|
456
|
+
"fontStyle": "normal",
|
|
457
|
+
"fontWeight": "100 800",
|
|
458
|
+
"fontDisplay": "swap"
|
|
459
|
+
}
|
|
460
|
+
],
|
|
461
|
+
"fontStacks": {
|
|
462
|
+
"ubuntu-sans": "\"Ubuntu Sans\", \"Ubuntu\", system-ui, sans-serif"
|
|
463
|
+
},
|
|
464
|
+
"elements": [
|
|
465
|
+
{
|
|
466
|
+
"identifier": "body",
|
|
467
|
+
"fontSize": 0.75,
|
|
468
|
+
"lineHeight": 4,
|
|
469
|
+
"spaceAfter": 1,
|
|
470
|
+
"fontFamily": "ubuntu-sans",
|
|
471
|
+
"fontWeight": 400,
|
|
472
|
+
"fontStyle": "normal"
|
|
473
|
+
}
|
|
474
|
+
],
|
|
475
|
+
"roles": {
|
|
476
|
+
"body": "body"
|
|
477
|
+
},
|
|
478
|
+
"layout": {
|
|
479
|
+
"contentMaxWidthRem": 90,
|
|
480
|
+
"contentPaddingInlineRem": 1,
|
|
481
|
+
"measureRem": 40,
|
|
482
|
+
"sectionSpaceBaselineUnits": 8,
|
|
483
|
+
"sectionSpaceDeepBaselineUnits": 16,
|
|
484
|
+
"stripSpaceBaselineUnits": 8,
|
|
485
|
+
"gridGapInlineBaselineUnits": 2,
|
|
486
|
+
"gridGapBlockBaselineUnits": 2,
|
|
487
|
+
"pageMarginBaselineUnits": 2
|
|
488
|
+
},
|
|
489
|
+
"components": {
|
|
490
|
+
"borderWidthPx": 1,
|
|
491
|
+
"radiusRem": 0,
|
|
492
|
+
"controlBlockPaddingRem": 0.5,
|
|
493
|
+
"controlCompactBlockPaddingRem": 0.25,
|
|
494
|
+
"controlInlinePaddingRem": 1,
|
|
495
|
+
"controlVisualSizeRem": 0.75,
|
|
496
|
+
"fieldGapBaselineUnits": 1,
|
|
497
|
+
"panelPaddingInlineBaselineUnits": 2,
|
|
498
|
+
"panelPaddingBlockBaselineUnits": 2,
|
|
499
|
+
"accordionIndentBaselineUnits": 3
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Generate full downstream CSS and tokens
|
|
505
|
+
|
|
506
|
+
Use the Node/build subpath so the downstream repo does not need to duplicate any build logic:
|
|
507
|
+
|
|
508
|
+
```ts
|
|
509
|
+
import { buildThemeFromConfig } from "baseline-foundry/build";
|
|
510
|
+
|
|
511
|
+
await buildThemeFromConfig("config/ubuntu-foundry-theme.json", {
|
|
512
|
+
distDir: "generated/foundry/ubuntu",
|
|
513
|
+
baselineDir: ".generated/baseline/ubuntu"
|
|
514
|
+
});
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
If a downstream surface bundle should ship multiple named fonts or brand variants in one stylesheet, pass a label for the default surface plus sibling named surfaces:
|
|
518
|
+
|
|
519
|
+
Baseline Foundry does not ship IBM Plex as a built-in tier or preset. Ubuntu Sans remains the only built-in tier font. For non-Ubuntu downstream bundles, provide your own config file and treat `config/experiments/ibm-plex-engine-smoke.json` as a reference/example rather than as a published preset.
|
|
520
|
+
|
|
521
|
+
```ts
|
|
522
|
+
await buildThemeFromConfig("config/brand-ibm-plex-theme.json", {
|
|
523
|
+
distDir: "generated/foundry/smoke",
|
|
524
|
+
baselineDir: ".generated/baseline/smoke",
|
|
525
|
+
surfaceLabel: "IBM Plex Sans",
|
|
526
|
+
additionalSurfaces: [
|
|
527
|
+
{
|
|
528
|
+
name: "ubuntu-smoke",
|
|
529
|
+
label: "Ubuntu Sans",
|
|
530
|
+
className: "bf-surface-ubuntu-smoke",
|
|
531
|
+
configPath: "config/ubuntu-foundry-theme.json"
|
|
532
|
+
}
|
|
533
|
+
]
|
|
534
|
+
});
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
That does three things:
|
|
538
|
+
|
|
539
|
+
1. writes the reduced baseline-generator input JSON
|
|
540
|
+
2. runs `@lyubomir-popov/baseline-nudge-generator`
|
|
541
|
+
3. emits `tokens.json`, `styles.css`, and `surfaces.json` for the downstream font or surface set
|
|
542
|
+
|
|
543
|
+
`surfaces.json` will then expose each named surface's runtime tokens, stored metrics, and optional UI label under one manifest-backed bundle.
|
|
544
|
+
|
|
545
|
+
### Derive nudges only
|
|
546
|
+
|
|
547
|
+
If the downstream repo wants the font metrics and `nudgeTop` values but plans to own CSS generation itself, use `deriveBaselineTokensFromConfig`:
|
|
548
|
+
|
|
549
|
+
```ts
|
|
550
|
+
import { deriveBaselineTokensFromConfig } from "baseline-foundry/build";
|
|
551
|
+
|
|
552
|
+
const result = await deriveBaselineTokensFromConfig("config/ubuntu-foundry-theme.json", {
|
|
553
|
+
baselineDir: ".generated/baseline/ubuntu"
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
console.log(result.tokens.elements.body.nudgeTop);
|
|
557
|
+
console.log(result.baselineConfigPath);
|
|
558
|
+
console.log(result.baselineTokensPath);
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Direct utility usage
|
|
562
|
+
|
|
563
|
+
`baseline-foundry` uses `@lyubomir-popov/baseline-nudge-generator` under the hood.
|
|
564
|
+
The reduced config passed to that utility contains only:
|
|
565
|
+
|
|
566
|
+
- `baselineUnit`
|
|
567
|
+
- `fontFiles` with build-time font paths
|
|
568
|
+
- `elements` with `identifier`, `fontSize`, `lineHeight`, `spaceAfter`, `fontFamily`, `fontWeight`, and `fontStyle`
|
|
569
|
+
|
|
570
|
+
Equivalent direct usage looks like this:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
import { generateFromConfig } from "@lyubomir-popov/baseline-nudge-generator";
|
|
574
|
+
|
|
575
|
+
await generateFromConfig(".generated/baseline/ubuntu/ubuntu-foundry-theme.baseline.json", ".generated/baseline/ubuntu");
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
The generated `tokens.json` then contains the derived metric nudges per element, including `nudgeTop`, which `baseline-foundry` turns into the scoped `--bf-<role>-nudge-start` / `--bf-<role>-nudge-end` variables inside each emitted surface.
|
|
579
|
+
|
|
580
|
+
### Practical downstream advice
|
|
581
|
+
|
|
582
|
+
- Regenerate tokens whenever the downstream font files change.
|
|
583
|
+
- Regenerate tokens whenever font size, line-height, or baseline unit changes.
|
|
584
|
+
- Keep at least one non-`runtimeOnly` font file in `fontFiles`; that is the file the nudge generator reads for metrics.
|
|
585
|
+
- If a downstream repo ships multiple runtime faces, mark only the non-metric extras as `runtimeOnly`.
|
|
586
|
+
- Keep metrics as the default engine for production fonts; `.bf-engine-cap` remains an opt-in fallback, not the default path.
|
|
587
|
+
|
|
588
|
+
## Demo
|
|
589
|
+
|
|
590
|
+
The demo surface at `/` shows editorial prose rhythm, tier switching, dark
|
|
591
|
+
theme, grid, spacing, and component specimens. BF primitives are indexed at
|
|
592
|
+
`demo/components/index.html`; patterns, site compositions, and layouts are
|
|
593
|
+
indexed separately at `demo/patterns/index.html`. Their isolated test routes
|
|
594
|
+
remain under `demo/components/`, and the authoritative saved-page inventory is
|
|
595
|
+
in `scripts/component-demo-shared.ts`.
|
|
596
|
+
|
|
597
|
+
## Start Here
|
|
598
|
+
|
|
599
|
+
If you resume this repo in a new chat, read:
|
|
600
|
+
|
|
601
|
+
1. `AGENTS.md`
|
|
602
|
+
2. `AGENT-INBOX.md`
|
|
603
|
+
3. `docs/agent-index.md`
|
|
604
|
+
4. `docs/specs.md`
|