From c09dbdd121f2b8bb01e42d79350bf7a7acf09f28 Mon Sep 17 00:00:00 2001 From: rahim Date: Thu, 19 Mar 2026 01:14:57 -0700 Subject: [PATCH] fix(skin): hide volume popover when volume control is unsupported (#1025) --- packages/html/src/define/shared.css | 5 ++ .../presets/audio/minimal-skin.tailwind.tsx | 60 ++++++++++--------- .../react/src/presets/audio/minimal-skin.tsx | 56 ++++++++++------- .../react/src/presets/audio/skin.tailwind.tsx | 60 ++++++++++--------- packages/react/src/presets/audio/skin.tsx | 56 ++++++++++------- .../presets/video/minimal-skin.tailwind.tsx | 60 ++++++++++--------- .../react/src/presets/video/minimal-skin.tsx | 56 ++++++++++------- .../react/src/presets/video/skin.tailwind.tsx | 60 ++++++++++--------- packages/react/src/presets/video/skin.tsx | 56 ++++++++++------- .../src/default/css/components/popup.css | 4 ++ .../src/minimal/css/components/popup.css | 4 ++ 11 files changed, 277 insertions(+), 200 deletions(-) diff --git a/packages/html/src/define/shared.css b/packages/html/src/define/shared.css index dbe98d6a..456d624a 100644 --- a/packages/html/src/define/shared.css +++ b/packages/html/src/define/shared.css @@ -6,3 +6,8 @@ media-tooltip-group { :host { display: grid; } + +/* Hide volume popover when volume control is unsupported (e.g., iOS Safari). */ +.media-popover--volume:has(media-volume-slider[data-availability="unsupported"]) { + display: none; +} diff --git a/packages/react/src/presets/audio/minimal-skin.tailwind.tsx b/packages/react/src/presets/audio/minimal-skin.tailwind.tsx index e88f4fae..eaa77156 100644 --- a/packages/react/src/presets/audio/minimal-skin.tailwind.tsx +++ b/packages/react/src/presets/audio/minimal-skin.tailwind.tsx @@ -98,6 +98,38 @@ function PlayLabel(): ReactNode { return paused ? <>Play : <>Pause; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + }> + }> + } /> + + } /> + + + + ); +} + /* ------------------------------------------ Skin ------------------------------------------- */ export function MinimalAudioSkinTailwind(props: MinimalAudioSkinProps): ReactNode { @@ -196,33 +228,7 @@ export function MinimalAudioSkinTailwind(props: MinimalAudioSkinProps): ReactNod Toggle playback rate - - ( - - )} - /> - } - /> - - } - > - }> - } /> - - } /> - - - + diff --git a/packages/react/src/presets/audio/minimal-skin.tsx b/packages/react/src/presets/audio/minimal-skin.tsx index 904a5c7c..98e9e3a6 100644 --- a/packages/react/src/presets/audio/minimal-skin.tsx +++ b/packages/react/src/presets/audio/minimal-skin.tsx @@ -36,6 +36,38 @@ function PlayLabel(): ReactNode { return paused ? <>Play : <>Pause; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + + + + + + + + + ); +} + export function MinimalAudioSkin(props: MinimalAudioSkinProps): ReactNode { const { children, className, ...rest } = props; @@ -132,29 +164,7 @@ export function MinimalAudioSkin(props: MinimalAudioSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - - - - - - - - + diff --git a/packages/react/src/presets/audio/skin.tailwind.tsx b/packages/react/src/presets/audio/skin.tailwind.tsx index e475f61d..9a23b086 100644 --- a/packages/react/src/presets/audio/skin.tailwind.tsx +++ b/packages/react/src/presets/audio/skin.tailwind.tsx @@ -97,6 +97,38 @@ function PlayLabel(): ReactNode { return paused ? <>Play : <>Pause; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + }> + }> + } /> + + } /> + + + + ); +} + /* ------------------------------------------ Skin ------------------------------------------- */ export function AudioSkinTailwind(props: AudioSkinProps): ReactNode { @@ -188,33 +220,7 @@ export function AudioSkinTailwind(props: AudioSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - } - > - }> - } /> - - } /> - - - + diff --git a/packages/react/src/presets/audio/skin.tsx b/packages/react/src/presets/audio/skin.tsx index 3ce8cb06..074bcc6a 100644 --- a/packages/react/src/presets/audio/skin.tsx +++ b/packages/react/src/presets/audio/skin.tsx @@ -36,6 +36,38 @@ function PlayLabel(): ReactNode { return paused ? <>Play : <>Pause; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + + + + + + + + + ); +} + export function AudioSkin(props: AudioSkinProps): ReactNode { const { children, className, ...rest } = props; @@ -125,29 +157,7 @@ export function AudioSkin(props: AudioSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - - - - - - - - + diff --git a/packages/react/src/presets/video/minimal-skin.tailwind.tsx b/packages/react/src/presets/video/minimal-skin.tailwind.tsx index 2b0a5db4..5adbcb29 100644 --- a/packages/react/src/presets/video/minimal-skin.tailwind.tsx +++ b/packages/react/src/presets/video/minimal-skin.tailwind.tsx @@ -144,6 +144,38 @@ function FullscreenLabel(): ReactNode { return fullscreen ? <>Exit fullscreen : <>Enter fullscreen; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + }> + }> + } /> + + } /> + + + + ); +} + /* ------------------------------------------ Skin ------------------------------------------- */ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNode { @@ -270,33 +302,7 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod Toggle playback rate - - ( - - )} - /> - } - /> - - } - > - }> - } /> - - } /> - - - + Exit fullscreen : <>Enter fullscreen; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + + + + + + + + + ); +} + export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { const { children, className, poster, ...rest } = props; @@ -196,29 +228,7 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - - - - - - - - + Exit fullscreen : <>Enter fullscreen; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + }> + }> + } /> + + } /> + + + + ); +} + /* ------------------------------------------ Skin ------------------------------------------- */ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { @@ -263,33 +295,7 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - } - > - }> - } /> - - } /> - - - + Exit fullscreen : <>Enter fullscreen; } +function VolumePopover(): ReactNode { + const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported'); + + const muteButton = ( + ( + + )} + /> + ); + + if (volumeUnsupported) return muteButton; + + return ( + + + + + + + + + + + + ); +} + export function VideoSkin(props: VideoSkinProps): ReactNode { const { children, className, poster, ...rest } = props; @@ -189,29 +221,7 @@ export function VideoSkin(props: VideoSkinProps): ReactNode { Toggle playback rate - - ( - - )} - /> - } - /> - - - - - - - - - +