@oxyhq/bloom 0.74.2 → 0.74.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.
@@ -25,12 +25,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
25
25
  "primaryLight": "rgb(36 26 14)",
26
26
  "primarySubtle": "rgba(202, 129, 0, 0.24)",
27
27
  "primarySubtleForeground": "rgb(255 221 184)",
28
- "secondary": "rgb(0 127 153)",
29
- "secondaryForeground": "rgb(255 255 255)",
28
+ "secondary": "rgb(0 213 255)",
29
+ "secondaryForeground": "rgb(0 0 0)",
30
30
  "shadow": "rgba(0, 0, 0, 0.3)",
31
31
  "success": "rgb(16 185 129)",
32
- "tertiary": "rgb(78 98 255)",
33
- "tertiaryForeground": "rgb(255 255 255)",
32
+ "tertiary": "rgb(111 128 255)",
33
+ "tertiaryForeground": "rgb(0 0 0)",
34
34
  "text": "rgb(244 223 203)",
35
35
  "textSecondary": "rgb(217 195 171)",
36
36
  "textTertiary": "rgb(161 141 120)",
@@ -95,12 +95,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
95
95
  "primaryLight": "rgb(21 28 36)",
96
96
  "primarySubtle": "rgba(0, 151, 237, 0.24)",
97
97
  "primarySubtleForeground": "rgb(207 229 255)",
98
- "secondary": "rgb(214 58 43)",
99
- "secondaryForeground": "rgb(255 255 255)",
98
+ "secondary": "rgb(247 81 63)",
99
+ "secondaryForeground": "rgb(0 0 0)",
100
100
  "shadow": "rgba(0, 0, 0, 0.3)",
101
101
  "success": "rgb(16 185 129)",
102
- "tertiary": "rgb(134 116 0)",
103
- "tertiaryForeground": "rgb(255 255 255)",
102
+ "tertiary": "rgb(252 220 0)",
103
+ "tertiaryForeground": "rgb(0 0 0)",
104
104
  "text": "rgb(220 227 238)",
105
105
  "textSecondary": "rgb(190 199 212)",
106
106
  "textTertiary": "rgb(136 146 158)",
@@ -165,12 +165,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
165
165
  "primaryLight": "rgb(24 29 18)",
166
166
  "primarySubtle": "rgba(87, 163, 0, 0.24)",
167
167
  "primarySubtleForeground": "rgb(138 254 0)",
168
- "secondary": "rgb(92 94 255)",
169
- "secondaryForeground": "rgb(255 255 255)",
168
+ "secondary": "rgb(122 125 255)",
169
+ "secondaryForeground": "rgb(0 0 0)",
170
170
  "shadow": "rgba(0, 0, 0, 0.3)",
171
171
  "success": "rgb(16 185 129)",
172
- "tertiary": "rgb(203 50 163)",
173
- "tertiaryForeground": "rgb(255 255 255)",
172
+ "tertiary": "rgb(232 76 188)",
173
+ "tertiaryForeground": "rgb(0 0 0)",
174
174
  "text": "rgb(223 229 211)",
175
175
  "textSecondary": "rgb(193 202 180)",
176
176
  "textTertiary": "rgb(139 148 128)",
@@ -235,12 +235,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
235
235
  "primaryLight": "rgb(19 30 24)",
236
236
  "primarySubtle": "rgba(0, 165, 114, 0.24)",
237
237
  "primarySubtleForeground": "rgb(71 255 184)",
238
- "secondary": "rgb(216 52 80)",
239
- "secondaryForeground": "rgb(255 255 255)",
238
+ "secondary": "rgb(247 76 101)",
239
+ "secondaryForeground": "rgb(0 0 0)",
240
240
  "shadow": "rgba(0, 0, 0, 0.3)",
241
241
  "success": "rgb(16 185 129)",
