refactor: correctly focus player buttons

This commit is contained in:
Timothy Z. 2026-04-29 16:28:39 +03:00
parent f70af4efda
commit b7655e658f
3 changed files with 13 additions and 13 deletions

View file

@ -117,18 +117,18 @@ const ControlBar = React.forwardRef(({
onSeekRequested={onSeekRequested}
/>
<div className={styles['control-bar-buttons-container']}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': typeof paused !== 'boolean' })} title={paused ? t('PLAYER_PLAY') : t('PLAYER_PAUSE')} tabIndex={0} onClick={onPlayPauseButtonClick}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': typeof paused !== 'boolean' })} title={paused ? t('PLAYER_PLAY') : t('PLAYER_PAUSE')} tabIndex={-1} onClick={onPlayPauseButtonClick}>
<Icon className={styles['icon']} name={typeof paused !== 'boolean' || paused ? 'play' : 'pause'} />
</Button>
{
nextVideo !== null ?
<Button className={classnames(styles['control-bar-button'])} title={t('PLAYER_NEXT_VIDEO')} tabIndex={0} onClick={onNextVideoButtonClick}>
<Button className={classnames(styles['control-bar-button'])} title={t('PLAYER_NEXT_VIDEO')} tabIndex={-1} onClick={onNextVideoButtonClick}>
<Icon className={styles['icon']} name={'next'} />
</Button>
:
null
}
<Button className={classnames(styles['control-bar-button'], { 'disabled': typeof muted !== 'boolean' })} title={muted ? t('PLAYER_UNMUTE') : t('PLAYER_MUTE')} tabIndex={0} onClick={onMuteButtonClick}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': typeof muted !== 'boolean' })} title={muted ? t('PLAYER_UNMUTE') : t('PLAYER_MUTE')} tabIndex={-1} onClick={onMuteButtonClick}>
<Icon
className={styles['icon']}
name={
@ -156,33 +156,33 @@ const ControlBar = React.forwardRef(({
<Icon className={styles['icon']} name={'more-vertical'} />
</Button>
<div className={classnames(styles['control-bar-buttons-menu-container'], { 'open': buttonsMenuOpen })}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': statistics === null || statistics.type === 'Err' || stream === null || typeof stream.infoHash !== 'string' || typeof stream.fileIdx !== 'number' })} tabIndex={0} onMouseDown={onStatisticsButtonMouseDown} onClick={onToggleStatisticsMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': statistics === null || statistics.type === 'Err' || stream === null || typeof stream.infoHash !== 'string' || typeof stream.fileIdx !== 'number' })} tabIndex={-1} onMouseDown={onStatisticsButtonMouseDown} onClick={onToggleStatisticsMenu}>
<Icon className={styles['icon']} name={'network'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': playbackSpeed === null })} tabIndex={0} onMouseDown={onSpeedButtonMouseDown} onClick={onToggleSpeedMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': playbackSpeed === null })} tabIndex={-1} onMouseDown={onSpeedButtonMouseDown} onClick={onToggleSpeedMenu}>
<Icon className={styles['icon']} name={'speed'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !chromecastServiceActive })} tabIndex={0} onClick={onChromecastButtonClick}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !chromecastServiceActive })} tabIndex={-1} onClick={onChromecastButtonClick}>
<Icon className={styles['icon']} name={'cast'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !Array.isArray(subtitlesTracks) || subtitlesTracks.length === 0 })} tabIndex={0} onMouseDown={onSubtitlesButtonMouseDown} onClick={onToggleSubtitlesMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !Array.isArray(subtitlesTracks) || subtitlesTracks.length === 0 })} tabIndex={-1} onMouseDown={onSubtitlesButtonMouseDown} onClick={onToggleSubtitlesMenu}>
<Icon className={styles['icon']} name={'subtitles'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !Array.isArray(audioTracks) || audioTracks.length === 0 })} tabIndex={0} onMouseDown={onAudioButtonMouseDown} onClick={onToggleAudioMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !Array.isArray(audioTracks) || audioTracks.length === 0 })} tabIndex={-1} onMouseDown={onAudioButtonMouseDown} onClick={onToggleAudioMenu}>
<Icon className={styles['icon']} name={'audio-tracks'} />
</Button>
{
metaItem?.content?.videos?.length > 0 ?
<Button className={styles['control-bar-button']} tabIndex={0} onMouseDown={onVideosButtonMouseDown} onClick={onToggleSideDrawer}>
<Button className={styles['control-bar-button']} tabIndex={-1} onMouseDown={onVideosButtonMouseDown} onClick={onToggleSideDrawer}>
<Icon className={styles['icon']} name={'episodes'} />
</Button>
:
null
}
<Button className={classnames(styles['control-bar-button'], { 'disabled': videoScale === null })} title={videoScaleLabel} tabIndex={0} onClick={onVideoScaleChanged}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': videoScale === null })} title={videoScaleLabel} tabIndex={-1} onClick={onVideoScaleChanged}>
<Icon className={styles['icon']} name={'scale'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !stream })} tabIndex={0} onMouseDown={onOptionsButtonMouseDown} onClick={onToggleOptionsMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !stream })} tabIndex={-1} onMouseDown={onOptionsButtonMouseDown} onClick={onToggleOptionsMenu}>
<Icon className={styles['icon']} name={'more-horizontal'} />
</Button>
</div>

View file

@ -59,7 +59,7 @@ const SeekBar = ({ className, time, duration, buffered, onSeekRequested }) => {
onSlide={onSlide}
onComplete={onComplete}
/>
<Button onClick={toggleRemainingTimeMode} tabIndex={0}>
<Button onClick={toggleRemainingTimeMode} tabIndex={-1}>
<div className={styles['label']}>
{remainingTimeMode && duration !== null && !isNaN(duration)
? formatTime(duration - time, '-')

View file

@ -3,7 +3,7 @@
import { useEffect, useRef } from 'react';
import { useGamepad } from '../GamepadContext';
const FOCUSABLE = '[tabindex="0"]';
const FOCUSABLE = '[tabindex]';
const getActiveScope = (fallback: HTMLDivElement | null): HTMLElement | null => {
const modal = document.querySelector<HTMLElement>('.modals-container');