Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e5ecb97
swatch picker WIP
mttshw Dec 12, 2025
cc1217f
Update index.html
mttshw Dec 12, 2025
c9214aa
added option to exclude or include the result label
mttshw Dec 12, 2025
4df6695
updated html
mttshw Dec 12, 2025
636bc36
Update swatch-picker/open-swatch-picker.js
mttshw Dec 13, 2025
caf169d
Update swatch-picker/open-swatch-picker.js
mttshw Dec 13, 2025
cb408a6
Update swatch-picker/open-swatch-picker.js
mttshw Dec 13, 2025
4964bac
Update swatch-picker/open-swatch-picker.js
mttshw Dec 13, 2025
8fa3525
Update swatch-picker/open-swatch-picker.js
mttshw Dec 13, 2025
ccf3e9a
fixing some pr comments
mttshw Dec 13, 2025
8d4a63a
buggered it
mttshw Dec 13, 2025
419ab7c
why doesnt this work
mttshw Dec 13, 2025
a446760
removing button
mttshw Dec 13, 2025
86eae93
cant add a label inside a button
mttshw Dec 13, 2025
60dde34
reduced options a bit
mttshw Dec 13, 2025
28d75bf
removed console logs
mttshw Dec 13, 2025
88f02f2
Update swatch-picker/open-swatch-picker.js
mttshw Dec 14, 2025
ac20317
Update swatch-picker/open-swatch-picker.js
mttshw Dec 14, 2025
853e790
Update swatch-picker/open-swatch-picker.js
mttshw Dec 14, 2025
61a578d
Update swatch-picker/open-swatch-picker.js
mttshw Dec 14, 2025
697d170
dedenting
mttshw Dec 14, 2025
8069b90
cut a lot of the crap out
mttshw Dec 14, 2025
44340bc
stop converting to rgb and hex every time
mttshw Dec 14, 2025
fe81471
added form controls
mttshw Dec 14, 2025
beda35b
remove looping through elements
mttshw Dec 14, 2025
9ddf48f
remove ampersands
mttshw Dec 14, 2025
448592d
Update swatch-picker/open-swatch-picker.js
mttshw Dec 15, 2025
a2640a9
improving the way values are set
mttshw Dec 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eleventy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default (eleventyConfig) => {
eleventyConfig.addPassthroughCopy("css");
eleventyConfig.addPassthroughCopy("swatch-picker");
eleventyConfig.addPassthroughCopy("favicon.ico");
eleventyConfig.addPassthroughCopy("favicon.png");
return {
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

109 changes: 109 additions & 0 deletions swatch-picker/color-converters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const oklchToOklab = (oklch) => {
const [ lightness, chroma, hue, alpha = 1 ] = oklch;
const hueRad = (hue * Math.PI) / 180; // Convert degrees to radians
const a = chroma * Math.cos(hueRad);
const b = chroma * Math.sin(hueRad);
return { lightness, a, b, alpha };
}

const oklabToXyzD65 = (oklab) => {
const { lightness, a, b, alpha } = oklab;

// Calculate LMS values
let l = lightness * 1.0 + a * 0.3963377773761749 + b * 0.2158037573099136;
let m = lightness * 1.0 + a * -0.1055613458156586 + b * -0.0638541728258133;
let s = lightness * 1.0 + a * -0.0894841775298119 + b * -1.2914855480194092;

// Apply the power of 3 to LMS values
l = Math.pow(l, 3);
m = Math.pow(m, 3);
s = Math.pow(s, 3);

// Convert LMS to XYZ
const x = l * 1.2268798758459243 + m * -0.5578149944602171 + s * 0.2813910456659647;
const y = l * -0.0405757452148008 + m * 1.112286803280317 + s * -0.0717110580655164;
const z = l * -0.0763729366746601 + m * -0.4214933324022432 + s * 1.5869240198367816;

// Return the XYZD65 object
return {
x: x * 100.0,
y: y * 100.0,
z: z * 100.0,
alpha: alpha
};
}

const xyzD65ToLinearRgb = (xyzD65) => {
const { x, y, z, alpha } = xyzD65;

// Normalize x, y, z by dividing by 100
const xNorm = x / 100.0;
const yNorm = y / 100.0;
const zNorm = z / 100.0;

// Calculate red, green, and blue components
const red = xNorm * (12831.0 / 3959.0) + yNorm * (-329.0 / 214.0) + zNorm * (-1974.0 / 3959.0);
const green = xNorm * (-851781.0 / 878810.0) + yNorm * (1648619.0 / 878810.0) + zNorm * (36519.0 / 878810.0);
const blue = xNorm * (705.0 / 12673.0) + yNorm * (-2585.0 / 12673.0) + zNorm * (705.0 / 667.0);

// Return the LinearRgb object
return {
red,
green,
blue,
alpha
};
}

const linearRgbToSrgb = (linearRgb) => {
const { red, green, blue, alpha } = linearRgb;

// Helper function to clamp values between 0 and 1
const clamp01 = (value) => Math.max(0, Math.min(1, value));

// Helper function for gamma correction
const gamma = (value) => {
return value <= 0.0031308
? 12.92 * value
: 1.055 * Math.pow(value, 1 / 2.4) - 0.055;
};

// Convert LinearRgb to Srgb
return {
red: Math.round(gamma(clamp01(red)) * 255),
green: Math.round(gamma(clamp01(green)) * 255),
blue: Math.round(gamma(clamp01(blue)) * 255),
alpha
};
}

export const oklchToHex = (oklch) => {

const oklchOb = oklch.match(/oklch\(([^)]+)\)/)[1].replaceAll(' ', ',').split(',').map(Number);

const oklab = oklchToOklab(oklchOb);

const xyzD65 = oklabToXyzD65(oklab);

const linearRgb = xyzD65ToLinearRgb(xyzD65);

const srgb = linearRgbToSrgb(linearRgb);

const r = Math.round(srgb.red);
const g = Math.round(srgb.green);
const b = Math.round(srgb.blue);
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}

export const oklchToRgb = (oklch) => {
const oklchOb = oklch.match(/oklch\(([^)]+)\)/)[1].replaceAll(' ', ',').split(',').map(Number);
const oklab = oklchToOklab(oklchOb);
const xyzD65 = oklabToXyzD65(oklab);
const linearRgb = xyzD65ToLinearRgb(xyzD65);
const srgb = linearRgbToSrgb(linearRgb);

const r = Math.round(srgb.red);
const g = Math.round(srgb.green);
const b = Math.round(srgb.blue);
return `rgb(${r}, ${g}, ${b})`;
}
109 changes: 109 additions & 0 deletions swatch-picker/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="../css/open-swatch.css">
<link rel="stylesheet" href="../css/page.css">
<title>Swatch Picker | open swatch - the open color system</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<header hero>
<h1>Open Swatch</h1>
<div>
<p>Swatch picker</p>
<a href="/">&lt; Back to openswatch</a>
</div>
<section>