242
- "tertiary": "rgb(165 64 234)",
243
- "tertiaryForeground": "rgb(255 255 255)",
242
+ "tertiary": "rgb(189 94 255)",
243
+ "tertiaryForeground": "rgb(0 0 0)",
244
244
  "text": "rgb(217 230 220)",
245
245
  "textSecondary": "rgb(186 203 191)",
246
246
  "textTertiary": "rgb(132 149 138)",
@@ -305,12 +305,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
305
305
  "primaryLight": "rgb(17 30 28)",
306
306
  "primarySubtle": "rgba(0, 163, 146, 0.24)",
307
307
  "primarySubtleForeground": "rgb(0 254 229)",
308
- "secondary": "rgb(212 63 10)",
309
- "secondaryForeground": "rgb(255 255 255)",
308
+ "secondary": "rgb(244 86 35)",
309
+ "secondaryForeground": "rgb(0 0 0)",
310
310
  "shadow": "rgba(0, 0, 0, 0.3)",
311
311
  "success": "rgb(16 185 129)",
312
- "tertiary": "rgb(193 53 190)",
313
- "tertiaryForeground": "rgb(255 255 255)",
312
+ "tertiary": "rgb(227 85 221)",
313
+ "tertiaryForeground": "rgb(0 0 0)",
314
314
  "text": "rgb(215 230 225)",
315
315
  "textSecondary": "rgb(184 202 198)",
316
316
  "textTertiary": "rgb(130 148 144)",
@@ -375,12 +375,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
375
375
  "primaryLight": "rgb(38 24 17)",
376
376
  "primarySubtle": "rgba(237, 105, 0, 0.24)",
377
377
  "primarySubtleForeground": "rgb(255 219 202)",
378
- "secondary": "rgb(0 130 130)",
379
- "secondaryForeground": "rgb(255 255 255)",
378
+ "secondary": "rgb(0 255 254)",
379
+ "secondaryForeground": "rgb(0 0 0)",
380
380
  "shadow": "rgba(0, 0, 0, 0.3)",
381
381
  "success": "rgb(16 185 129)",
382
- "tertiary": "rgb(81 97 255)",
383
- "tertiaryForeground": "rgb(255 255 255)",
382
+ "tertiary": "rgb(114 127 255)",
383
+ "tertiaryForeground": "rgb(0 0 0)",
384
384
  "text": "rgb(248 221 209)",
385
385
  "textSecondary": "rgb(223 192 178)",
386
386
  "textTertiary": "rgb(166 139 126)",
@@ -445,12 +445,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
445
445
  "primaryLight": "rgb(33 25 34)",
446
446
  "primarySubtle": "rgba(213, 86, 255, 0.24)",
447
447
  "primarySubtleForeground": "rgb(251 215 255)",
448
- "secondary": "rgb(0 132 104)",
449
- "secondaryForeground": "rgb(255 255 255)",
448
+ "secondary": "rgb(0 253 200)",
449
+ "secondaryForeground": "rgb(0 0 0)",
450
450
  "shadow": "rgba(0, 0, 0, 0.3)",
451
451
  "success": "rgb(16 185 129)",
452
- "tertiary": "rgb(53 133 0)",
453
- "tertiaryForeground": "rgb(255 255 255)",
452
+ "tertiary": "rgb(142 249 86)",
453
+ "tertiaryForeground": "rgb(0 0 0)",
454
454
  "text": "rgb(237 222 235)",
455
455
  "textSecondary": "rgb(210 193 210)",
456
456
  "textTertiary": "rgb(155 140 155)",
@@ -515,12 +515,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
515
515
  "primaryLight": "rgb(37 24 29)",
516
516
  "primarySubtle": "rgba(255, 69, 163, 0.24)",
517
517
  "primarySubtleForeground": "rgb(255 217 228)",
518
- "secondary": "rgb(0 129 139)",
519
- "secondaryForeground": "rgb(255 255 255)",
518
+ "secondary": "rgb(0 237 255)",
519
+ "secondaryForeground": "rgb(0 0 0)",
520
520
  "shadow": "rgba(0, 0, 0, 0.3)",
