From 7a69bf44891e2c5a478e2241168a276b9d61ac34 Mon Sep 17 00:00:00 2001 From: rahim Date: Thu, 12 Mar 2026 01:46:24 -0700 Subject: [PATCH] fix(skin): scope controls transitions to fine pointer only (#909) --- .../src/default/css/components/overlay.css | 22 +++++++----- packages/skins/src/default/css/video.css | 26 +++++++++----- .../default/tailwind/components/overlay.ts | 17 +++++----- .../src/default/tailwind/video.tailwind.ts | 16 +++++---- .../src/minimal/css/components/overlay.css | 22 +++++++----- packages/skins/src/minimal/css/video.css | 34 +++++++++++-------- .../minimal/tailwind/components/overlay.ts | 17 +++++----- .../src/minimal/tailwind/video.tailwind.ts | 19 ++++++----- 8 files changed, 104 insertions(+), 69 deletions(-) diff --git a/packages/skins/src/default/css/components/overlay.css b/packages/skins/src/default/css/components/overlay.css index 267de670..1642ff5d 100644 --- a/packages/skins/src/default/css/components/overlay.css +++ b/packages/skins/src/default/css/components/overlay.css @@ -9,22 +9,28 @@ background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3), oklch(0 0 0 / 0)); backdrop-filter: blur(0) saturate(1.5); opacity: 0; - transition-property: opacity, backdrop-filter; - transition-duration: 300ms; - transition-delay: 500ms; - transition-timing-function: ease-out; pointer-events: none; - @media (prefers-reduced-motion: reduce) { - transition-duration: 100ms; + @media (pointer: fine) { + transition-property: opacity, backdrop-filter; + transition-duration: 300ms; + transition-delay: 500ms; + transition-timing-function: ease-out; + + @media (prefers-reduced-motion: reduce) { + transition-duration: 100ms; + } } } .media-default-skin .media-controls[data-visible] ~ .media-overlay, .media-default-skin .media-error[data-open] ~ .media-overlay { opacity: 1; - transition-duration: 150ms; - transition-delay: 0ms; + + @media (pointer: fine) { + transition-duration: 150ms; + transition-delay: 0ms; + } } .media-default-skin .media-error[data-open] ~ .media-overlay { diff --git a/packages/skins/src/default/css/video.css b/packages/skins/src/default/css/video.css index 174750a3..10f8f442 100644 --- a/packages/skins/src/default/css/video.css +++ b/packages/skins/src/default/css/video.css @@ -57,26 +57,36 @@ bottom: 0.75rem; inset-inline: 0.75rem; z-index: 10; + color: oklch(1 0 0); + will-change: scale, transform, filter, opacity; - transition-property: scale, transform, filter, opacity; - transition-duration: 100ms; - transition-delay: 0ms; transition-timing-function: ease-out; transform-origin: bottom; - color: oklch(1 0 0); + + @media (pointer: fine) { + transition-property: scale, transform, filter, opacity; + transition-duration: 100ms; + transition-delay: 0ms; + } &:not([data-visible]) { opacity: 0; + pointer-events: none; scale: 0.9; filter: blur(8px); - transition-duration: 300ms; - transition-delay: 500ms; - pointer-events: none; + + @media (pointer: fine) { + transition-duration: 300ms; + transition-delay: 500ms; + + @media (prefers-reduced-motion: reduce) { + transition-duration: 100ms; + } + } @media (prefers-reduced-motion: reduce) { scale: 1; filter: blur(0); - transition-duration: 100ms; } } } diff --git a/packages/skins/src/default/tailwind/components/overlay.ts b/packages/skins/src/default/tailwind/components/overlay.ts index 7c5be90e..276fbdf5 100644 --- a/packages/skins/src/default/tailwind/components/overlay.ts +++ b/packages/skins/src/default/tailwind/components/overlay.ts @@ -8,18 +8,19 @@ export const overlay = cn( 'opacity-0', 'bg-linear-to-t from-black/50 via-black/30 to-transparent', 'backdrop-blur-none backdrop-saturate-150', - // Transitions - 'transition-[opacity,backdrop-filter] ease-out', - 'duration-300 delay-500', + // Transitions (fine pointer only) + '[@media(pointer:fine)]:transition-[opacity,backdrop-filter]', + '[@media(pointer:fine)]:ease-out', + '[@media(pointer:fine)]:duration-300 [@media(pointer:fine)]:delay-500', // Shown when controls visible 'peer-data-visible/controls:opacity-100', - 'peer-data-visible/controls:duration-150', - 'peer-data-visible/controls:delay-0', + '[@media(pointer:fine)]:peer-data-visible/controls:duration-150', + '[@media(pointer:fine)]:peer-data-visible/controls:delay-0', // Shown when error visible (+ blur) 'peer-data-open/error:opacity-100', - 'peer-data-open/error:duration-150', - 'peer-data-open/error:delay-0', + '[@media(pointer:fine)]:peer-data-open/error:duration-150', + '[@media(pointer:fine)]:peer-data-open/error:delay-0', 'peer-data-open/error:backdrop-blur-lg', // Reduced motion - 'motion-reduce:duration-100' + '[@media(pointer:fine)]:motion-reduce:duration-100' ); diff --git a/packages/skins/src/default/tailwind/video.tailwind.ts b/packages/skins/src/default/tailwind/video.tailwind.ts index 51df0f4a..7d3ab13c 100644 --- a/packages/skins/src/default/tailwind/video.tailwind.ts +++ b/packages/skins/src/default/tailwind/video.tailwind.ts @@ -85,16 +85,18 @@ export const controls = cn( // Position 'absolute bottom-3 inset-x-3', 'text-white z-10', - // Transitions + // Transitions (fine pointer only — instant toggle on touch to avoid dead-zone taps) 'will-change-[scale,transform,filter,opacity]', - 'transition-[scale,transform,filter,opacity] ease-out', - 'delay-0 duration-100 origin-bottom', + '[@media(pointer:fine)]:transition-[scale,transform,filter,opacity]', + 'ease-out origin-bottom', + '[@media(pointer:fine)]:delay-0 [@media(pointer:fine)]:duration-100', // Hidden state - 'not-data-visible:pointer-events-none not-data-visible:blur-sm', - 'not-data-visible:scale-90 not-data-visible:opacity-0', - 'not-data-visible:delay-500 not-data-visible:duration-300', + 'not-data-visible:pointer-events-none not-data-visible:opacity-0', + 'not-data-visible:blur-sm not-data-visible:scale-90', + '[@media(pointer:fine)]:not-data-visible:delay-500', + '[@media(pointer:fine)]:not-data-visible:duration-300', // Reduced motion + hidden - 'motion-reduce:not-data-visible:duration-100', + '[@media(pointer:fine)]:motion-reduce:not-data-visible:duration-100', 'motion-reduce:not-data-visible:blur-none', 'motion-reduce:not-data-visible:scale-100' ); diff --git a/packages/skins/src/minimal/css/components/overlay.css b/packages/skins/src/minimal/css/components/overlay.css index bcfaf985..48666271 100644 --- a/packages/skins/src/minimal/css/components/overlay.css +++ b/packages/skins/src/minimal/css/components/overlay.css @@ -9,22 +9,28 @@ background-image: linear-gradient(to top, oklch(0 0 0 / 0.7), oklch(0 0 0 / 0.5) 7.5rem, oklch(0 0 0 / 0)); backdrop-filter: blur(0) saturate(1.5); opacity: 0; - transition-property: opacity, backdrop-filter; - transition-duration: 500ms; - transition-delay: 500ms; - transition-timing-function: ease-out; pointer-events: none; - @media (prefers-reduced-motion: reduce) { - transition-duration: 100ms; + @media (pointer: fine) { + transition-property: opacity, backdrop-filter; + transition-duration: 500ms; + transition-delay: 500ms; + transition-timing-function: ease-out; + + @media (prefers-reduced-motion: reduce) { + transition-duration: 100ms; + } } } .media-minimal-skin .media-controls[data-visible] ~ .media-overlay, .media-minimal-skin .media-error[data-open] ~ .media-overlay { opacity: 1; - transition-duration: 150ms; - transition-delay: 0ms; + + @media (pointer: fine) { + transition-duration: 150ms; + transition-delay: 0ms; + } } .media-minimal-skin .media-error[data-open] ~ .media-overlay { diff --git a/packages/skins/src/minimal/css/video.css b/packages/skins/src/minimal/css/video.css index 090c0a47..9e69fade 100644 --- a/packages/skins/src/minimal/css/video.css +++ b/packages/skins/src/minimal/css/video.css @@ -54,13 +54,16 @@ z-index: 10; gap: 0.5rem; padding: 2rem 0.375rem 0.375rem 0.375rem; - will-change: transform, filter, opacity; - transition-property: transform, filter, opacity; - transition-duration: 75ms; - transition-delay: 0ms; - transition-timing-function: ease-out; color: oklch(1 0 0); + @media (pointer: fine) { + will-change: transform, filter, opacity; + transition-property: transform, filter, opacity; + transition-duration: 75ms; + transition-delay: 0ms; + transition-timing-function: ease-out; + } + @container media-root (width > 40rem) { gap: 0.875rem; padding: 2.5rem 0.75rem 0.75rem 0.75rem; @@ -68,17 +71,20 @@ &:not([data-visible]) { opacity: 0; - transform: translateY(100%); - filter: blur(8px); - transition-duration: 500ms; - transition-delay: 500ms; pointer-events: none; - @media (prefers-reduced-motion: reduce) { - scale: 1; - transform: translateY(0); - filter: blur(0); - transition-duration: 100ms; + @media (pointer: fine) { + transform: translateY(100%); + filter: blur(8px); + transition-duration: 500ms; + transition-delay: 500ms; + + @media (prefers-reduced-motion: reduce) { + scale: 1; + transform: translateY(0); + filter: blur(0); + transition-duration: 100ms; + } } } } diff --git a/packages/skins/src/minimal/tailwind/components/overlay.ts b/packages/skins/src/minimal/tailwind/components/overlay.ts index 174454e1..61313a9d 100644 --- a/packages/skins/src/minimal/tailwind/components/overlay.ts +++ b/packages/skins/src/minimal/tailwind/components/overlay.ts @@ -8,18 +8,19 @@ export const overlay = cn( 'opacity-0', 'bg-linear-to-t from-black/70 via-black/50 via-[7.5rem] to-transparent', 'backdrop-blur-none backdrop-saturate-150', - // Transitions - 'transition-[opacity,backdrop-filter] ease-out', - 'duration-500 delay-500', + // Transitions (fine pointer only) + '[@media(pointer:fine)]:transition-[opacity,backdrop-filter]', + '[@media(pointer:fine)]:ease-out', + '[@media(pointer:fine)]:duration-500 [@media(pointer:fine)]:delay-500', // Shown when controls visible 'peer-data-visible/controls:opacity-100', - 'peer-data-visible/controls:duration-150', - 'peer-data-visible/controls:delay-0', + '[@media(pointer:fine)]:peer-data-visible/controls:duration-150', + '[@media(pointer:fine)]:peer-data-visible/controls:delay-0', // Shown when error visible (+ blur) 'peer-data-open/error:opacity-100', - 'peer-data-open/error:duration-150', - 'peer-data-open/error:delay-0', + '[@media(pointer:fine)]:peer-data-open/error:duration-150', + '[@media(pointer:fine)]:peer-data-open/error:delay-0', 'peer-data-open/error:backdrop-blur-lg', // Reduced motion - 'motion-reduce:duration-100' + '[@media(pointer:fine)]:motion-reduce:duration-100' ); diff --git a/packages/skins/src/minimal/tailwind/video.tailwind.ts b/packages/skins/src/minimal/tailwind/video.tailwind.ts index f837bfc3..75878365 100644 --- a/packages/skins/src/minimal/tailwind/video.tailwind.ts +++ b/packages/skins/src/minimal/tailwind/video.tailwind.ts @@ -65,18 +65,21 @@ export const controls = cn( 'absolute bottom-0 inset-x-0', 'pt-8 px-1.5 pb-1.5 gap-2', 'text-white z-10', - // Transitions + // Transitions (fine pointer only — instant toggle on touch to avoid dead-zone taps) 'will-change-[translate,filter,opacity]', - 'transition-[translate,filter,opacity] ease-out', - 'delay-0 duration-75', + '[@media(pointer:fine)]:transition-[translate,filter,opacity]', + 'ease-out', + '[@media(pointer:fine)]:delay-0 [@media(pointer:fine)]:duration-75', // Hidden state - 'not-data-visible:opacity-0 not-data-visible:translate-y-full', - 'not-data-visible:blur-sm not-data-visible:pointer-events-none', - 'not-data-visible:delay-500 not-data-visible:duration-500', + 'not-data-visible:opacity-0 not-data-visible:pointer-events-none', + 'not-data-visible:translate-y-full not-data-visible:blur-sm', + '[@media(pointer:fine)]:not-data-visible:delay-500', + '[@media(pointer:fine)]:not-data-visible:duration-500', // Reduced motion + hidden - 'motion-reduce:not-data-visible:duration-100', + '[@media(pointer:fine)]:motion-reduce:not-data-visible:duration-100', 'motion-reduce:not-data-visible:translate-y-0', - 'motion-reduce:not-data-visible:blur-none motion-reduce:not-data-visible:scale-100', + 'motion-reduce:not-data-visible:blur-none', + 'motion-reduce:not-data-visible:scale-100', // Wider container '@sm/media-root:pt-10 @sm/media-root:px-3 @sm/media-root:pb-3', '@sm/media-root:gap-3.5'