</section>
</header>
<main>
<section>
<h2>Default use</h2>
<p>By default the picker will return the variable </p>
<h3>Example</h3>
<open-swatch-picker></open-swatch-picker>
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker&gt;&lt;/open-swatch-picker&gt;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit but you could get away with just &lt; here and others.

Suggested change
&lt;open-swatch-picker&gt;&lt;/open-swatch-picker&gt;
&lt;open-swatch-picker>&lt;/open-swatch-picker>

</code>
</pre>
</section>
<hr>
<section>
<h2>Return Hex Code</h2>
<h3>Example</h3>
<open-swatch-picker output-type="hex"></open-swatch-picker>
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker output-type="hex"&gt;&lt;/open-swatch-picker&gt;
</code>
</pre>
</section>
<hr>
<section>
<h2>Return RGB</h2>
<h3>Example</h3>
<open-swatch-picker output-type="rgb"></open-swatch-picker>
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker output-type="rgb"&gt;&lt;/open-swatch-picker&gt;
</code>
</pre>
</section>
<hr>
<section>
<h2>Hide output</h2>
<p>Default: false.</p>
<h3>Example</h3>
<open-swatch-picker hide-output-label="true">
</open-swatch-picker>
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker hide-output-label="true"&gt;
&lt;/open-swatch-picker&gt;
</code>
</pre>
</section>

<section>
<h2>Custom label</h2>
<p>Default: false. To hide, just dont set `show output label`;</p>
<h3>Example</h3>
<open-swatch-picker label="Pick a color">
</open-swatch-picker>
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker label="Pick a color"&gt;
&lt;/open-swatch-picker&gt;
</code>
</pre>
</section>

<section>
<h2>Populate form controls</h2>
<h3>Example</h3>
<open-swatch-picker id="color-input">
</open-swatch-picker>
<output for="color-input"></output>
<input type="text" open-swatch-picker="color-input" />
<h3>Usage</h3>
<pre>
<code>
&lt;open-swatch-picker id="color-input"&gt;&lt;/open-swatch-picker&gt;
&lt;output for="color-input"&gt;&lt;/output&gt;
&lt;input type="text" open-swatch-picker="color-input" /&gt;
</code>
</pre>
</section>

</main>
</body>
<script src="open-swatch-picker.js" defer type="module"></script>

</html>
Loading