521
521
  "success": "rgb(16 185 129)",
522
- "tertiary": "rgb(0 135 37)",
523
- "tertiaryForeground": "rgb(255 255 255)",
522
+ "tertiary": "rgb(100 250 110)",
523
+ "tertiaryForeground": "rgb(0 0 0)",
524
524
  "text": "rgb(245 220 227)",
525
525
  "textSecondary": "rgb(219 191 200)",
526
526
  "textTertiary": "rgb(163 138 146)",
@@ -585,12 +585,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
585
585
  "primaryLight": "rgb(29 26 36)",
586
586
  "primarySubtle": "rgba(160, 120, 255, 0.24)",
587
587
  "primarySubtleForeground": "rgb(233 221 255)",
588
- "secondary": "rgb(144 112 0)",
589
- "secondaryForeground": "rgb(255 255 255)",
588
+ "secondary": "rgb(254 199 0)",
589
+ "secondaryForeground": "rgb(0 0 0)",
590
590
  "shadow": "rgba(0, 0, 0, 0.3)",
591
591
  "success": "rgb(16 185 129)",
592
- "tertiary": "rgb(10 136 0)",
593
- "tertiaryForeground": "rgb(255 255 255)",
592
+ "tertiary": "rgb(118 245 94)",
593
+ "tertiaryForeground": "rgb(0 0 0)",
594
594
  "text": "rgb(231 224 238)",
595
595
  "textSecondary": "rgb(203 195 213)",
596
596
  "textTertiary": "rgb(148 142 159)",
@@ -655,12 +655,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
655
655
  "primaryLight": "rgb(39 24 23)",
656
656
  "primarySubtle": "rgba(255, 84, 81, 0.24)",
657
657
  "primarySubtleForeground": "rgb(255 218 215)",
658
- "secondary": "rgb(0 126 166)",
659
- "secondaryForeground": "rgb(255 255 255)",
658
+ "secondary": "rgb(0 193 253)",
659
+ "secondaryForeground": "rgb(0 0 0)",
660
660
  "shadow": "rgba(0, 0, 0, 0.3)",
661
661
  "success": "rgb(16 185 129)",
662
- "tertiary": "rgb(0 135 45)",
663
- "tertiaryForeground": "rgb(255 255 255)",
662
+ "tertiary": "rgb(90 250 115)",
663
+ "tertiaryForeground": "rgb(0 0 0)",
664
664
  "text": "rgb(249 220 217)",
665
665
  "textSecondary": "rgb(223 191 188)",
666
666
  "textTertiary": "rgb(167 138 136)",
@@ -725,12 +725,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
725
725
  "primaryLight": "rgb(20 29 35)",
726
726
  "primarySubtle": "rgba(0, 154, 218, 0.24)",
727
727
  "primarySubtleForeground": "rgb(201 230 255)",
728
- "secondary": "rgb(213 61 30)",
729
- "secondaryForeground": "rgb(255 255 255)",
728
+ "secondary": "rgb(246 83 51)",
729
+ "secondaryForeground": "rgb(0 0 0)",
730
730
  "shadow": "rgba(0, 0, 0, 0.3)",
731
731
  "success": "rgb(16 185 129)",
732
- "tertiary": "rgb(144 112 0)",
733
- "tertiaryForeground": "rgb(255 255 255)",
732
+ "tertiary": "rgb(253 200 0)",
733
+ "tertiaryForeground": "rgb(0 0 0)",
734
734
  "text": "rgb(219 227 237)",
735
735
  "textSecondary": "rgb(188 200 211)",
736
736
  "textTertiary": "rgb(134 146 157)",
@@ -795,12 +795,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
795
795
  "primaryLight": "rgb(17 29 32)",
796
796
  "primarySubtle": "rgba(0, 159, 177, 0.24)",
797
797
  "primarySubtleForeground": "rgb(154 240 255)",
