@bsuite/theme 0.7.2 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/theme",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -113,6 +113,64 @@
113
113
  --role-success: var(--braden-aqua);
114
114
  --role-info: var(--braden-teal-deep);
115
115
 
116
+ /* ═══ INFORMATIONAL SCALE — categorical, NOT semantic ═══
117
+ Added 2026-08-03 by operator ruling: "informational hues might be handy
118
+ to stand out against the style colour palette."
119
+
120
+ Role tokens describe STATE. They cannot describe CATEGORY — which
121
+ pipeline stage, which user role, which product tile. Apps that needed a
122
+ category reached for raw Tailwind instead, which is how one role-badge
123
+ table came to use purple, indigo, blue, violet and sky as its only
124
+ distinguishing signal.
125
+
126
+ NUMBERED, NOT NAMED, deliberately. Call one of these "moss green" and
127
+ it will be used for success within a week. A number says what these
128
+ are: interchangeable slots carrying no meaning of their own.
129
+ NEVER use an --info-* for state. State has role tokens.
130
+
131
+ Derived, not picked by eye: Vienot-Brettel-Mollon dichromat simulation,
132
+ DeltaE in OKLab, scored as the WORST case across normal, deuteranope and
133
+ protanope vision. Two constraints — perceptual distance keeps them
134
+ DISTINGUISHABLE, a >=28 degree hue gap keeps them looking CATEGORICAL
135
+ rather than like a light/dark pair of one colour. Every one is also
136
+ held away from the brand roles, which is what "stand out against the
137
+ style palette" requires: an informational badge must not read as a
138
+ primary action or an error.
139
+ Reproduce with scripts/design-informational-hues.py
140
+
141
+ LIMIT: worst-case separation is ~0.06-0.07, against >=0.156 for the
142
+ semantic pairs. That is 10x better than the purple-vs-blue pairing this
143
+ system rejected (0.006), but it is NOT the semantic standard and cannot
144
+ be — 8 mutually-distinct categories that also avoid 6 reserved brand
145
+ colours is a harder problem than 6 roles. So: colour is never the sole
146
+ signifier for a category. Always pair with a label or an icon. Past 8
147
+ categories, stop adding hues and add a second dimension. */
148
+ --info-1: oklch(0.660 0.120 0.0);
149
+ --info-2: oklch(0.660 0.120 30.0);
150
+ --info-3: oklch(0.620 0.120 72.0);
151
+ --info-4: oklch(0.460 0.120 132.0);
152
+ --info-5: oklch(0.780 0.120 162.0);
153
+ --info-6: oklch(0.740 0.120 222.0);
154
+ --info-7: oklch(0.660 0.120 252.0);
155
+ --info-8: oklch(0.620 0.120 324.0);
156
+
157
+ /* ═══ STAGE RAMP — progression, one hue, ascending lightness ═══
158
+ For an ORDERED sequence (pipeline stages), not a category set. A ramp
159
+ encodes direction: "further along" is visible at a glance, and it
160
+ survives greyscale and both dichromacies because lightness carries it.
161
+ Arbitrary per-stage hues cannot do that — a reader has to LEARN that
162
+ sky comes after amber.
163
+
164
+ Progression only. OUTCOMES are state, not stage: a hired candidate is
165
+ --role-success, a rejected one --role-error, a withdrawn one muted.
166
+ Do not extend this ramp to cover them. */
167
+ --stage-1: oklch(0.860 0.090 249.0);
168
+ --stage-2: oklch(0.780 0.090 249.0);
169
+ --stage-3: oklch(0.700 0.090 249.0);
170
+ --stage-4: oklch(0.620 0.090 249.0);
171
+ --stage-5: oklch(0.540 0.090 249.0);
172
+ --stage-6: oklch(0.460 0.090 249.0);
173
+
116
174
  /* ============================================================
117
175
  LAYER 3 — AA-SAFE TEXT RENDERINGS OF THE SATURATED ROLES
118
176
  A saturated fill colour is not a legible text colour.
package/src/css/vars.css CHANGED
@@ -127,6 +127,64 @@
127
127
  --role-success: var(--neon-electric-teal); /* was green — 0.043 from red */
128
128
  --role-info: var(--neon-electric-cyan); /* oklch(0.769 0.132 191.7) */
129
129
 
