pl-fe: video/audio player restyle

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-13 11:29:15 +02:00
parent 5df6d1db61
commit 77a62c576f
3 changed files with 63 additions and 42 deletions

View File

@ -316,7 +316,7 @@ const Audio: React.FC<IAudio> = (props) => {
};
const _draw = () => {
visualizer.current?.draw(_getCX(), _getCY(), _getAccentColor(), _getRadius(), _getScaleCoefficient());
visualizer.current?.draw(_getCX(), _getCY(), _getAccentColor() || '#ffffff', _getRadius(), _getScaleCoefficient());
};
const _getRadius = (): number => ((height || props.height || 0) - (PADDING * _getScaleCoefficient()) * 2) / 2;
@ -327,7 +327,7 @@ const Audio: React.FC<IAudio> = (props) => {
const _getCY = (): number => Math.floor(_getRadius() + (PADDING * _getScaleCoefficient()));
const _getAccentColor = (): string => accentColor || '#ffffff';
const _getAccentColor = () => accentColor || undefined;
const _getBackgroundColor = (): string => backgroundColor || '#000000';
@ -493,15 +493,19 @@ const Audio: React.FC<IAudio> = (props) => {
/>
</div>
<div className='video-player__controls absolute bottom-0 left-0 z-[2] box-border bg-transparent px-4 py-0 pt-2.5 opacity-100 ring-0 transition-opacity duration-100 ease-in-out'>
<div className='mx-[-5px] my-0 flex justify-between pb-2'>
<div className={clsx(
'video-player__controls video-player__controls--visible',
// { 'video-player__controls--visible': paused || hovered },
)}
>
<div className='mx-[-5px] my-0 flex justify-between'>
<div className='video-player__buttons left'>
<button
type='button'
title={intl.formatMessage(paused ? messages.play : messages.pause)}
aria-label={intl.formatMessage(paused ? messages.play : messages.pause)}
className='player-button text-current opacity-[75] hover:text-current hover:opacity-100 focus:text-current focus:opacity-100 active:text-current active:opacity-100'
className={clsx('player-button', fullscreen && 'py-2.5')}
onClick={togglePlay}
>
<Icon src={paused ? require('@phosphor-icons/core/regular/play.svg') : require('@phosphor-icons/core/regular/pause.svg')} />
@ -511,25 +515,14 @@ const Audio: React.FC<IAudio> = (props) => {
type='button'
title={intl.formatMessage(muted ? messages.unmute : messages.mute)}
aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)}
className='player-button text-current opacity-[75] hover:text-current hover:opacity-100 focus:text-current focus:opacity-100 active:text-current active:opacity-100'
className={clsx('player-button', fullscreen && 'py-2.5')}
onClick={toggleMute}
>
<Icon src={muted ? require('@phosphor-icons/core/regular/speaker-x.svg') : require('@phosphor-icons/core/regular/speaker-high.svg')} />
</button>
<div
className={clsx('video-player__volume before:bg-white/10', { 'overflow-visible w-12 mr-4': hovered })}
ref={slider}
onMouseDown={handleVolumeMouseDown}
>
<div
className='video-player__volume__current'
style={{
width: `${volume * 100}%`,
backgroundColor: _getAccentColor(),
}}
/>
<div className={clsx('video-player__volume', { 'overflow-visible w-12 mr-4': hovered })} onMouseDown={handleVolumeMouseDown} ref={slider}>
<div className='video-player__volume__current' style={{ width: `${volume * 100}%`, backgroundColor: _getAccentColor() }} />
<span
className={clsx('video-player__volume__handle', { 'opacity-100': dragging || hovered })}
tabIndex={0}
@ -537,7 +530,7 @@ const Audio: React.FC<IAudio> = (props) => {
/>
</div>
<span className='mx-[5px] my-0 inline flex-initial overflow-hidden text-ellipsis'>
<span className='my-0 inline flex-initial overflow-hidden text-ellipsis text-black dark:text-white'>
<span className='text-sm font-medium text-current'>{formatTime(Math.floor(currentTime))}</span>
{getDuration() && (<>
<span className='mx-1.5 my-0 inline-block text-sm font-medium text-current'>/</span>
@ -550,7 +543,7 @@ const Audio: React.FC<IAudio> = (props) => {
<a
title={intl.formatMessage(messages.download)}
aria-label={intl.formatMessage(messages.download)}
className='text-inherit'
className='player-button text-inherit'
href={src}
download
target='_blank'

View File

@ -19,6 +19,7 @@ const messages = defineMessages({
pause: { id: 'video.pause', defaultMessage: 'Pause' },
mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
download: { id: 'video.download', defaultMessage: 'Download file' },
fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
});
@ -493,10 +494,15 @@ const Video: React.FC<IVideo> = ({
onVolumeChange={handleVolumeChange}
/>
<div className={clsx('video-player__controls absolute inset-x-0 bottom-0 z-[2] box-border px-4 py-0 opacity-0 ring-0 transition-opacity duration-100 ease-in-out', { 'opacity-100': paused || hovered })}>
<div
className={clsx(
'video-player__controls',
{ 'video-player__controls--visible': paused || hovered },
)}
>
<div className='video-player__seek' onMouseDown={handleMouseDown} ref={seek}>
<div className='absolute top-3.5 block h-1 rounded bg-white/20' style={{ width: `${buffer}%` }} />
<div className='absolute top-3.5 block h-1 rounded bg-accent-500' style={{ width: `${progress}%` }} />
<div className='absolute top-1 block h-1 rounded bg-black/20 dark:bg-white/20' style={{ width: `${buffer}%` }} />
<div className='absolute top-1 block h-1 rounded bg-accent-500' style={{ width: `${progress}%` }} />
<span
className={clsx('video-player__seek__handle', { 'opacity-100': dragging })}
@ -506,7 +512,7 @@ const Video: React.FC<IVideo> = ({
/>
</div>
<div className='mx-[-5px] my-0 flex justify-between pb-2'>
<div className='mx-[-5px] my-0 flex justify-between'>
<div className='video-player__buttons left'>
<button
type='button'
@ -539,9 +545,9 @@ const Video: React.FC<IVideo> = ({
</div>
{(detailed || fullscreen) && (
<span>
<span className='text-sm font-medium text-white'>{formatTime(currentTime)}</span>
<span className='mx-1.5 my-0 inline-block text-sm font-medium text-white'>/</span>
<span className='text-black dark:text-white'>
<span className='text-sm font-medium'>{formatTime(currentTime)}</span>
<span className='mx-1.5 my-0 inline-block text-sm font-medium'>/</span>
<span className='text-sm font-medium'>{formatTime(duration)}</span>
</span>
)}
@ -552,6 +558,16 @@ const Video: React.FC<IVideo> = ({
</div>
<div className='video-player__buttons right'>
<a
title={intl.formatMessage(messages.download)}
aria-label={intl.formatMessage(messages.download)}
className='player-button text-inherit'
href={src}
download
target='_blank'
>
<Icon src={require('@phosphor-icons/core/regular/download-simple.svg')} />
</a>
<button
type='button'
title={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}

View File

@ -12,27 +12,41 @@
.video-player {
&__controls {
background: linear-gradient(0deg, #000000d9 0, #00000073 60%, transparent);
@apply bg-primary-200 dark:bg-primary-700 box-border ring-0 transition-all duration-300 ease-in-out;
position: absolute;
left: 0.75rem;
right: 0.75rem;
bottom: -4rem;
z-index: 2;
opacity: 0.8;
border-radius: 0.625rem;
padding: 0.25rem 0.75rem;
&--visible {
bottom: 0.75rem;
}
&:has(.video-player__seek) {
padding-top: 0.5rem;
}
}
&__buttons {
@apply flex min-w-[30px] items-center text-base whitespace-nowrap overflow-hidden text-ellipsis flex-initial;
@apply flex items-center text-base whitespace-nowrap overflow-hidden text-ellipsis flex-initial gap-1;
flex: 0 1 auto;
.player-button {
@apply inline-block outline-0 bg-transparent text-base border-0 text-white/75 active:text-white hover:text-white focus:text-white;
@apply block outline-0 bg-transparent text-base border-0 text-black dark:text-white rounded-full;
flex: 0 0 auto;
padding: 5px 6px;
padding: 4px;
&:hover {
@apply dark:bg-primary-200/20 bg-primary-700/20 rounded-full;
}
.svg-icon {
@apply w-5 h-5;
}
&:active,
&:hover,
&:focus {
@apply text-white;
}
}
}
@ -56,7 +70,6 @@
&__handle {
@apply bg-accent-500 absolute z-[3] rounded-[50%] size-3 top-1/2 left-0 -ml-1.5 opacity-0;
transform: translate(0, -50%);
box-shadow: 1px 2px 6px #0003;
.no-reduce-motion & {
transition: opacity 100ms linear;
@ -71,11 +84,10 @@
}
&__seek {
@apply cursor-pointer h-6 relative before:content-[''] before:w-full before:bg-white/35 before:rounded before:block before:absolute before:h-1 before:top-3.5;
@apply cursor-pointer h-3 relative before:content-[''] before:w-full before:bg-black/35 dark:before:bg-white/35 before:rounded before:block before:absolute before:h-1 before:top-1;
&__handle {
@apply bg-accent-500 absolute z-[3] opacity-0 rounded-[50%] size-3 top-2.5 -ml-1.5;
box-shadow: 1px 2px 6px #0003;
@apply bg-accent-500 absolute z-[3] opacity-0 rounded-[50%] size-3 -ml-1.5;
.no-reduce-motion & {
transition: opacity 0.1s ease;