mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
fix(skin): hide volume popover when volume control is unsupported (#1025)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,38 @@ function PlayLabel(): ReactNode {
|
||||
return paused ? <>Play</> : <>Pause</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="left">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className={cn(popup.volume)}>
|
||||
<VolumeSlider.Root orientation="horizontal" thumbAlignment="edge" render={(props) => <SliderRoot {...props} />}>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
/* ------------------------------------------ Skin ------------------------------------------- */
|
||||
|
||||
export function MinimalAudioSkinTailwind(props: MinimalAudioSkinProps): ReactNode {
|
||||
@@ -196,33 +228,7 @@ export function MinimalAudioSkinTailwind(props: MinimalAudioSkinProps): ReactNod
|
||||
<Tooltip.Popup className={cn(popup.tooltip)}>Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="left">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className={cn(popup.volume)}>
|
||||
<VolumeSlider.Root
|
||||
orientation="horizontal"
|
||||
thumbAlignment="edge"
|
||||
render={(props) => <SliderRoot {...props} />}
|
||||
>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
</div>
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
|
||||
@@ -36,6 +36,38 @@ function PlayLabel(): ReactNode {
|
||||
return paused ? <>Play</> : <>Pause</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="left">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className="media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="horizontal" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
export function MinimalAudioSkin(props: MinimalAudioSkinProps): ReactNode {
|
||||
const { children, className, ...rest } = props;
|
||||
|
||||
@@ -132,29 +164,7 @@ export function MinimalAudioSkin(props: MinimalAudioSkinProps): ReactNode {
|
||||
<Tooltip.Popup className="media-tooltip">Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="left">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className="media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="horizontal" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
</div>
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
|
||||
@@ -97,6 +97,38 @@ function PlayLabel(): ReactNode {
|
||||
return paused ? <>Play</> : <>Pause</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className={cn(popup.popover, popup.volume)}>
|
||||
<VolumeSlider.Root orientation="vertical" thumbAlignment="edge" render={(props) => <SliderRoot {...props} />}>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
/* ------------------------------------------ Skin ------------------------------------------- */
|
||||
|
||||
export function AudioSkinTailwind(props: AudioSkinProps): ReactNode {
|
||||
@@ -188,33 +220,7 @@ export function AudioSkinTailwind(props: AudioSkinProps): ReactNode {
|
||||
<Tooltip.Popup className={cn(popup.tooltip)}>Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className={cn(popup.popover, popup.volume)}>
|
||||
<VolumeSlider.Root
|
||||
orientation="vertical"
|
||||
thumbAlignment="edge"
|
||||
render={(props) => <SliderRoot {...props} />}
|
||||
>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -36,6 +36,38 @@ function PlayLabel(): ReactNode {
|
||||
return paused ? <>Play</> : <>Pause</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className="media-surface media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
export function AudioSkin(props: AudioSkinProps): ReactNode {
|
||||
const { children, className, ...rest } = props;
|
||||
|
||||
@@ -125,29 +157,7 @@ export function AudioSkin(props: AudioSkinProps): ReactNode {
|
||||
<Tooltip.Popup className="media-surface media-tooltip">Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className="media-surface media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
</Tooltip.Provider>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -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 = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className={cn(popup.volume)}>
|
||||
<VolumeSlider.Root orientation="vertical" thumbAlignment="edge" render={(props) => <SliderRoot {...props} />}>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
/* ------------------------------------------ Skin ------------------------------------------- */
|
||||
|
||||
export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNode {
|
||||
@@ -270,33 +302,7 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod
|
||||
<Tooltip.Popup className={cn(popup.tooltip)}>Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className={cn(popup.volume)}>
|
||||
<VolumeSlider.Root
|
||||
orientation="vertical"
|
||||
thumbAlignment="edge"
|
||||
render={(props) => <SliderRoot {...props} />}
|
||||
>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
|
||||
@@ -78,6 +78,38 @@ function FullscreenLabel(): ReactNode {
|
||||
return fullscreen ? <>Exit fullscreen</> : <>Enter fullscreen</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className="media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode {
|
||||
const { children, className, poster, ...rest } = props;
|
||||
|
||||
@@ -196,29 +228,7 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode {
|
||||
<Tooltip.Popup className="media-tooltip">Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className="media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
|
||||
@@ -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 = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className={cn(popup.popover, popup.volume)}>
|
||||
<VolumeSlider.Root orientation="vertical" thumbAlignment="edge" render={(props) => <SliderRoot {...props} />}>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
/* ------------------------------------------ Skin ------------------------------------------- */
|
||||
|
||||
export function VideoSkinTailwind(props: VideoSkinProps): ReactNode {
|
||||
@@ -263,33 +295,7 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode {
|
||||
<Tooltip.Popup className={cn(popup.tooltip)}>Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button variant="icon" {...props} className={iconState.mute.button}>
|
||||
<VolumeOffIcon className={cn(icon, iconState.mute.volumeOff)} />
|
||||
<VolumeLowIcon className={cn(icon, iconState.mute.volumeLow)} />
|
||||
<VolumeHighIcon className={cn(icon, iconState.mute.volumeHigh)} />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className={cn(popup.popover, popup.volume)}>
|
||||
<VolumeSlider.Root
|
||||
orientation="vertical"
|
||||
thumbAlignment="edge"
|
||||
render={(props) => <SliderRoot {...props} />}
|
||||
>
|
||||
<VolumeSlider.Track render={(props) => <SliderTrack {...props} />}>
|
||||
<VolumeSlider.Fill render={(props) => <SliderFill {...props} />} />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb render={(props) => <SliderThumb persistent {...props} />} />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
|
||||
@@ -78,6 +78,38 @@ function FullscreenLabel(): ReactNode {
|
||||
return fullscreen ? <>Exit fullscreen</> : <>Enter fullscreen</>;
|
||||
}
|
||||
|
||||
function VolumePopover(): ReactNode {
|
||||
const volumeUnsupported = usePlayer((s) => s.volumeAvailability === 'unsupported');
|
||||
|
||||
const muteButton = (
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
if (volumeUnsupported) return muteButton;
|
||||
|
||||
return (
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger render={muteButton} />
|
||||
<Popover.Popup className="media-surface media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
export function VideoSkin(props: VideoSkinProps): ReactNode {
|
||||
const { children, className, poster, ...rest } = props;
|
||||
|
||||
@@ -189,29 +221,7 @@ export function VideoSkin(props: VideoSkinProps): ReactNode {
|
||||
<Tooltip.Popup className="media-surface media-tooltip">Toggle playback rate</Tooltip.Popup>
|
||||
</Tooltip.Root>
|
||||
|
||||
<Popover.Root openOnHover delay={200} closeDelay={100} side="top">
|
||||
<Popover.Trigger
|
||||
render={
|
||||
<MuteButton
|
||||
render={(props) => (
|
||||
<Button {...props} className="media-button--icon media-button--mute">
|
||||
<VolumeOffIcon className="media-icon media-icon--volume-off" />
|
||||
<VolumeLowIcon className="media-icon media-icon--volume-low" />
|
||||
<VolumeHighIcon className="media-icon media-icon--volume-high" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Popover.Popup className="media-surface media-popover media-popover--volume">
|
||||
<VolumeSlider.Root className="media-slider" orientation="vertical" thumbAlignment="edge">
|
||||
<VolumeSlider.Track className="media-slider__track">
|
||||
<VolumeSlider.Fill className="media-slider__fill" />
|
||||
</VolumeSlider.Track>
|
||||
<VolumeSlider.Thumb className="media-slider__thumb media-slider__thumb--persistent" />
|
||||
</VolumeSlider.Root>
|
||||
</Popover.Popup>
|
||||
</Popover.Root>
|
||||
<VolumePopover />
|
||||
|
||||
<Tooltip.Root side="top">
|
||||
<Tooltip.Trigger
|
||||
|
||||
@@ -82,6 +82,10 @@
|
||||
.media-default-skin .media-popover--volume {
|
||||
padding: 0.625rem 0.25rem;
|
||||
border-radius: calc(infinity * 1px);
|
||||
|
||||
&:has(media-volume-slider[data-availability="unsupported"]) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-tooltip {
|
||||
|
||||
@@ -107,3 +107,7 @@
|
||||
background-color: oklch(0 0 0 / 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.media-minimal-skin .media-popover--volume:has(media-volume-slider[data-availability="unsupported"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user