130
+ /* ═══ INFORMATIONAL SCALE — categorical, NOT semantic ═══
131
+ Added 2026-08-03 by operator ruling: "informational hues might be handy
132
+ to stand out against the style colour palette."
133
+
134
+ Role tokens describe STATE. They cannot describe CATEGORY — which
135
+ pipeline stage, which user role, which product tile. Apps that needed a
136
+ category reached for raw Tailwind instead, which is how one role-badge
137
+ table came to use purple, indigo, blue, violet and sky as its only
138
+ distinguishing signal.
139
+
140
+ NUMBERED, NOT NAMED, deliberately. Call one of these "moss green" and
141
+ it will be used for success within a week. A number says what these
142
+ are: interchangeable slots carrying no meaning of their own.
143
+ NEVER use an --info-* for state. State has role tokens.
144
+
145
+ Derived, not picked by eye: Vienot-Brettel-Mollon dichromat simulation,
146
+ DeltaE in OKLab, scored as the WORST case across normal, deuteranope and
147
+ protanope vision. Two constraints — perceptual distance keeps them
148
+ DISTINGUISHABLE, a >=28 degree hue gap keeps them looking CATEGORICAL
149
+ rather than like a light/dark pair of one colour. Every one is also
150
+ held away from the brand roles, which is what "stand out against the
151
+ style palette" requires: an informational badge must not read as a
152
+ primary action or an error.
153
+ Reproduce with scripts/design-informational-hues.py
154
+
155
+ LIMIT: worst-case separation is ~0.06-0.07, against >=0.156 for the
156
+ semantic pairs. That is 10x better than the purple-vs-blue pairing this
157
+ system rejected (0.006), but it is NOT the semantic standard and cannot
158
+ be — 8 mutually-distinct categories that also avoid 6 reserved brand
159
+ colours is a harder problem than 6 roles. So: colour is never the sole
160
+ signifier for a category. Always pair with a label or an icon. Past 8
161
+ categories, stop adding hues and add a second dimension. */
162
+ --info-1: oklch(0.460 0.140 0.0);
163
+ --info-2: oklch(0.700 0.140 42.0);
164
+ --info-3: oklch(0.540 0.140 138.0);
165
+ --info-4: oklch(0.700 0.140 168.0);
166
+ --info-5: oklch(0.780 0.140 228.0);
167
+ --info-6: oklch(0.700 0.140 258.0);
168
+ --info-7: oklch(0.500 0.140 300.0);
169
+ --info-8: oklch(0.460 0.140 330.0);
170
+
171
+ /* ═══ STAGE RAMP — progression, one hue, ascending lightness ═══
172
+ For an ORDERED sequence (pipeline stages), not a category set. A ramp
173
+ encodes direction: "further along" is visible at a glance, and it
174
+ survives greyscale and both dichromacies because lightness carries it.
175
+ Arbitrary per-stage hues cannot do that — a reader has to LEARN that
176
+ sky comes after amber.
177
+
178
+ Progression only. OUTCOMES are state, not stage: a hired candidate is
179
+ --role-success, a rejected one --role-error, a withdrawn one muted.
180
+ Do not extend this ramp to cover them. */
181
+ --stage-1: oklch(0.860 0.130 262.9);
182
+ --stage-2: oklch(0.780 0.130 262.9);
183
+ --stage-3: oklch(0.700 0.130 262.9);
184
+ --stage-4: oklch(0.620 0.130 262.9);
185
+ --stage-5: oklch(0.540 0.130 262.9);
186
+ --stage-6: oklch(0.460 0.130 262.9);
187
+
130
188
  /* AA-safe text renderings of the saturated roles on light surfaces.
131
189
  A saturated fill colour is not a legible text colour; these are the
132
190
  text variants and are the ONLY correct token for coloured type. */
package/src/preset-v4.css CHANGED
@@ -102,6 +102,30 @@
102
102
  --color-warning-text: var(--role-warning-text);
103
103
  --color-success-text: var(--role-success-text);
104
104
 
105
+ /* Informational scale — CATEGORICAL, never state. `bg-info-3`, `text-info-5`.
106
+ Numbered because they are interchangeable slots with no meaning of their
107
+ own; naming one invites it to be used as a semantic. Pair every one with a
108
+ label or icon — their separation is deliberately below the semantic
109
+ standard and cannot carry meaning alone. See --info-* in vars.css. */
110
+ --color-info-1: var(--info-1);
111
+ --color-info-2: var(--info-2);
112
+ --color-info-3: var(--info-3);
113
+ --color-info-4: var(--info-4);
114
+ --color-info-5: var(--info-5);
115
+ --color-info-6: var(--info-6);
116
+ --color-info-7: var(--info-7);
117
+ --color-info-8: var(--info-8);
118
+
119
+ /* Stage ramp — ORDERED progression. `bg-stage-1` .. `bg-stage-6`, lightness
120
+ descending, so "further along" reads at a glance and survives greyscale.
121
+ Outcomes are NOT stages: hired is --role-success, rejected --role-error. */
122
+ --color-stage-1: var(--stage-1);
123
+ --color-stage-2: var(--stage-2);
124
+ --color-stage-3: var(--stage-3);
125
+ --color-stage-4: var(--stage-4);
126
+ --color-stage-5: var(--stage-5);
127
+ --color-stage-6: var(--stage-6);
128
+
105
129
  /* Per-app accent (Layer 5). Resolves through [data-app] on <body>,
106
130
  falling back to the shared accent when no app is declared. */
107
131
  --color-app-accent: var(--app-accent, var(--role-accent));