Better infrastructure for core colors, show core colors in docs, closes #668

This commit is contained in:
Lea Verou
2025-02-05 10:23:24 -05:00
parent 68f645e776
commit 17eeccbc5d
5 changed files with 88 additions and 27 deletions

View File

@@ -1 +1 @@
export { default as default } from '../../src/styles/color/palettes.js';
export { default as default } from '../../src/styles/color/palettes-analyzed.js';

View File

@@ -15,6 +15,7 @@
<thead>
<tr>
<th></th>
<th class="core-column">Core tint</th>
{% for tint in tints -%}
<th>{{ tint }}</th>
{%- endfor %}
@@ -23,6 +24,12 @@
{% for hue in hues -%}
<tr>
<th>{{ hue | capitalize }}</th>
<td class="core-column">
<div class="color swatch" style="background-color: var(--wa-color-{{ hue }}); color: var(--wa-color-{{ hue }}-{{ '05' if palettes[paletteId][hue].maxChromaTint > 60 else '95' }});">
{{ palettes[paletteId][hue].maxChromaTint }}
<wa-copy-button value="--wa-color-{{ hue }}" copy-label="--wa-color-{{ hue }}"></wa-copy-button>
</div>
</td>
{% for tint in tints -%}
<td>
<div class="color swatch" style="background-color: var(--wa-color-{{ hue }}-{{ tint }})">

View File

@@ -437,6 +437,7 @@ table.colors {
padding-block: 0;
}
}
tbody {
tr {
border: none;
@@ -456,6 +457,10 @@ table.colors {
padding-block: var(--wa-space-s);
}
}
.core-column {
padding-inline-end: var(--wa-space-xl);
}
}
/* Layout Examples */

View File

@@ -0,0 +1,67 @@
/**
* Analyze palettes and export the results.
* ✅ Convert colors to OKLCH
* ✅ Find accent tint (real and clamped)
* More later.
*/
import rawPalettes from './palettes.js';
// Default accent tint if all chromas are 0, but also the tint accent colors will be nudged towards (see chromaTolerance)
const DEFAULT_ACCENT = 60;
// Min and max allowed tints
const MIN_ACCENT = 40;
const MAX_ACCENT = 90;
// Chroma tolerance: Chroma will need to differ more than this to gravitate away from defaultAccent
const CHROMA_TOLERANCE = 0.000001;
const palettes = Object.assign({}, rawPalettes);
for (let paletteId in palettes) {
const tokens = Object.assign({}, palettes[paletteId]);
palettes[paletteId] = tokens;
for (let hue in tokens) {
let tints = Object.assign({}, tokens[hue]);
tokens[hue] = tints;
let maxChromaTint = DEFAULT_ACCENT;
let maxChroma = tints[DEFAULT_ACCENT].c || 0;
for (let tint in tints) {
let color = tints[tint].to('oklch');
tints[tint] = color;
if (tint === '05') {
// The object has both '5' and '05' keys, but '05' is out of order
continue;
}
tint = tint.padStart(2, '0');
if (color.c > maxChroma + CHROMA_TOLERANCE) {
maxChroma = color.c;
maxChromaTint = tint;
}
}
tints['05'] = tints['5'];
tints.maxChroma = tints.maxChromaRaw = maxChroma;
tints.maxChromaTint = tints.maxChromaTintRaw = maxChromaTint;
if (maxChromaTint < MIN_ACCENT || maxChromaTint > MAX_ACCENT) {
tints.maxChromaTint = clamp(MIN_ACCENT, maxChromaTint, MAX_ACCENT);
tints.maxChroma = tints[maxChromaTint].c;
}
}
}
function clamp(min, value, max) {
return Math.min(Math.max(min, value), max);
}
export default palettes;
export { rawPalettes };
console.log(palettes);

View File

@@ -7,7 +7,7 @@ import chalk from 'chalk';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import palettes from './palettes.js';
import palettes, { rawPalettes } from './palettes-analyzed.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
@@ -19,9 +19,6 @@ const selector = paletteId =>
// Default accent tint if all chromas are 0, but also the tint accent colors will be nudged towards (see chromaTolerance)
const defaultAccent = 60;
// Chroma tolerance: Chroma will need to differ more than this to gravitate away from defaultAccent
const chromaTolerance = 0.000001;
// Min and max allowed tints
const minAccentTint = 40;
const maxAccentTint = 90;
@@ -42,40 +39,29 @@ for (let paletteId in palettes) {
for (let hue in tokens) {
let tints = tokens[hue];
let maxChromaTint = defaultAccent;
let maxChroma = tints[defaultAccent].get('oklch.c');
let tintCSS = '';
for (let tint in tints) {
if (tint === '05') {
if (tint === '05' || !(tint > 0)) {
// The object has both '5' and '05' keys, but '05' is out of order
// Also ignore non-tints
continue;
}
let color = tints[tint];
let lchColor = color.to('oklch');
tint = tint.padStart(2, '0');
if (lchColor.c > maxChroma + chromaTolerance) {
maxChroma = lchColor.c;
maxChromaTint = tint;
}
let lchComment = `/* ${lchColor.toString()} */`;
tintCSS = `--wa-color-${hue}-${tint}: ${color} ${lchComment};\n` + tintCSS;
tintCSS =
`--wa-color-${hue}-${tint}: ${color.toString({ format: 'hex' })} /* ${color.toString()} */;\n` + tintCSS;
}
if (maxChromaTint < minAccentTint || maxChromaTint > maxAccentTint) {
let fakeMaxChromaTint = clamp(minAccentTint, maxChromaTint, maxAccentTint);
if (tints.maxChromaTint != tints.maxChromaTintRaw) {
let huePrefix = hueToChalk(hue)(hue.padEnd(hueMaxChars + 2));
console.warn(
`${prefix} ${huePrefix}: Clamping accent color to ${chalk.bold(fakeMaxChromaTint)}, but peak chroma is in ${chalk.bold(maxChromaTint)} (${formatComparison(tints[maxChromaTint].get('oklch.c'), tints[fakeMaxChromaTint].get('oklch.c'))})`,
`${prefix} ${huePrefix}: Clamping accent color to ${chalk.bold(tints.maxChromaTint)}, but peak chroma is in ${chalk.bold(tints.maxChromaTintRaw)} (${formatComparison(tints[tints.maxChromaTintRaw].c, tints[tints.maxChromaTint].c)})`,
);
issueCount++;
maxChromaTint = fakeMaxChromaTint;
if (prefix.trim()) {
// First time encountering an issue with this palette
@@ -86,7 +72,7 @@ for (let paletteId in palettes) {
}
}
tintCSS += `--wa-color-${hue}: var(--wa-color-${hue}-${maxChromaTint});\n`;
tintCSS += `--wa-color-${hue}: var(--wa-color-${hue}-${tints.maxChromaTint});\n`;
css += tintCSS + '\n';
}
@@ -101,10 +87,6 @@ console.info(
(issueCount > 0 ? ` ${chalk.bold(issueCount)} issues found across ${chalk.bold(issuePaletteCount)} palettes.` : ''),
);
function clamp(min, value, max) {
return Math.min(Math.max(min, value), max);
}
/**
* Format a comparison by rounding numbers to the lowest number of significant digits that still shows a difference.
* @param {number} a