From 17eeccbc5d117725ebb3fb010aaebc64313e0e70 Mon Sep 17 00:00:00 2001 From: Lea Verou Date: Wed, 5 Feb 2025 10:23:24 -0500 Subject: [PATCH] Better infrastructure for core colors, show core colors in docs, closes #668 --- docs/_data/palettes.js | 2 +- docs/_layouts/palette.njk | 7 +++ docs/assets/styles/docs.css | 5 ++ src/styles/color/palettes-analyzed.js | 67 +++++++++++++++++++++++++++ src/styles/color/tintless.js | 34 ++++---------- 5 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 src/styles/color/palettes-analyzed.js diff --git a/docs/_data/palettes.js b/docs/_data/palettes.js index fb231f0e9..c16e54f75 100644 --- a/docs/_data/palettes.js +++ b/docs/_data/palettes.js @@ -1 +1 @@ -export { default as default } from '../../src/styles/color/palettes.js'; +export { default as default } from '../../src/styles/color/palettes-analyzed.js'; diff --git a/docs/_layouts/palette.njk b/docs/_layouts/palette.njk index 6903717e4..f122dec0a 100644 --- a/docs/_layouts/palette.njk +++ b/docs/_layouts/palette.njk @@ -15,6 +15,7 @@ + Core tint {% for tint in tints -%} {{ tint }} {%- endfor %} @@ -23,6 +24,12 @@ {% for hue in hues -%} {{ hue | capitalize }} + +
+ {{ palettes[paletteId][hue].maxChromaTint }} + +
+ {% for tint in tints -%}
diff --git a/docs/assets/styles/docs.css b/docs/assets/styles/docs.css index b98b5bc8f..37ddd9fa3 100644 --- a/docs/assets/styles/docs.css +++ b/docs/assets/styles/docs.css @@ -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 */ diff --git a/src/styles/color/palettes-analyzed.js b/src/styles/color/palettes-analyzed.js new file mode 100644 index 000000000..d485d7736 --- /dev/null +++ b/src/styles/color/palettes-analyzed.js @@ -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); diff --git a/src/styles/color/tintless.js b/src/styles/color/tintless.js index 3ca44cc10..d7e901ba0 100644 --- a/src/styles/color/tintless.js +++ b/src/styles/color/tintless.js @@ -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