🚸(frontend) auto-hide participant controls after 3s of inactivity

Auto-hides participant tile controls after 3 seconds of cursor inactivity
to reduce visual clutter. Controls reappear on cursor movement.
This commit is contained in:
lebaudantoine
2025-02-14 17:21:31 +01:00
committed by aleb_the_flash
parent c3e4ea0fd1
commit aa2783ae2e

View File

@@ -15,7 +15,7 @@ import {
} from '@livekit/components-react' } from '@livekit/components-react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { TrackReferenceOrPlaceholder } from '@livekit/components-core' import { TrackReferenceOrPlaceholder } from '@livekit/components-core'
import { useEffect, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useSidePanel } from '../hooks/useSidePanel' import { useSidePanel } from '../hooks/useSidePanel'
import { useFullScreen } from '../hooks/useFullScreen' import { useFullScreen } from '../hooks/useFullScreen'
import { Participant, Track } from 'livekit-client' import { Participant, Track } from 'livekit-client'
@@ -126,6 +126,8 @@ const MuteButton = ({ participant }: { participant: Participant }) => {
) )
} }
const MOUSE_IDLE_TIME = 3000
export const ParticipantTileFocus = ({ export const ParticipantTileFocus = ({
trackRef, trackRef,
}: { }: {
@@ -134,8 +136,11 @@ export const ParticipantTileFocus = ({
const [hovered, setHovered] = useState(false) const [hovered, setHovered] = useState(false)
const [opacity, setOpacity] = useState(0) const [opacity, setOpacity] = useState(0)
const idleTimerRef = useRef<number | null>(null)
const [isIdleRef, setIsIdleRef] = useState(false)
useEffect(() => { useEffect(() => {
if (hovered) { if (hovered && !isIdleRef) {
// Wait for next frame to ensure element is mounted // Wait for next frame to ensure element is mounted
requestAnimationFrame(() => { requestAnimationFrame(() => {
setOpacity(0.6) setOpacity(0.6)
@@ -143,7 +148,17 @@ export const ParticipantTileFocus = ({
} else { } else {
setOpacity(0) setOpacity(0)
} }
}, [hovered]) }, [hovered, isIdleRef])
const handleMouseMove = () => {
if (idleTimerRef.current) {
window.clearTimeout(idleTimerRef.current)
}
idleTimerRef.current = window.setTimeout(() => {
setIsIdleRef(true)
}, MOUSE_IDLE_TIME)
setIsIdleRef(false)
}
const participant = trackRef.participant const participant = trackRef.participant
@@ -164,6 +179,7 @@ export const ParticipantTileFocus = ({
})} })}
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
onMouseMove={handleMouseMove}
> >
{hovered && ( {hovered && (
<div <div