color-elements
Version:
A set of web components for working with color. A Color.js project.
240 lines (203 loc) • 4.84 kB
CSS
:host {
--_transparency-cell-size: var(--transparency-cell-size, .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)
);
position: relative;
display: inline-flex;
gap: .3em;
width: var(--color-swatch-width, fit-content);
margin: .3em;
border-radius: var(--color-swatch-radius, .2rem);
}
:host([size="large"]) {
flex-flow: column;
inline-size: 11em;
min-block-size: 6em;
contain: inline-size;
container-name: color-swatch;
container-type: inline-size;
}
slot {
all: inherit;
display: contents;
}
#gamut {
font-size: 80%;
&:is(:host([size="large"]) *) {
position: absolute;
top: 0;
right: 0;
margin: .5rem;
}
&:not(:host([size="large"]) *) {
@container style(--details-style: compact) {
position: absolute;
font-size: 50%;
top: 0;
right: 0;
margin: .2rem;
}
&:is(.static *) {
align-self: baseline;
}
}
&[style*="--gamut-level: 0"] {
display: none;
}
}
[part="info"] {
margin: 0;
display: inline-flex;
display: none;
gap: .5em;
&:is(:host([size="large"]) &) {
display: grid;
grid-template-columns: max-content auto;
gap: .1em .2em;
font-size: max(9px, 80%);
justify-content: start;
.coord {
display: contents;
}
}
.coord {
display: flex;
gap: .2em;
dd {
margin: 0;
font-weight: bold;
font-variant-numeric: tabular-nums;
}
}
}
[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, .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) * .8);
width: var(--_details-popup-width);
background: canvas;
border: 1px solid var(--_border-color);
padding: .6em 1em;
border-radius: .2rem;
box-shadow: 0 .05em 1em -.7em black;
transition: var(--_transition-duration) allow-discrete;
transition-property: all, display;
transition-delay: 0s, var(--_transition-duration);
transform-origin: 50% calc(100% + var(--_pointer-height));
&[popover] {
/* Make the triangle pointer visible */
overflow: visible;
/* Bring the popover back on the screen */
position: fixed;
inset: unset;
/* And position it relative to the parent swatch */
left: var(--_popover-left);
top: var(--_popover-top);
translate: -50% -100%;
}
/* Triangle pointer */
&::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%);
}
&:not(:is(:host(:hover), :host(:focus-within), :host(:active), :host(:target), :host([open])) *),
&:is(:host([open=false]) *) {
display: none;
opacity: 0;
scale: 0;
}
}
}
[part="color"] {
display: flex;
gap: .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: .5em;
display: flex;
flex-flow: column;
flex: 1;
background:
linear-gradient(var(--color) 0 100%),
var(--_transparency-grid);
&:is(:host([size="large"]) *) {
min-block-size: 3em;
}
&:not(:host([size="large"]) *) {
display: flex;
min-inline-size: 2em;
min-block-size: 1em;
font-size: 65%;
flex: 1;
}
}
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);
}