@bsuite/theme 0.7.2 → 0.9.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 +1 -1
- package/src/css/braden.css +58 -0
- package/src/css/vars.css +71 -0
- package/src/preset-v4.css +35 -0
package/package.json
CHANGED
package/src/css/braden.css
CHANGED
|
@@ -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,77 @@
|
|
|
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
|
+
/* ═══ TYPE ═══ Lifted from the D2C contract, which specified a font
|
|
131
|
+
stack this package never shipped. Apps were left to pick their own, so
|
|
132
|
+
the estate ran system-ui, Inter and JetBrains Mono simultaneously while
|
|
133
|
+
the contract asked for one family. Same shape of gap as the heading
|
|
134
|
+
ramp: written down, never implemented. */
|
|
135
|
+
--font-display: 'Geist Variable', Geist, system-ui, sans-serif;
|
|
136
|
+
--font-body: 'Geist Variable', Geist, system-ui, sans-serif;
|
|
137
|
+
--font-mono: 'Geist Mono Variable', 'Geist Mono', ui-monospace, monospace;
|
|
138
|
+
--track-display: -0.028em;
|
|
139
|
+
--track-heading: -0.018em;
|
|
140
|
+
--track-body: 0em;
|
|
141
|
+
--track-eyebrow: 0.09em;
|
|
142
|
+
|
|
143
|
+
/* ═══ INFORMATIONAL SCALE — categorical, NOT semantic ═══
|
|
144
|
+
Added 2026-08-03 by operator ruling: "informational hues might be handy
|
|
145
|
+
to stand out against the style colour palette."
|
|
146
|
+
|
|
147
|
+
Role tokens describe STATE. They cannot describe CATEGORY — which
|
|
148
|
+
pipeline stage, which user role, which product tile. Apps that needed a
|
|
149
|
+
category reached for raw Tailwind instead, which is how one role-badge
|
|
150
|
+
table came to use purple, indigo, blue, violet and sky as its only
|
|
151
|
+
distinguishing signal.
|
|
152
|
+
|
|
153
|
+
NUMBERED, NOT NAMED, deliberately. Call one of these "moss green" and
|
|
154
|
+
it will be used for success within a week. A number says what these
|
|
155
|
+
are: interchangeable slots carrying no meaning of their own.
|
|
156
|
+
NEVER use an --info-* for state. State has role tokens.
|
|
157
|
+
|
|
158
|
+
Derived, not picked by eye: Vienot-Brettel-Mollon dichromat simulation,
|
|
159
|
+
DeltaE in OKLab, scored as the WORST case across normal, deuteranope and
|
|
160
|
+
protanope vision. Two constraints — perceptual distance keeps them
|
|
161
|
+
DISTINGUISHABLE, a >=28 degree hue gap keeps them looking CATEGORICAL
|
|
162
|
+
rather than like a light/dark pair of one colour. Every one is also
|
|
163
|
+
held away from the brand roles, which is what "stand out against the
|
|
164
|
+
style palette" requires: an informational badge must not read as a
|
|
165
|
+
primary action or an error.
|
|
166
|
+
Reproduce with scripts/design-informational-hues.py
|
|
167
|
+
|
|
168
|
+
LIMIT: worst-case separation is ~0.06-0.07, against >=0.156 for the
|
|
169
|
+
semantic pairs. That is 10x better than the purple-vs-blue pairing this
|
|
170
|
+
system rejected (0.006), but it is NOT the semantic standard and cannot
|
|
171
|
+
be — 8 mutually-distinct categories that also avoid 6 reserved brand
|
|
172
|
+
colours is a harder problem than 6 roles. So: colour is never the sole
|
|
173
|
+
signifier for a category. Always pair with a label or an icon. Past 8
|
|
174
|
+
categories, stop adding hues and add a second dimension. */
|
|
175
|
+
--info-1: oklch(0.460 0.140 0.0);
|
|
176
|
+
--info-2: oklch(0.700 0.140 42.0);
|
|
177
|
+
--info-3: oklch(0.540 0.140 138.0);
|
|
178
|
+
--info-4: oklch(0.700 0.140 168.0);
|
|
179
|
+
--info-5: oklch(0.780 0.140 228.0);
|
|
180
|
+
--info-6: oklch(0.700 0.140 258.0);
|
|
181
|
+
--info-7: oklch(0.500 0.140 300.0);
|
|
182
|
+
--info-8: oklch(0.460 0.140 330.0);
|
|
183
|
+
|
|
184
|
+
/* ═══ STAGE RAMP — progression, one hue, ascending lightness ═══
|
|
185
|
+
For an ORDERED sequence (pipeline stages), not a category set. A ramp
|
|
186
|
+
encodes direction: "further along" is visible at a glance, and it
|
|
187
|
+
survives greyscale and both dichromacies because lightness carries it.
|
|
188
|
+
Arbitrary per-stage hues cannot do that — a reader has to LEARN that
|
|
189
|
+
sky comes after amber.
|
|
190
|
+
|
|
191
|
+
Progression only. OUTCOMES are state, not stage: a hired candidate is
|
|
192
|
+
--role-success, a rejected one --role-error, a withdrawn one muted.
|
|
193
|
+
Do not extend this ramp to cover them. */
|
|
194
|
+
--stage-1: oklch(0.860 0.130 262.9);
|
|
195
|
+
--stage-2: oklch(0.780 0.130 262.9);
|
|
196
|
+
--stage-3: oklch(0.700 0.130 262.9);
|
|
197
|
+
--stage-4: oklch(0.620 0.130 262.9);
|
|
198
|
+
--stage-5: oklch(0.540 0.130 262.9);
|
|
199
|
+
--stage-6: oklch(0.460 0.130 262.9);
|
|
200
|
+
|
|
130
201
|
/* AA-safe text renderings of the saturated roles on light surfaces.
|
|
131
202
|
A saturated fill colour is not a legible text colour; these are the
|
|
132
203
|
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));
|
|
@@ -144,6 +168,17 @@
|
|
|
144
168
|
--color-text-on-success: var(--text-on-success);
|
|
145
169
|
--color-text-on-warning: var(--text-on-warning);
|
|
146
170
|
|
|
171
|
+
/* ============================================================
|
|
172
|
+
TYPE — the contract's stack, bridged to Tailwind's font-* utilities.
|
|
173
|
+
`font-sans` and `font-mono` are what components actually write, so
|
|
174
|
+
without this bridge the tokens exist and nothing uses them. Every D2C
|
|
175
|
+
app had been declaring its own --font-sans locally instead, which is how
|
|
176
|
+
the estate came to run system-ui, Inter and JetBrains Mono at once.
|
|
177
|
+
============================================================ */
|
|
178
|
+
--font-sans: var(--font-body);
|
|
179
|
+
--font-display: var(--font-display);
|
|
180
|
+
--font-mono: var(--font-mono);
|
|
181
|
+
|
|
147
182
|
/* ============================================================
|
|
148
183
|
ANIMATIONS
|
|
149
184
|
============================================================ */
|