@crewlethq/tokens 0.6.0 → 0.6.1
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 +15 -5
- package/dist/css/themes.css +6 -6
- package/dist/themes.d.ts +6 -6
- package/dist/themes.js +6 -6
- package/package.json +1 -1
- package/test/palette.d.mts +6 -0
- package/test/palette.mjs +18 -0
- package/test/palette.test.mjs +16 -4
package/README.md
CHANGED
|
@@ -39,6 +39,15 @@ const accent = color.brand.accent;
|
|
|
39
39
|
CSS variables follow Style Dictionary's `--{group}-{path}` convention,
|
|
40
40
|
for example `var(--color-brand-accent)` or `var(--spacing-4)`.
|
|
41
41
|
|
|
42
|
+
## Changed in 0.6.1: the dark text ramp
|
|
43
|
+
|
|
44
|
+
In 0.6.0 the dark primary and tertiary text steps sat 1.98:1 apart, so a word a screen dims from the first step to the third (a calendar's days from the neighbouring month) read as a rounding rather than a step. The dark primary is lifted dE 0.30, and the palette suite now holds the step in every state.
|
|
45
|
+
|
|
46
|
+
| What changed | What to change | Details |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| `--color-text-primary` in dark is `#e7eaf3`. It was `#e6e9f2`. The fit placed the danger fill, its hover and the third chart series one 8-bit step from their 0.6.0 values beside it. | Nothing, for a stylesheet that reads the tokens. | [Surfaces](#surfaces) |
|
|
49
|
+
| In `@crewlethq/tokens/test/palette`, the rule `a dimmed word is a step from the word being read` is new, with the export `DIMMED_TEXT`: the primary and tertiary text steps clear 2:1 between themselves. | Nothing, unless an application's own palette override draws the two steps closer. | [The palette suite](#the-palette-suite) |
|
|
50
|
+
|
|
42
51
|
## Changed in 0.6.0: the default palette
|
|
43
52
|
|
|
44
53
|
The dark and light themes take the default palette approved on 4 October 2026: blue-black neutrals, a violet accent (`#725be6` in dark, `#735af2` in light) and a cyan working state. No token is renamed or removed; the themed values change. [`tokens/intent.json`](./tokens/intent.json) records the approved values, and every value the palette suite's floors moved names its approved value, the distance and the measurement in its own comment. The marketing root, `tokens.css` on its own, keeps its values.
|
|
@@ -165,6 +174,7 @@ Where an approved value failed one of the suite's floors, the floor won and the
|
|
|
165
174
|
| `--color-border-default` dark | `#14151a` | `#191b20` | 2.53 | dE 0.99 off the card, under 3 |
|
|
166
175
|
| `--color-border-default` light | `#f5f5f5` | `#e7e8ec` | 3.92 | dE 0.84 off the sheet and 1.02 off raised, under 3 |
|
|
167
176
|
| `--color-border-strong` dark | `#2b3245` | `#2d3448` | 0.85 | dE 2.43 as a raised chip's edge on an inset well inside a raised surface, under 3 |
|
|
177
|
+
| `--color-text-primary` dark | `#e6e9f2` | `#e7eaf3` | 0.30 | 1.98:1 from the tertiary step, under the 2:1 a dimmed word keeps |
|
|
168
178
|
| `--color-text-tertiary` dark | `#8a91a6` | `#9fa7bc` | 7.08 | 3.45:1 on a pressed row inside a raised surface |
|
|
169
179
|
| `--color-text-tertiary` light | `#5a6075` | `#585e73` | 0.71 | 4.37:1 on a pressed row on the frame |
|
|
170
180
|
| `--color-text-muted` light | `#8a90a3` | `#878d9f` | 1.04 | 2.69:1 on the frame, under the decoration band |
|
|
@@ -393,7 +403,7 @@ Both families are the approved palette's hues, or a move from them that the pale
|
|
|
393
403
|
|
|
394
404
|
| Token | Palette | Design | Shipped | Moved (dE) | Because |
|
|
395
405
|
| --- | --- | --- | --- | --- | --- |
|
|
396
|
-
| `--color-feedback-danger` | dark | `#f0506e` | `#
|
|
406
|
+
| `--color-feedback-danger` | dark | `#f0506e` | `#d73756` | 7.04 | white on it 3.46:1; dE 5.9 from done under deuteranopia; dE 4.9 from the chart green under deuteranopia |
|
|
397
407
|
| `--color-feedback-danger` | light | `#cc2a4a` | `#b9112c` | 5.75 | dE 7.2 from done under deuteranopia; dE 6.9 from the chart green under deuteranopia |
|
|
398
408
|
| `--color-feedback-warning` | dark | `#f0b429` | `#f0b425` | 0.17 | dE 9.8 from done under protanopia |
|
|
399
409
|
| `--color-feedback-warning` | light | `#ffb300` | `#c17300` | 19.65 | 1.52:1 as a mark on the frame |
|
|
@@ -405,7 +415,7 @@ Both families are the approved palette's hues, or a move from them that the pale
|
|
|
405
415
|
| `--color-data-1` | dark | `#3c7fec` | `#4d8ff6` | 4.75 | dE 9.7 from the accent under normal vision and 3.3 under deuteranopia |
|
|
406
416
|
| `--color-data-1` | light | `#4381e5` | `#5c76c3` | 5.71 | dE 4.5 from the accent under deuteranopia |
|
|
407
417
|
| `--color-data-2` | light | `#ed810c` | `#dd5920` | 9.59 | 2.29:1 as a mark on the frame |
|
|
408
|
-
| `--color-data-3` | dark | `#2fa24e` | `#
|
|
418
|
+
| `--color-data-3` | dark | `#2fa24e` | `#26b582` | 7.30 | dE 0.6 from danger under deuteranopia; dE 2.6 from the orange under protanopia |
|
|
409
419
|
| `--color-data-3` | light | `#2f9d4c` | `#00956e` | 5.75 | 2.94:1 as a mark on the frame; dE 5.6 from the yellow under protanopia; dE 7.9 from danger under deuteranopia |
|
|
410
420
|
| `--color-data-4` | light | `#edb302` | `#c27600` | 17.33 | 1.61:1 as a mark on the frame: a yellow dark enough to be seen on a light page is an ochre |
|
|
411
421
|
|
|
@@ -413,8 +423,8 @@ Every other state and series step ships as approved: the dark inks, dark success
|
|
|
413
423
|
|
|
414
424
|
In light, the yellow series sits beside the warning ochre (`#c27600` and `#c17300`). The approved palette drew the two a few steps apart, and both were darkened onto the same floor, a mark that clears 3:1 on the frame. Nothing in the suite keeps a series from a state other than the reserved red, and a series is read only inside a figure that names it.
|
|
415
425
|
|
|
416
|
-
- **The danger fill carries a white label**, on a toast's destructive action and on an upload's remove button, so it is dark enough for 4.5:1 in both palettes (4.
|
|
417
|
-
- **The reserved red is kept away from every series**: dE 14 under normal vision and 8 under protanopia and deuteranopia, where red, orange and green fall onto one axis. The approved chart green sat dE 0.
|
|
426
|
+
- **The danger fill carries a white label**, on a toast's destructive action and on an upload's remove button, so it is dark enough for 4.5:1 in both palettes (4.59:1 dark, 6.61:1 light), and its hover, `--color-feedback-danger-hover`, is a step darker again, the least a reader can see (dE 3.03 dark, 3.02 light). The palette suite holds the hover as it holds the primary action's: `a hovered destructive action is a visible step away from its label`.
|
|
427
|
+
- **The reserved red is kept away from every series**: dE 14 under normal vision and 8 under protanopia and deuteranopia, where red, orange and green fall onto one axis. The approved chart green sat dE 0.6 from the shipped red under deuteranopia.
|
|
418
428
|
- **Neighbouring series** sit dE 9 apart under every vision and dE 15 under normal vision. The second floor is new: on its own, the dichromat floor let a pair sit dE 9 apart for every reader, which to full-colour vision is two shades of one hue.
|
|
419
429
|
|
|
420
430
|
The marketing root keeps its own state and series values (`tokens/color.json`), which the suite measures in the `base` state.
|
|
@@ -438,7 +448,7 @@ The marketing root keeps its own state and series values (`tokens/color.json`),
|
|
|
438
448
|
|
|
439
449
|
## The palette suite
|
|
440
450
|
|
|
441
|
-
`test/palette.mjs` holds the rule table and the colour maths, and `test/palette.test.mjs` runs it over `dist/css` in import order, in every theme state: the base marketing root (`base`), the dark root (`dark`), light by media query (`light (media query)`) and light by attribute (`light (attribute)`), which are the keys `paletteStates()` returns. It measures every text step on every surface it can land on (the four opaque rungs in `OPAQUE_SURFACES`, and the translucent overlays composited over each of them), every ink on its own soft tint, every fill as a mark, the primary action's three fills under its label and the steps between them, the destructive action's fill and its hover under the same label, the focus ring, the control boundary, the rail's current row, the steps between the rungs, the hairline that finds a card and the strong hairline round a raised chip, whether a hovered and a pressed row can be seen, the hue separations under normal, protan and deuteranopic vision (the states from each other, the chart series from their neighbours and from the danger red, and every hue from the accent), and the structure of the theme file itself. A component suite that measures a colour of its own measures it on `OPAQUE_SURFACES` too, rather than on a list of surface names it keeps itself.
|
|
451
|
+
`test/palette.mjs` holds the rule table and the colour maths, and `test/palette.test.mjs` runs it over `dist/css` in import order, in every theme state: the base marketing root (`base`), the dark root (`dark`), light by media query (`light (media query)`) and light by attribute (`light (attribute)`), which are the keys `paletteStates()` returns. It measures every text step on every surface it can land on (the four opaque rungs in `OPAQUE_SURFACES`, and the translucent overlays composited over each of them), the step between a word and a dimmed one, every ink on its own soft tint, every fill as a mark, the primary action's three fills under its label and the steps between them, the destructive action's fill and its hover under the same label, the focus ring, the control boundary, the rail's current row, the steps between the rungs, the hairline that finds a card and the strong hairline round a raised chip, whether a hovered and a pressed row can be seen, the hue separations under normal, protan and deuteranopic vision (the states from each other, the chart series from their neighbours and from the danger red, and every hue from the accent), and the structure of the theme file itself. A component suite that measures a colour of its own measures it on `OPAQUE_SURFACES` too, rather than on a list of surface names it keeps itself.
|
|
442
452
|
|
|
443
453
|
The module is **published**, as `@crewlethq/tokens/test/palette`, so a consumer runs the same rules over the version it installed:
|
|
444
454
|
|
package/dist/css/themes.css
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
--color-surface-scrim: rgba(0, 0, 0, 0.6);
|
|
26
26
|
--color-surface-veil: rgba(7, 8, 13, 0.65);
|
|
27
27
|
--color-surface-inverse: #fcfcfc;
|
|
28
|
-
--color-text-primary: #
|
|
28
|
+
--color-text-primary: #e7eaf3;
|
|
29
29
|
--color-text-secondary: #a9b0c3;
|
|
30
30
|
--color-text-tertiary: #9fa7bc;
|
|
31
31
|
--color-text-muted: #5a6176;
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
--color-feedback-success-ink: #74dcae;
|
|
49
49
|
--color-feedback-warning: #f0b425;
|
|
50
50
|
--color-feedback-warning-ink: #f6cd72;
|
|
51
|
-
--color-feedback-danger: #
|
|
52
|
-
--color-feedback-danger-hover: #
|
|
51
|
+
--color-feedback-danger: #d73756;
|
|
52
|
+
--color-feedback-danger-hover: #cc2b4e;
|
|
53
53
|
--color-feedback-danger-ink: #ff9fb0;
|
|
54
54
|
--color-feedback-info: #61d0ff;
|
|
55
55
|
--color-feedback-info-ink: #8ad6fb;
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
--color-feedback-success-line: rgba(52, 201, 139, 0.3);
|
|
58
58
|
--color-feedback-warning-soft: rgba(240, 180, 37, 0.12);
|
|
59
59
|
--color-feedback-warning-line: rgba(240, 180, 37, 0.3);
|
|
60
|
-
--color-feedback-danger-soft: rgba(
|
|
61
|
-
--color-feedback-danger-line: rgba(
|
|
60
|
+
--color-feedback-danger-soft: rgba(215, 55, 86, 0.12);
|
|
61
|
+
--color-feedback-danger-line: rgba(215, 55, 86, 0.3);
|
|
62
62
|
--color-feedback-info-soft: rgba(97, 208, 255, 0.12);
|
|
63
63
|
--color-feedback-info-line: rgba(97, 208, 255, 0.3);
|
|
64
64
|
--color-data-1: #4d8ff6;
|
|
65
65
|
--color-data-2: #e67737;
|
|
66
|
-
--color-data-3: #
|
|
66
|
+
--color-data-3: #26b582;
|
|
67
67
|
--color-data-4: #eab106;
|
|
68
68
|
--color-data-other: #6a7186;
|
|
69
69
|
--color-node-purple: #8e6ed4;
|
package/dist/themes.d.ts
CHANGED
|
@@ -141,7 +141,7 @@ export declare const themes: {
|
|
|
141
141
|
readonly inverse: "#fcfcfc";
|
|
142
142
|
};
|
|
143
143
|
readonly text: {
|
|
144
|
-
readonly primary: "#
|
|
144
|
+
readonly primary: "#e7eaf3";
|
|
145
145
|
readonly secondary: "#a9b0c3";
|
|
146
146
|
readonly tertiary: "#9fa7bc";
|
|
147
147
|
readonly muted: "#5a6176";
|
|
@@ -170,8 +170,8 @@ export declare const themes: {
|
|
|
170
170
|
readonly successInk: "#74dcae";
|
|
171
171
|
readonly warning: "#f0b425";
|
|
172
172
|
readonly warningInk: "#f6cd72";
|
|
173
|
-
readonly danger: "#
|
|
174
|
-
readonly dangerHover: "#
|
|
173
|
+
readonly danger: "#d73756";
|
|
174
|
+
readonly dangerHover: "#cc2b4e";
|
|
175
175
|
readonly dangerInk: "#ff9fb0";
|
|
176
176
|
readonly info: "#61d0ff";
|
|
177
177
|
readonly infoInk: "#8ad6fb";
|
|
@@ -179,15 +179,15 @@ export declare const themes: {
|
|
|
179
179
|
readonly successLine: "rgba(52, 201, 139, 0.3)";
|
|
180
180
|
readonly warningSoft: "rgba(240, 180, 37, 0.12)";
|
|
181
181
|
readonly warningLine: "rgba(240, 180, 37, 0.3)";
|
|
182
|
-
readonly dangerSoft: "rgba(
|
|
183
|
-
readonly dangerLine: "rgba(
|
|
182
|
+
readonly dangerSoft: "rgba(215, 55, 86, 0.12)";
|
|
183
|
+
readonly dangerLine: "rgba(215, 55, 86, 0.3)";
|
|
184
184
|
readonly infoSoft: "rgba(97, 208, 255, 0.12)";
|
|
185
185
|
readonly infoLine: "rgba(97, 208, 255, 0.3)";
|
|
186
186
|
};
|
|
187
187
|
readonly data: {
|
|
188
188
|
readonly "1": "#4d8ff6";
|
|
189
189
|
readonly "2": "#e67737";
|
|
190
|
-
readonly "3": "#
|
|
190
|
+
readonly "3": "#26b582";
|
|
191
191
|
readonly "4": "#eab106";
|
|
192
192
|
readonly other: "#6a7186";
|
|
193
193
|
};
|
package/dist/themes.js
CHANGED
|
@@ -142,7 +142,7 @@ export const themes = {
|
|
|
142
142
|
"inverse": "#fcfcfc"
|
|
143
143
|
},
|
|
144
144
|
"text": {
|
|
145
|
-
"primary": "#
|
|
145
|
+
"primary": "#e7eaf3",
|
|
146
146
|
"secondary": "#a9b0c3",
|
|
147
147
|
"tertiary": "#9fa7bc",
|
|
148
148
|
"muted": "#5a6176",
|
|
@@ -171,8 +171,8 @@ export const themes = {
|
|
|
171
171
|
"successInk": "#74dcae",
|
|
172
172
|
"warning": "#f0b425",
|
|
173
173
|
"warningInk": "#f6cd72",
|
|
174
|
-
"danger": "#
|
|
175
|
-
"dangerHover": "#
|
|
174
|
+
"danger": "#d73756",
|
|
175
|
+
"dangerHover": "#cc2b4e",
|
|
176
176
|
"dangerInk": "#ff9fb0",
|
|
177
177
|
"info": "#61d0ff",
|
|
178
178
|
"infoInk": "#8ad6fb",
|
|
@@ -180,15 +180,15 @@ export const themes = {
|
|
|
180
180
|
"successLine": "rgba(52, 201, 139, 0.3)",
|
|
181
181
|
"warningSoft": "rgba(240, 180, 37, 0.12)",
|
|
182
182
|
"warningLine": "rgba(240, 180, 37, 0.3)",
|
|
183
|
-
"dangerSoft": "rgba(
|
|
184
|
-
"dangerLine": "rgba(
|
|
183
|
+
"dangerSoft": "rgba(215, 55, 86, 0.12)",
|
|
184
|
+
"dangerLine": "rgba(215, 55, 86, 0.3)",
|
|
185
185
|
"infoSoft": "rgba(97, 208, 255, 0.12)",
|
|
186
186
|
"infoLine": "rgba(97, 208, 255, 0.3)"
|
|
187
187
|
},
|
|
188
188
|
"data": {
|
|
189
189
|
"1": "#4d8ff6",
|
|
190
190
|
"2": "#e67737",
|
|
191
|
-
"3": "#
|
|
191
|
+
"3": "#26b582",
|
|
192
192
|
"4": "#eab106",
|
|
193
193
|
"other": "#6a7186"
|
|
194
194
|
},
|
package/package.json
CHANGED
package/test/palette.d.mts
CHANGED
|
@@ -90,6 +90,12 @@ export const OPAQUE_SURFACES: readonly string[];
|
|
|
90
90
|
*/
|
|
91
91
|
export const TEXT_STEPS: readonly (readonly [string, number])[];
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* A dimmed word against the word being read, as [read, dimmed, contrast]: the
|
|
95
|
+
* two text steps clear that contrast between themselves.
|
|
96
|
+
*/
|
|
97
|
+
export const DIMMED_TEXT: readonly [string, string, number];
|
|
98
|
+
|
|
93
99
|
/**
|
|
94
100
|
* The steps of the ladder, each as [rule, upper rung, lower rung, the dE the
|
|
95
101
|
* upper rung has to sit off the lower one].
|
package/test/palette.mjs
CHANGED
|
@@ -155,6 +155,18 @@ export const TEXT_STEPS = [
|
|
|
155
155
|
['--color-text-tertiary', 4.5],
|
|
156
156
|
];
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* A DIMMED word against the word being read, as [read, dimmed, contrast]: the
|
|
160
|
+
* primary step and the tertiary one. A screen dims what is not its subject by
|
|
161
|
+
* dropping it from the first step to the third (a calendar's days from the
|
|
162
|
+
* neighbouring month, a resolved row under an open one), and both are facts,
|
|
163
|
+
* so each clears its own floor above. What this holds is that the two are a
|
|
164
|
+
* STEP apart rather than a rounding: 2:1 between the inks themselves. A ramp
|
|
165
|
+
* squeezed from both ends, a dimmer primary over a tertiary lifted for its
|
|
166
|
+
* floor on a pressed raised row, can keep every floor and lose the step.
|
|
167
|
+
*/
|
|
168
|
+
export const DIMMED_TEXT = ['--color-text-primary', '--color-text-tertiary', 2];
|
|
169
|
+
|
|
158
170
|
/** A hue used as TEXT on a surface. */
|
|
159
171
|
export const INK_STEPS = [
|
|
160
172
|
'--color-brand-accent-ink',
|
|
@@ -681,6 +693,12 @@ function checkState(state, values, profile, push) {
|
|
|
681
693
|
const low = worst(colour(name), all);
|
|
682
694
|
say('text step clears its floor', low.ratio >= floor, name, low.ratio, `${low.ratio.toFixed(2)}:1 >= ${floor} (worst on ${low.name})`);
|
|
683
695
|
}
|
|
696
|
+
{
|
|
697
|
+
// A dimmed word against the word being read. See DIMMED_TEXT.
|
|
698
|
+
const [read, dimmed, floor] = DIMMED_TEXT;
|
|
699
|
+
const ratio = contrast(colour(read), colour(dimmed));
|
|
700
|
+
say('a dimmed word is a step from the word being read', ratio >= floor, `${read} vs ${dimmed}`, ratio, `${ratio.toFixed(2)}:1 >= ${floor}`);
|
|
701
|
+
}
|
|
684
702
|
|
|
685
703
|
{
|
|
686
704
|
// It exists for a hairline glyph and a disabled affordance. The assertion
|
package/test/palette.test.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
DATA_ADJACENT_DE,
|
|
23
23
|
DATA_ADJACENT_NORMAL_DE,
|
|
24
24
|
describeFailure,
|
|
25
|
+
DIMMED_TEXT,
|
|
25
26
|
fromOklab,
|
|
26
27
|
hex,
|
|
27
28
|
oklabToLinear,
|
|
@@ -156,6 +157,17 @@ describe('the palette', () => {
|
|
|
156
157
|
assert.ok(onBase.includes('text step clears its floor'));
|
|
157
158
|
});
|
|
158
159
|
|
|
160
|
+
test('a dimmed word is measured in every state, and one a rounding from the word being read is caught', () => {
|
|
161
|
+
const DIMMED_RULE = 'a dimmed word is a step from the word being read';
|
|
162
|
+
assert.deepEqual(DIMMED_TEXT, ['--color-text-primary', '--color-text-tertiary', 2]);
|
|
163
|
+
for (const state of STATES) {
|
|
164
|
+
assert.equal(checks.filter((check) => check.state === state && check.rule === DIMMED_RULE).length, 1, state);
|
|
165
|
+
}
|
|
166
|
+
// The tertiary step lifted onto the secondary one: each clears its own
|
|
167
|
+
// floor, and the step between the first and the third is gone.
|
|
168
|
+
assert.deepEqual(failuresAfter('dark', '--color-text-tertiary', typed.dark.color.text.secondary), [DIMMED_RULE]);
|
|
169
|
+
});
|
|
170
|
+
|
|
159
171
|
test('the theme layer is dark first, and wins over the token layer', () => {
|
|
160
172
|
// themes.css is imported second on purpose. If that ever stopped being
|
|
161
173
|
// true the dark state would silently be the marketing palette; and if the
|
|
@@ -444,13 +456,13 @@ describe('the state and chart hues', () => {
|
|
|
444
456
|
// 3.46:1, and a deuteranopic reader finds it dE 5.9 from done. It also
|
|
445
457
|
// sits under the floors the reserved red keeps from the orange (11.4
|
|
446
458
|
// under normal vision, 6.8 under deuteranopia) and from the green
|
|
447
|
-
// (deuteranopia
|
|
459
|
+
// (deuteranopia 4.9).
|
|
448
460
|
const failing = checksAfter('dark', '--color-feedback-danger', '#f0506e').map(summary);
|
|
449
461
|
assert.deepEqual(failing, [
|
|
450
462
|
`${LABEL_RULE}: --color-text-on-accent on --color-feedback-danger: 3.46:1 (worst on --color-feedback-danger on --color-surface-frame)`,
|
|
451
463
|
`${STATUS_RULE}: --color-feedback-success vs --color-feedback-danger: dE n34.5/p18.6/d5.9 >= 10`,
|
|
452
464
|
`${DANGER_RULE}: --color-data-2: dE n11.4/p9.9/d6.8 >= 14 normal, 8 dichromat`,
|
|
453
|
-
`${DANGER_RULE}: --color-data-3: dE n32.
|
|
465
|
+
`${DANGER_RULE}: --color-data-3: dE n32.5/p12.7/d4.9 >= 14 normal, 8 dichromat`,
|
|
454
466
|
]);
|
|
455
467
|
});
|
|
456
468
|
|
|
@@ -465,12 +477,12 @@ describe('the state and chart hues', () => {
|
|
|
465
477
|
test('a neighbour that clears every dichromat floor is still caught under normal vision', () => {
|
|
466
478
|
// A teal fourth series beside the aqua green third: dE 13.0 apart under
|
|
467
479
|
// protanopia and 12.3 under deuteranopia, which the dichromat floor alone
|
|
468
|
-
// passes, and
|
|
480
|
+
// passes, and 13.0 under normal vision, two shades of one hue to every
|
|
469
481
|
// reader who sees colour. Nothing else it touches fails, so the
|
|
470
482
|
// normal-vision floor is the only thing standing between it and a chart.
|
|
471
483
|
const failing = checksAfter('dark', '--color-data-4', '#008c87');
|
|
472
484
|
assert.deepEqual(failing.map(summary), [
|
|
473
|
-
`${ADJACENT_RULE}: --color-data-3 vs --color-data-4: dE
|
|
485
|
+
`${ADJACENT_RULE}: --color-data-3 vs --color-data-4: dE n13.0/p13.0/d12.3 >= ${DATA_ADJACENT_NORMAL_DE} normal, ${DATA_ADJACENT_DE} every vision`,
|
|
474
486
|
]);
|
|
475
487
|
assert.ok(failing[0].value >= DATA_ADJACENT_DE, 'the mutation has to clear the dichromat floor, or it proves nothing about the normal one');
|
|
476
488
|
});
|