@brignano/design 0.1.1 → 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.
package/DECISIONS.md CHANGED
@@ -215,3 +215,36 @@ with it; `--mark` does not.
215
215
  separates them; a form error is not "rust means overdue", but they are the same
216
216
  register of message.
217
217
  - Nothing amber is clickable anywhere in the system.
218
+
219
+ ---
220
+
221
+ ## ADR-0005 — Diagrams are not charts: neutral nodes, colour for state only
222
+
223
+ **Status:** accepted · 2026-10-13
224
+
225
+ ### Context
226
+
227
+ `driftwood` draws architecture diagrams and was the first consumer to need them.
228
+ Its first pass on these tokens took the chart exception (§8, ADR-0002) and tinted
229
+ each node by family (edge, compute, data, messaging…) with `--chart-1…6`. On a
230
+ real 46-resource platform that put six hues on screen before anything was wrong,
231
+ and the database that was down was one more tinted box among them.
232
+
233
+ ### Decision
234
+
235
+ A diagram follows the restraint rule. The chart exception exists because a chart
236
+ has nothing *but* colour to tell series apart; a diagram node has an icon, a name
237
+ and a kind label, so family is already carried three times. Nodes are neutral.
238
+ Colour is reserved for state: health (`--danger`, `--attention`) and what a change
239
+ did, via three new aliases — `--diff-added`, `--diff-changed`, `--diff-removed` —
240
+ over the existing state hues. No new hue enters the system.
241
+
242
+ ### Consequences
243
+
244
+ - On a healthy, unchanged system the diagram is grey, and that is correct:
245
+ nothing is asking for you.
246
+ - `--diff-changed` shares cobalt with links. Context separates them (a node edge
247
+ with a `~ changed` tag is not underlined text), the same way feedback and domain
248
+ status share hues in ADR-0004.
249
+ - Standalone exports (SVG files, Mermaid in a pull request) take the light theme's
250
+ values, resolved from `tokens.css` by the consumer at build time.
package/DESIGN.md CHANGED
@@ -159,7 +159,44 @@ rationale in [`tokens.chart.css`](./tokens.chart.css). The short version:
159
159
  - Text wears text tokens, never the series colour.
160
160
  - **Never a dual-axis chart.** Two measures of different scale → two charts.
161
161
 
162
- ## 9. Accessibility floor
162
+ ## 9. Diagrams and diffs
163
+
164
+ An architecture diagram (`driftwood`, `homelab`) is a picture of a system, read to
165
+ answer "what changed, and what is broken". It follows the restraint rule, **not**
166
+ the chart exception: node *type* is a category like event type, and is carried by
167
+ an icon and a label, never a hue. A diagram where every node is tinted by family
168
+ is thirty coloured things, and the one that is down disappears among them.
169
+
170
+ - **Nodes are neutral.** `--card` fill, `--line-strong` edge, `--radius` corners,
171
+ an icon in `--ink-soft`, the name in `--ink`, the kind in `--mono` at
172
+ `--text-xs` in `--ink-soft`. Grouping is a zone: `--line` hairline, no fill or
173
+ a faint one, a `--mono` eyebrow label.
174
+ - **Edges are `--slate`.** They are UI marks (3:1), never text.
175
+ - **Only state gets colour**, and always as a tag with a symbol and a word as well:
176
+
177
+ | Token | Means | Tag |
178
+ |---|---|---|
179
+ | `--diff-added` | this change created it | `+ added` |
180
+ | `--diff-changed` | this change modified it | `~ changed` |
181
+ | `--diff-removed` | this change removes it — dashed, struck through | `− removed` |
182
+ | `--danger` | it is down | `✕ down` |
183
+ | `--attention` | degraded, or differs from the design | `▲ degraded` |
184
+
185
+ The diff tokens alias the state hues on purpose (added is *settled*, a change is
186
+ *informational*, a removal is the change that can lose data), so a diff adds no
187
+ hue to the system. Health wins the fill (`-surface`); a diff only takes the edge.
188
+ - **Selection** is the focus treatment: a 2px `--i-ink` outline, offset. Asking
189
+ "what depends on this?" dims everything unrelated to ~30% opacity and inks the
190
+ connecting edges in `--ink`; it never introduces a colour.
191
+ - **Lead with the verdict.** A page about a deploy opens with one sentence saying
192
+ what happened and what needs you, then the pills that back it up, then the
193
+ picture.
194
+ - **Diagrams follow the theme.** On a page they use the tokens like everything
195
+ else. A diagram exported as a standalone file (an SVG, a Mermaid block in a pull
196
+ request) cannot use `var()`; it takes the **light** theme's values, resolved from
197
+ this file at build time, never typed in.
198
+
199
+ ## 10. Accessibility floor
163
200
 
