swatchbuckler.ts (3377B)
1 import * as d3 from "d3-color"; 2 3 const INC = 0.4; 4 const RANGE = 4.1; 5 6 // copied from https://gist.github.com/jfsiii/5641126 7 //// from http://www.w3.org/TR/WCAG20/#relativeluminancedef 8 function luminance({ r, g, b }) { 9 var RsRGB = r / 255; 10 var GsRGB = g / 255; 11 var BsRGB = b / 255; 12 13 var R = 14 RsRGB <= 0.03928 ? RsRGB / 12.92 : Math.pow((RsRGB + 0.055) / 1.055, 2.4); 15 var G = 16 GsRGB <= 0.03928 ? GsRGB / 12.92 : Math.pow((GsRGB + 0.055) / 1.055, 2.4); 17 var B = 18 BsRGB <= 0.03928 ? BsRGB / 12.92 : Math.pow((BsRGB + 0.055) / 1.055, 2.4); 19 20 // For the sRGB colorspace, the relative luminance of a color is defined as: 21 var L = 0.2126 * R + 0.7152 * G + 0.0722 * B; 22 return L; 23 } 24 25 function contrast(lumA: number, lumB: number) { 26 if (lumA < lumB) { 27 let tmp = lumA; 28 lumA = lumB; 29 lumB = tmp; 30 } 31 return (lumA + 0.05) / (lumB + 0.05); 32 } 33 34 function makeCssVariables(colors: string[]) { 35 return colors.map((c, idx) => `--mono-tint-${idx}: ${c};`).join("\n"); 36 } 37 38 function makeColors() { 39 const parentEl = document.getElementById("renderzone") as HTMLDivElement; 40 const colorEl = document.getElementById("midcolor") as HTMLInputElement; 41 const midColor = d3.lch(colorEl.value); 42 const minContrast = Number( 43 (document.getElementById("mincontrast") as HTMLInputElement).value, 44 ); 45 const heading = (document.getElementById("msg") as HTMLInputElement).value; 46 47 if (Number.isNaN(midColor.h)) { 48 colorEl.style.background = "salmon"; 49 function handlePress() { 50 colorEl.style.background = "white"; 51 } 52 colorEl.addEventListener("keydown", handlePress, { once: true }); 53 return; 54 } 55 56 parentEl.innerHTML = ""; 57 58 const tints = []; 59 for (let i = -1 * RANGE; i <= RANGE; i += INC) { 60 const bg = d3.lch(midColor).brighter(i).formatHex(); 61 if (bg == "#000000" || bg == "#ffffff") { 62 continue; 63 } 64 const bgLum = luminance(d3.rgb(bg)); 65 const sign = bgLum > 0.5 ? 1 : -1; 66 67 tints.push(bg); 68 69 for (let j = sign * -1 * RANGE; sign * j <= RANGE; j += sign * INC) { 70 const fg = d3.lch(midColor).brighter(j).formatHex(); 71 const swatchContrast = contrast(luminance(d3.rgb(fg)), bgLum); 72 if (fg == "#000000" || fg == "#ffffff" || swatchContrast < minContrast) { 73 continue; 74 } 75 const el = document.createElement("div"); 76 el.classList.add("renderblock", "rounded"); 77 el.style.backgroundColor = bg; 78 el.style.color = fg; 79 el.innerHTML = `<h1>${heading}</h1> 80 <h2>bg: ${bg}</h2> 81 <h3>fg: ${fg}</h3> 82 <p>contrast ratio: ${swatchContrast.toPrecision(4)}</p>`; 83 const b = document.createElement("button"); 84 b.innerText = "copy css"; 85 b.style.color = bg; 86 b.style.backgroundColor = fg; 87 b.addEventListener("click", () => { 88 navigator.clipboard.writeText( 89 `background-color: ${bg};\ncolor: ${fg};`, 90 ); 91 }); 92 el.appendChild(b); 93 parentEl.appendChild(el); 94 } 95 } 96 97 console.log(makeCssVariables(tints)); 98 } 99 100 document.addEventListener("DOMContentLoaded", () => { 101 makeColors(); 102 document.addEventListener("keypress", (e) => { 103 if (e.keyCode === 13) { 104 makeColors(); 105 } 106 }); 107 const buttonEl = document.getElementById("thebutton") as HTMLButtonElement; 108 buttonEl.addEventListener("click", () => { 109 makeColors(); 110 }); 111 });