From 9920b91fe08a96de2a1daeaf9c2e896e1cf680f1 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Mon, 28 Jul 2025 15:08:30 +0200 Subject: [PATCH 1/2] [color-swatch] Fix popovers with color details in ``s in Safari Safari appears to have issues with combining styles within container queries with popover styles, so we need to move them out. --- src/color-swatch/color-swatch.css | 108 +++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 23 deletions(-) diff --git a/src/color-swatch/color-swatch.css b/src/color-swatch/color-swatch.css index 093ddf9..961693c 100644 --- a/src/color-swatch/color-swatch.css +++ b/src/color-swatch/color-swatch.css @@ -94,6 +94,18 @@ slot { } [part="details"] { + /* + Why here and not in the style query below? Because Safari has issues with parsing nested rules inside style queries, + we need to duplicate some rules to achieve the desired effect. Moving custom properties here allows us to make the code a bit DRYer. + */ + --_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); + display: flex; flex-flow: inherit; gap: inherit; @@ -116,14 +128,6 @@ slot { } @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; @@ -135,26 +139,12 @@ slot { border: 1px solid var(--_border-color); padding: 0.6em 1em; border-radius: 0.2rem; - box-shadow: 0 0.05em 1em -0.7em black; + box-shadow: 0 0.05em 1em -0.7em canvastext; 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: ""; @@ -183,6 +173,78 @@ slot { scale: 0; } } + + &[popover] { + /* Make the triangle pointer visible */ + overflow: visible; + + /* Bring the popover back on the screen */ + position: fixed; + inset: unset; + + &:popover-open { + /* And position it relative to the parent swatch */ + left: var(--_popover-left); + top: var(--_popover-top); + translate: -50% -100%; + + /* We need to duplicate these rules from the style query rule because Safari refuses to pick them up. */ + 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 canvastext; + transition: var(--_transition-duration) allow-discrete; + transition-property: all, display; + transition-delay: 0s, var(--_transition-duration); + transform-origin: 50% calc(100% + var(--_pointer-height)); + } + + &:not(:popover-open) { + /* Hide the popover when not open. This is also a workaround for Safari */ + display: none; + opacity: 0; + scale: 0; + } + } + + &[popover] { + /* Make the triangle pointer visible */ + overflow: visible; + + /* Bring the popover back on the screen */ + position: fixed; + inset: unset; + + &:popover-open { + /* And position it relative to the parent swatch */ + left: var(--_popover-left); + top: var(--_popover-top); + translate: -50% -100%; + + /* We need to duplicate these rules from the style query rule because Safari refuses to pick them up. */ + 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 canvastext; + transition: var(--_transition-duration) allow-discrete; + transition-property: all, display; + transition-delay: 0s, var(--_transition-duration); + transform-origin: 50% calc(100% + var(--_pointer-height)); + } + + &:not(:popover-open) { + /* Hide the popover when not open. This is also a workaround for Safari */ + display: none; + opacity: 0; + scale: 0; + } + } } [part="color"] { From ea4d6f2a9785ac2562d6d223a7f02f803ccaf272 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Thu, 31 Jul 2025 12:37:40 +0200 Subject: [PATCH 2/2] Improve browser support Now it works not only in Chrome, but also in Safari and Firefox. Support for `popover` is much wider than support for style queries. --- src/color-swatch/color-swatch.css | 130 ++++++++++++------------------ 1 file changed, 52 insertions(+), 78 deletions(-) diff --git a/src/color-swatch/color-swatch.css b/src/color-swatch/color-swatch.css index 961693c..69cdecd 100644 --- a/src/color-swatch/color-swatch.css +++ b/src/color-swatch/color-swatch.css @@ -94,10 +94,6 @@ slot { } [part="details"] { - /* - Why here and not in the style query below? Because Safari has issues with parsing nested rules inside style queries, - we need to duplicate some rules to achieve the desired effect. Moving custom properties here allows us to make the code a bit DRYer. - */ --_border-color: var( --border-color, color-mix(in oklab, buttonborder 20%, oklab(none none none / 0%)) @@ -127,51 +123,19 @@ slot { font-size: 80%; } - @container style(--details-style: compact) { + /* Triangle pointer */ + &::before { + content: ""; position: absolute; + top: 100%; 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 canvastext; - transition: var(--_transition-duration) allow-discrete; - transition-property: all, display; - transition-delay: 0s, var(--_transition-duration); - transform-origin: 50% calc(100% + var(--_pointer-height)); - - /* 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%); - } - - /* - 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; - } + 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%); } &[popover] { @@ -188,7 +152,6 @@ slot { top: var(--_popover-top); translate: -50% -100%; - /* We need to duplicate these rules from the style query rule because Safari refuses to pick them up. */ margin-bottom: calc(var(--_pointer-height) * 0.8); width: var(--_details-popup-width); background: canvas; @@ -203,47 +166,58 @@ slot { } &:not(:popover-open) { - /* Hide the popover when not open. This is also a workaround for Safari */ display: none; - opacity: 0; - scale: 0; } } - &[popover] { - /* Make the triangle pointer visible */ - overflow: visible; - - /* Bring the popover back on the screen */ - position: fixed; - inset: unset; - + @starting-style { + /* Enable transitions */ &:popover-open { - /* And position it relative to the parent swatch */ - left: var(--_popover-left); - top: var(--_popover-top); - translate: -50% -100%; - - /* We need to duplicate these rules from the style query rule because Safari refuses to pick them up. */ - 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 canvastext; - transition: var(--_transition-duration) allow-discrete; - transition-property: all, display; - transition-delay: 0s, var(--_transition-duration); - transform-origin: 50% calc(100% + var(--_pointer-height)); + opacity: 0; + scale: 0; } + } +} - &:not(:popover-open) { - /* Hide the popover when not open. This is also a workaround for Safari */ +@container style(--details-style: compact) { + [part="details"]:not([popover]) { + 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 canvastext; + transition: var(--_transition-duration) allow-discrete; + transition-property: all, display; + transition-delay: 0s, var(--_transition-duration); + transform-origin: 50% calc(100% + var(--_pointer-height)); + + /* + 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; } + + @starting-style { + /* Enable transitions */ + & { + opacity: 0; + scale: 0; + } + } } }