164
201
  Non-negotiable in both themes:
165
202
 
@@ -171,7 +208,7 @@ Non-negotiable in both themes:
171
208
  - Measured ratios sit next to their values in `tokens.css`. Changing a value means
172
209
  re-measuring it.
173
210
 
174
- ## 10. Integrating with a Tailwind consumer
211
+ ## 11. Integrating with a Tailwind consumer
175
212
 
176
213
  Tailwind's dark variant keys off a `.dark` class; these tokens key off
177
214
  `[data-theme]`. **Both must be set together**, by the same code, in both places
@@ -200,7 +237,7 @@ Import order matters — Tailwind first, then tokens, then the bridge:
200
237
  @import "@brignano/design/tailwind.css";
201
238
  ```
202
239
 
203
- ## 11. The one rule that keeps this true
240
+ ## 12. The one rule that keeps this true
204
241
 
205
242
  **Never hardcode a hex outside `tokens.css`.**
206
243
 
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anthony Brignano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -9,6 +9,7 @@ The shared design system for every brignano surface — `brignano.io`, `life`,
9
9
  | [`DECISIONS.md`](./DECISIONS.md) | Why the values are what they are. ADRs. |
10
10
  | [`tokens.css`](./tokens.css) | Single source of truth for colour, type, space, shape, motion. |
11
11
  | [`tokens.chart.css`](./tokens.chart.css) | Validated categorical palette for data viz. |
12
+ | [`previews/`](./previews) | Live swatches. Open one in a browser to see the tokens render. |
12
13
 
13
14
  ## The shape of it
14
15
 
@@ -35,6 +36,31 @@ The tool tier is the default. A marketing surface opts in with
35
36
  `class="tier-marketing"` on `<html>`, which unlocks the display face and opens the
36
37
  type scale. Colour is identical across tiers.
37
38
 
39
+ ## Previews
40
+
41
+ `previews/` holds a page per area — colour, type, elevation, controls, feedback, diagrams,
42
+ status. Each renders its subject twice, once in the viewer's theme and once on a
43
+ forced-dark ground, so drift between the two shows up without toggling anything.
44
+ No build step: open the file.
45
+
46
+ Every preview opens with a card marker:
47
+
48
+ ```html
49
+ <!-- @dsCard group="Foundations" -->
50
+ ```
51
+
52
+ That first line is what a [claude.ai/design][ds] design-system project reads to
53
+ build its card index — `group` becomes the section heading in the Design System
54
+ pane. The markers are comments, so they cost nothing when the page is opened
55
+ locally.
56
+
57
+ **A sync to such a project keeps this layout** — `tokens.css` at the project
58
+ root, `previews/` one level below it. `_preview.css` reaches it with
59
+ `@import '../tokens.css'` rather than carrying its own copy, because a second
60
+ copy of the tokens is the drift this repo exists to prevent. The trade is that
61
+ the parent reference is load-bearing: flatten the uploaded bundle and every
62
+ preview renders unstyled.
63
+
38
64
  ## For agents
39
65
 
40
66
  Read `DESIGN.md` before styling anything. Use the tokens. **Never hardcode a hex
@@ -55,7 +81,7 @@ something actually looks different.
55
81
 
56
82
  ## Releasing
57
83
 
58
- The tag is the trigger. `.github/workflows/release.yml` publishes to npm on any
84
+ The tag is the trigger. `.github/workflows/publish.yml` publishes to npm on any
59
85
  `v*` tag, after checking the tag agrees with `package.json` — npm versions are
60
86
  immutable, so a mismatch is caught before it's permanent.
61
87
 
@@ -69,4 +95,20 @@ this repo and there should never be one — the runner exchanges its OIDC identi
69
95
  for a short-lived credential via npm [trusted publishing][tp], which is also what
70
96
  produces the provenance attestation. A laptop has no such identity.
71
97
 
98
+ **The workflow is called `publish.yml` in every repo that publishes a package,
99
+ and that is not cosmetic.** npm's Trusted Publisher form takes the workflow
100
+ filename as part of the OIDC claim, and offers `publish.yml` as its example. Any
101
+ other name is a value you have to remember correctly, from the GitHub side, while
102
+ filling in a form on the npm side. Getting it wrong fails as `ENEEDAUTH` — npm
103
+ declines the exchange, `npm publish` falls back to token auth, and there is no
104
+ token — which names neither the workflow nor the mismatch. Matching the tool's
105
+ default is cheaper than being right every time.
106
+
107
+ Setting up a new package: create `.github/workflows/publish.yml` from this one,
108
+ then add the Trusted Publisher on npmjs.com — publisher GitHub Actions, the org
109
+ and repo, workflow filename `publish.yml`, and **environment name blank**, since
110
+ these workflows declare no `environment:`. Configure it before the first tag, or
111
+ the first publish fails the way this one did.
112
+
113
+ [ds]: https://claude.ai/design
72
114
  [tp]: https://docs.npmjs.com/trusted-publishers/
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@brignano/design",
3
- "version": "0.1.1",
4
- "description": "Shared design system for brignano surfaces \u2014 colour, type, space, shape, motion.",
3
+ "version": "0.2.0",
4
+ "description": "Shared design system for brignano surfaces — colour, type, space, shape, motion.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
package/tokens.css CHANGED
@@ -136,6 +136,26 @@
136
136
  --danger-line: color-mix(in srgb, var(--danger) 32%, transparent);
137
137
  --info-line: var(--i-line);
138
138
 
139
+ /* ── Diff ─────────────────────────────────────────────────────────────
140
+ What a change did to a thing: a deploy, a plan, a pull request. Aliases
141
+ of the state hues, so a diff adds no hue of its own (DESIGN.md §9):
142
+
143
+ --diff-added created by this change success — settled
144
+ --diff-changed modified by this change interactive — informational
145
+ --diff-removed removed by this change danger — can lose data
146
+
147
+ Always with a symbol and a word (+ added, ~ changed, − removed). Aliased
148
+ in this block only: these resolve against whichever theme block wins. */
149
+ --diff-added: var(--success);
150
+ --diff-added-ink: var(--success-ink);
151
+ --diff-added-surface: var(--success-surface);
152
+ --diff-changed: var(--i);
153
+ --diff-changed-ink: var(--i-ink);
154
+ --diff-changed-surface: var(--i-surface);
155
+ --diff-removed: var(--danger);
156
+ --diff-removed-ink: var(--danger-ink);
157
+ --diff-removed-surface: var(--danger-surface);
158
+
139
159
  /* ── Mark — identity ──────────────────────────────────────────────────
140
160
  Inks a GRAPHIC: the trail line, the A|B monogram, a hero rule. That is
141
161
  the entire permitted use.
@@ -331,6 +351,23 @@
331
351
  --scrim: rgba(0, 0, 0, 0.68);
332
352
  }
333
353
 
354
+ :root {
355
+ /* Tool-tier scale — compact, because scanning beats reading.
356
+ Declared BEFORE the marketing tier on purpose: `:root` and
357
+ `.tier-marketing` have the same specificity, so on <html> whichever
358
+ comes later wins. With this block last, the class did nothing. */
359
+ --text-xs: 0.6875rem;
360
+ --text-sm: 0.8125rem;
361
+ --text-base: 0.9375rem;
362
+ --text-lg: 1.0625rem;
363
+ --text-xl: 1.25rem;
364
+ --text-2xl: 1.5rem;
365
+ --text-3xl: 1.875rem;
366
+ --text-4xl: 2.25rem;
367
+ --section-gap: var(--s6);
368
+ --measure: 780px;
369
+ }
370
+
334
371
  /* ── Marketing tier ─────────────────────────────────────────────────────
335
372
  `class="tier-marketing"` on <html> (brignano.io). Unlocks the display
336
373
  face and opens the type scale. COLOUR IS IDENTICAL ACROSS TIERS — that
@@ -349,20 +386,6 @@
349
386
  --measure: 68ch;
350
387
  }
351
388
 
352
- :root {
353
- /* Tool-tier scale — compact, because scanning beats reading. */
354
- --text-xs: 0.6875rem;
355
- --text-sm: 0.8125rem;
356
- --text-base: 0.9375rem;
357
- --text-lg: 1.0625rem;
358
- --text-xl: 1.25rem;
359
- --text-2xl: 1.5rem;
360
- --text-3xl: 1.875rem;
361
- --text-4xl: 2.25rem;
362
- --section-gap: var(--s6);
363
- --measure: 780px;
364
- }
365
-
366
389
  ::selection {
367
390
  background: var(--i-selection);
368
391
  }