Skip to content

Commit

Permalink
<color-gamut> prototype, used by <css-color>
Browse files Browse the repository at this point in the history
  • Loading branch information
LeaVerou committed Mar 23, 2024
1 parent 6a6e19c commit 2d64fdd
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 72 deletions.
4 changes: 2 additions & 2 deletions _build/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export function unslugify (slug) {
return slug.replace(/(^|-)([a-z])/g, ($0, $1, $2) => ($1 ? " " : "") + $2.toUpperCase());
}

export function first_heading (content) {
return content ? content.match(/^#+\s*(.+)/)?.[1] ?? "NO_HEADING_FOUND" : "EMPTY_CONTENT";
export function number (value, options) {
return value.toLocaleString("en", options);
}

Check warning on line 16 in _build/filters.js

View workflow job for this annotation

GitHub Actions / Lint & Test Types

Newline required at end of file but not found
3 changes: 2 additions & 1 deletion apps/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ body_classes: language-markup
- [Gradient interpolation](gradients)
- [Named color proximity](named)

## Elements
## [Elements](../elements/)

- [`<color-swatch>`](../elements/color-swatch/)
- [`<css-color>`](../elements/css-color/)

## External

Expand Down
14 changes: 14 additions & 0 deletions assets/css/style.postcss
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ fieldset {
}
}

input {
font: inherit;
}

input[type=number] {
width: 4em;
font: inherit;

@supports (field-sizing: content) {
field-sizing: content;
width: auto;
}
}

table {
width: 100%;
border: 5px solid transparent;
Expand Down
3 changes: 2 additions & 1 deletion elements/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ Then just start using it!
## Components

- [`<css-color>`](./css-color/)
- [`<color-swatch>`](./color-swatch/)
- [`<color-swatch>`](./color-swatch/)
- [`<color-gamut>`](./color-gamut/)
61 changes: 61 additions & 0 deletions elements/color-gamut/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
body_classes: cn-ignore
---
<script src="color-gamut.js" type="module"></script>
# &lt;color-gamut>

Gamut indicator. Used internally by `<css-color>`

## Usage

Static (only read once):
```html
<color-gamut>red</color-gamut>
```

Produces <color-gamut>red</color-gamut>

Dynamic:
```js
colorGamutElement.color = colorValue;
```

## Demo

<form id=params>
<code>oklch(<input type=number id=l value=50>% <input type=number id=min_c value=30>&ndash;<input type=number id=max_c value=40>% <input type=number id=h value=50>)</code>
<p><label>Chroma increments: <input type=number id=c_step value="0.2" min="0">%</label>
</form>

<script type=module>
params.addEventListener("input", e => {
let c_range = {min: Number(min_c.value), max: Number(max_c.value)};
let step = Number(c_step.value);
let colors = [];
for (let c = c_range.min; c<= c_range.max; c+=step) {
colors.push(`oklch(${l.value}% ${c.toLocaleString("en")}% ${h.value})`);
}

colors_tbody.innerHTML = colors.map(color => `
<tr>
<td>
<code>${color}</code>
</td>
<td>
<color-gamut>${color}</color-gamut>
</td>
</tr>`).join("\n");
});
params.dispatchEvent(new Event("input"));
</script>

<table>
<thead>
<tr>
<th>Color</th>
<th>Gamut</th>
</tr>
</thead>
<tbody id=colors_tbody>
</tbody>
</table>
135 changes: 135 additions & 0 deletions elements/color-gamut/color-gamut.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import Color from "../../dist/color.js";

const gamuts = ["srgb", "p3", "rec2020"];

let styleURL = new URL("./style.css", import.meta.url);

export default class ColorGamut extends HTMLElement {
#label;

constructor () {
super();
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = `
<style>@import url("${ styleURL }")</style>
<span id="label" part="label"></span>
`;

this.attributeChangedCallback();

let textContent = this.textContent;

if (textContent) {
this.color ??= this.textContent;
}
}

connectedCallback () {
this.#render();
}

#render () {
if (!this.isConnected) {
return;
}

if (!this.#label) {
this.#label = this.shadowRoot.querySelector("#label");
}

if (this.#color) {
let gamut = null;

for (let g in this.gamuts) {
if (this.#color.inGamut(g)) {
gamut = g;
break;
}
}

this.#setGamut(gamut);
}
else {
this.#setGamut();
}
}

#gamut;
get gamut () {
return this.#gamut;
}

#setGamut (gamut) {
this.#gamut = gamut;

if (gamut === undefined) {
this.removeAttribute("gamut");
this.style.removeProperty("--gamut-level");
this.#label.textContent = "";
return;
}

let label = "";
let level = -1;
let levels = Object.entries(this.gamuts);
if (gamut === null) {
// Outside all gamuts
this.setAttribute("gamut", "none");
level = levels.length;
label = levels.at(-1)[1] + "+";
}
else {
this.setAttribute("gamut", gamut);
label = this.gamuts[gamut];
level = levels.findIndex(([id]) => id === gamut);
}

this.#label.textContent = label;
this.style.setProperty("--gamut-level", level);
}

#color;
get color () {
return this.#color;
}

set color (color) {
if (!(color instanceof Color)) {
color = new Color(color);
}

this.#color = color;
this.#render();
}

static observedAttributes = ["gamuts"];
static defaultGamuts = ["srgb", "p3", "rec2020"];

attributeChangedCallback (name, oldValue, newValue) {
if (!name || name === "gamuts") {
if (newValue === undefined) {
newValue = this.getAttribute("gamuts");
}

if (oldValue !== newValue) {
this.gamuts = this.constructor.parseGamuts(newValue ?? this.constructor.defaultGamuts);
this.#render();
}
}
}

static parseGamuts (gamuts) {
if (typeof gamuts === "string") {
gamuts = gamuts.trim().split(/\s*,\s*/);
}

return Object.fromEntries(gamuts.map(gamut => {
gamut = gamut.trim();
let [id, label = Color.spaces[gamut]?.name ?? gamut] = gamut.split(/\s*:\s*/);
return [id, label];
}));

}
}