798
- "secondary": "rgb(213 49 120)",
799
- "secondaryForeground": "rgb(255 255 255)",
798
+ "secondary": "rgb(243 74 143)",
799
+ "secondaryForeground": "rgb(0 0 0)",
800
800
  "shadow": "rgba(0, 0, 0, 0.3)",
801
801
  "success": "rgb(16 185 129)",
802
- "tertiary": "rgb(174 97 0)",
803
- "tertiaryForeground": "rgb(255 255 255)",
802
+ "tertiary": "rgb(253 144 0)",
803
+ "tertiaryForeground": "rgb(0 0 0)",
804
804
  "text": "rgb(215 229 232)",
805
805
  "textSecondary": "rgb(184 202 205)",
806
806
  "textTertiary": "rgb(131 148 151)",
@@ -865,12 +865,12 @@ exports[`theme.colors snapshot for all presets (catches unintended palette shift
865
865
  "primaryLight": "rgb(33 27 13)",
866
866
  "primarySubtle": "rgba(182, 138, 0, 0.24)",
867
867
  "primarySubtleForeground": "rgb(255 223 154)",
868
- "secondary": "rgb(0 125 173)",
869
- "secondaryForeground": "rgb(255 255 255)",
868
+ "secondary": "rgb(0 186 255)",
869
+ "secondaryForeground": "rgb(0 0 0)",
870
870
  "shadow": "rgba(0, 0, 0, 0.3)",
871
871
  "success": "rgb(16 185 129)",
872
- "tertiary": "rgb(127 81 255)",
873
- "tertiaryForeground": "rgb(255 255 255)",
872
+ "tertiary": "rgb(149 115 255)",
873
+ "tertiaryForeground": "rgb(0 0 0)",
874
874
  "text": "rgb(238 225 202)",
875
875
  "textSecondary": "rgb(211 197 170)",
876
876
  "textTertiary": "rgb(156 143 119)",
@@ -116,23 +116,4 @@ describe('colour policy legibility', () => {
116
116
  expect(avoidableBlack).toEqual([]);
117
117
  });
118
118
 
119
- // A PRODUCT decision, not a property of the colour maths, which is exactly why
120
- // it needs an assertion: the accent fill is what a FAB and a compose button
121
- // paint with, and those carry a white label. It has silently flipped to black
122
- // twice — both times as a side effect of tuning the accent's TONE for hue
123
- // fidelity, with nothing in the suite watching the label.
124
- it('accent fills carry a WHITE label in both modes', () => {
125
- const black: string[] = [];
126
- for (const preset of APP_COLOR_NAMES) {
127
- for (const mode of ['light', 'dark'] as const) {
128
- const tokens = getResolvedTokens(preset, mode);
129
- for (const family of ['secondary', 'tertiary'] as const) {
130
- if (tokens[`--${family}-foreground`] !== 'rgb(255 255 255)') {
131
- black.push(`${preset}/${mode} --${family}`);
132
- }
133
- }
134
- }
135
- }
136
- expect(black).toEqual([]);
137
- });
138
- });
119
+ });
@@ -98,16 +98,15 @@ const LIGHT_FILL_TONE = 45;
98
98
  const DARK_FLOOR = 58;
99
99
 
100
100
  /**
101
- * Accent fills stop here in dark, and the ceiling is not aesthetic.
101
+ * Accent fills sit at their hue's PEAK tone in dark where the hue is most
102
+ * itself, so a lime reads as lime rather than olive.
102
103
  *
103
- * White text needs a fill at or below tone 49, and an accent is a BUTTON — the
104
- * FAB, the compose action where white on colour is the convention. Sitting the
105
- * accent at its hue's peak tone makes a lime look like lime, but peaks live at
106
- * tone 88 for that family, and no label survives up there except black. The hue
107
- * work still stands (a magenta seed's accent is the lime family, not the emerald
108
- * one it used to be); only its brightness is capped so the label can be white.
104
+ * The cost is fixed and cannot be engineered away: peaks for that family live
105
+ * around tone 88, and white text needs a fill at or below 49, so these buttons
106
+ * carry a BLACK label. Capping the tone to win the white label back turns the
107
+ * same accents dull measured on blue, rgb(252 220 0) becomes rgb(134 116 0).
108
+ * The bright colour is the deliberate choice.
109
109
  */
110
- const DARK_ACCENT_TONE = 49;
111
110
 
112
111
  /** Chroma ceiling for an accent FILL — the brand palette's own maximum, not the gamut's. */
113
112
  const ACCENT_CHROMA = 80;
@@ -116,6 +115,18 @@ const ACCENT_CHROMA = 80;
116
115
  const TEXT_TONE = { light: 40, dark: 80 } as const;
117
116
  const TEXT_CHROMA = 60;
118
117
 
118
+ /**
119
+ * The tone a `-strong` accent sits at: deep enough to carry a WHITE label.
120
+ *
121
+ * `--tertiary` is the vivid accent — a tile, a chip, a block of colour — and it
122
+ * sits at its hue's peak tone so a lime reads as lime. A solid BUTTON is a
123
+ * different job: it wants the same hue with white on it, which needs tone <= 49.
124
+ * One token cannot do both, exactly as `--primary` could not be both the fill
125
+ * and the legible text accent. Capping `--tertiary` itself to win the label back
126
+ * dulls every other use of it, so the button gets its own member instead.
127
+ */
128
+ const STRONG_TONE = 49;
129
+
119
130
  /** The `-subtle` tint is mixed from a BRIGHT tone at low alpha, never a dark one at high alpha. */
120
131
  const SUBTLE_SOURCE_TONE = 60;
121
132
  const SUBTLE_ALPHA = { light: 0.13, dark: 0.24 } as const;
@@ -310,7 +321,7 @@ export function buildPolicyTokens(
310
321
  // black. The accent chroma cap already keeps these hues out of neon territory,
311
322
  // and the hue itself is the caller's brand rather than ours to move. The
312
323
  // analyzer still runs where it was designed to, inside `color-roles`.
313
- const tone = isDark ? DARK_ACCENT_TONE : LIGHT_FILL_TONE;
324
+ const tone = isDark ? Math.max(peakTone(hue), DARK_FLOOR) : LIGHT_FILL_TONE;
314
325
  const pair = fillPair(fillPalette, tone);
315
326
  tokens[`--${role}`] = pair.fill;
316
327
  tokens[`--${role}-foreground`] = pair.foreground;
@@ -319,6 +330,12 @@ export function buildPolicyTokens(
319
330
  vividPalette.tone(SUBTLE_SOURCE_TONE),
320
331
  isDark ? SUBTLE_ALPHA.dark : SUBTLE_ALPHA.light,
321
332
  );
333
+ // The solid-button member: same hue, deep enough for a white label in both
334
+ // modes. In light it lands on the ordinary fill tone, so a button that uses
335
+ // it there is identical to one that used the accent.
336
+ const strong = fillPair(fillPalette, isDark ? STRONG_TONE : LIGHT_FILL_TONE);
337
+ tokens[`--${role}-strong`] = strong.fill;
338
+ tokens[`--${role}-strong-foreground`] = strong.foreground;
322
339
  }
323
340
 
324
341
  // Categorical chart ramp: five hues spread evenly from the seed at one tone.
@@ -61,8 +61,12 @@ export const CANONICAL_TOKENS = [
61
61
  'primary-subtle',
62
62
  'secondary-text',
63
63
  'secondary-subtle',
64
+ 'secondary-strong',
65
+ 'secondary-strong-foreground',
64
66
  'tertiary-text',
65
67
  'tertiary-subtle',
68
+ 'tertiary-strong',
69
+ 'tertiary-strong-foreground',
66
70
 
67
71
  // --- semantic status, themed per mode ---
68
72
  // Replaces four frozen hexes that all FAILED AA under white text (warning at