UNPKG

color-elements

Version:

A set of web components for working with color. A Color.js project.

293 lines (256 loc) 6.78 kB
:host { --_transparency-cell-size: var(--transparency-cell-size, 0.5em); --_transparency-background: var(--transparency-background, transparent); --_transparency-darkness: var(--transparency-darkness, 5%); --_transparency-grid: var( --transparency-grid, repeating-conic-gradient( transparent 0 25%, rgb(0 0 0 / var(--_transparency-darkness)) 0 50% ) 0 0 / calc(2 * var(--_transparency-cell-size)) calc(2 * var(--_transparency-cell-size)) content-box border-box var(--_transparency-background) ); --_dot-size: var(--dot-size, 1em); position: relative; display: inline-flex; gap: 0.3em; width: var(--color-swatch-width, fit-content); margin: 0.3em; border-radius: var(--color-swatch-radius, 0.2rem); } :host([size="large"]) { flex-flow: column; inline-size: min(11em, 100%); min-block-size: 6em; contain: inline-size; container-name: color-swatch; container-type: inline-size; --_dot-size: var(--dot-size, 1.5em); } slot { all: inherit; display: contents; } #gamut { font-size: 80%; &:is(:host([size="large"]) *) { position: absolute; top: 0; right: 0; margin: 0.5rem; } &:not(:host([size="large"]) *) { @container style(--details-style: compact) { position: absolute; font-size: 50%; top: 0; right: 0; margin: 0.2rem; } &:is(.static *) { align-self: baseline; } } &[style*="--gamut-level: 0"] { display: none; } /* Dot mode: the swatch is a bare marker, so its gamut badge is dropped (details surface in the tooltip instead). */ @container style(--swatch-style: dot) { display: none; } } [part="info"] { margin: 0; /* Hidden in the inline details view; revealed (below) as a coord grid wherever there's room to show it. */ display: none; grid-template-columns: max-content auto; gap: 0.1em 0.2em; font-size: max(9px, 80%); justify-content: start; .coord { display: contents; dd { margin: 0; font-weight: bold; font-variant-numeric: tabular-nums; } } /* Show the coords when the swatch has room for them: a large swatch, or a dot — where the dot itself carries no detail, so its coords surface in the (usually compact) tooltip. */ &:is(:host([size="large"]) &) { display: grid; } @container style(--swatch-style: dot) { display: grid; } } [part="details"] { display: flex; flex-flow: inherit; gap: inherit; /* Prevent flex items from overflowing */ min-inline-size: 0; &.static { &:is(:host([size="large"]) *) { background: canvas; } } &:not(:host([size="large"]) *) { align-items: baseline; } @container color-swatch (width <= 5rem) { font-size: 80%; } @container style(--details-style: compact) { --_border-color: var( --border-color, color-mix(in oklab, buttonborder 20%, oklab(none none none / 0%)) ); --_pointer-height: var(--pointer-height, 0.5em); --_transition-duration: var(--transition-duration, 400ms); --_details-popup-width: var(--details-popup-width, max-content); position: absolute; left: 50%; z-index: 2; translate: -50% 0; bottom: 100%; margin-bottom: calc(var(--_pointer-height) * 0.8); width: var(--_details-popup-width); background: canvas; border: 1px solid var(--_border-color); padding: 0.6em 1em; border-radius: 0.2rem; box-shadow: 0 0.05em 1em -0.7em black; transition: var(--_transition-duration); transition-behavior: allow-discrete; transition-property: opacity, scale, display, overlay; transform-origin: 50% calc(100% + var(--_pointer-height)); &[popover] { overflow: visible; /* show the triangle pointer */ position: fixed; inset: auto; margin: 0 0 calc(var(--_pointer-height) * 0.8); translate: none; position-anchor: --swatch; position-area: top; position-try-fallbacks: flip-block; /* Query the active fallback so the pointer can flip with it (below). */ container-type: anchored; } /* Triangle pointer. Sits on the bottom edge pointing down at the swatch. */ &::before { content: ""; position: absolute; top: 100%; left: 50%; translate: -50% -50%; aspect-ratio: 1; height: calc(var(--_pointer-height) * sqrt(2)); background: inherit; border: inherit; rotate: -45deg; clip-path: polygon(0 0, 0 100%, 100% 100%); } /* When the tooltip flips below the swatch, move the pointer to the top edge and point it up. Anchored container queries are Chrome 143+; elsewhere the pointer harmlessly stays at the bottom. */ @container anchored(fallback: flip-block) { &::before { top: 0; rotate: 45deg; clip-path: polygon(0 100%, 0 0, 100% 0); } } /* More straightforward selector: &:not(:is(:host(:hover), :host(:focus-within), :host(:active), :host(:target), :host([open])) *) doesn't work in Safari! See https://bugs.webkit.org/show_bug.cgi?id=296577 */ &:is(:host(:not(:hover):not(:focus-within):not(:active):not(:target):not([open])) *), &:is(:host([open="false"]) *) { display: none; opacity: 0; scale: 0; } } } [part="color"] { display: flex; gap: 0.2em; } [part="label"] { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } slot:not([name]) { &::slotted(input) { display: flex; box-sizing: border-box; min-width: 10ch; font: inherit; } &:is(:host([size="large"]) *)::slotted(input) { width: 100%; } } [part="color-wrapper"], slot[name="swatch"]::slotted(*), #swatch { border-radius: inherit; } slot[name="swatch"]::slotted(*), #swatch { flex: 1; display: flex; flex-flow: column; align-items: center; justify-content: center; padding: 0.5em; display: flex; flex-flow: column; flex: 1; background: linear-gradient(var(--color) 0 100%), var(--_transparency-grid); /* In compact mode the swatch is the anchor for its details popover. */ @container style(--details-style: compact) { anchor-name: --swatch; } &:where(:host([size="large"]) *) { min-block-size: 3em; } &:where(:not(:host([size="large"]) *)) { display: flex; min-inline-size: 2em; min-block-size: 1em; font-size: 65%; flex: 1; } @container style(--swatch-style: dot) { font-size: 1rem; margin: 0; /* A fixed circle, not a flex-stretched box (otherwise it elongates). */ flex: none; inline-size: var(--_dot-size); min-inline-size: 0; min-block-size: 0; aspect-ratio: 1; overflow: hidden; border-radius: 50%; border: var(--dot-border, clamp(2px, 0.3em, var(--_dot-size) / 10) solid white); box-shadow: var( --dot-shadow, 0 0.04em 0.1em rgb(0 0 0 / 16%), 0 0.12em 0.3em -0.04em rgb(0 0 0 / 22%) ); } } slot[name="swatch-content"] { /* See https://lea.verou.me/blog/2024/contrast-color/ */ --l: clamp(0, (var(--l-threshold, 0.7) / l - 1) * infinity, 1); color: oklch(from var(--color) var(--l) 0 h); }