customElements.define("color-gamut", ColorGamut);
31 changes: 31 additions & 0 deletions elements/color-gamut/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
:host {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: .2em;
color: white;
background: var(--gamut-color, var(--color-neutral-60, hsl(220 10% 60%)));
font-weight: bold;
padding-inline: .4em;
line-height: 1.4;
}

:host([gamut="p3"]) {
color: black;
}

:host([gamut="srgb"]) {
--gamut-color: var(--color-green, yellowgreen);
}

:host([gamut="p3"]) {
--gamut-color: var(--color-yellow, gold);
}

:host([gamut="rec2020"]) {
--gamut-color: var(--color-orange, orange);
}

:host([gamut="none"]) {
--gamut-color: var(--color-red, red);
}
24 changes: 5 additions & 19 deletions elements/css-color/css-color.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Color from "../../dist/color.js";
import ColorGamut from "../color-gamut/color-gamut.js";
// const styles = await fetch("./style.css").then(r => r.text());

const gamuts = ["srgb", "p3", "rec2020"];
Expand All @@ -19,7 +20,7 @@ export default class CSSColor extends HTMLElement {
</slot>
<div id="wrapper">
<slot></slot>
<span id="gamut" part="gamut"></span>
<color-gamut id="gamut" part="gamut" gamuts="srgb, p3, rec2020: P3+"></color-gamut>
</div>
`;
}
Expand Down Expand Up @@ -95,26 +96,10 @@ export default class CSSColor extends HTMLElement {
},
}));
}

if (this.#color) {
this.#renderGamut();
}
}

#renderGamut () {
if (this.#color) {
let gamut = gamuts.find(gamut => this.#color.inGamut(gamut)) ?? "";
this.dataset.gamut = this.#gamut = gamut;
}
else {
this.#gamut = null;
this.removeAttribute("data-gamut");
}
}

#gamut;
get gamut () {
return this.#gamut;
return this.#dom.gamutIndicator.gamut;
}

get value () {
Expand Down Expand Up @@ -155,7 +140,6 @@ export default class CSSColor extends HTMLElement {

this.#setColor(color);
this.#setValue(color.toString({ precision: 2, inGamut: false}));
this.#renderGamut();
}

#setColor (color) {
Expand All @@ -167,6 +151,8 @@ export default class CSSColor extends HTMLElement {
catch (e) {
this.style.setProperty("--color", this.value);
}

this.#dom.gamutIndicator.color = this.#color;
}

static observedAttributes = ["for"];
Expand Down
Loading

0 comments on commit 2d64fdd

Please sign in to comment.