mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-03 03:11:40 +00:00
* feat: add semantic selectors for now-playing media This change adds unique class names to the elements that display the currently playing media information. This makes it easier for extension developers to parse the DOM and understand what media is playing. The following classes have been added: - `media-player`: The main player container. - `player-cover-art`: The cover art of the playing track. - `song-title`: The title of the playing track. - `song-artist`: The artist of the playing track. - `song-album`: The album of the playing track. - `player-state-playing`/`player-state-paused`: The state of the player. - `elapsed-time`: The elapsed time of the playing track. - `total-duration`: The total duration of the playing track. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
91 lines
3 KiB
TypeScript
91 lines
3 KiB
TypeScript
import clsx from 'clsx';
|
|
import { t } from 'i18next';
|
|
import { forwardRef, ReactNode } from 'react';
|
|
|
|
import styles from './player-button.module.css';
|
|
|
|
import { ActionIcon, ActionIconProps } from '/@/shared/components/action-icon/action-icon';
|
|
import { Tooltip, TooltipProps } from '/@/shared/components/tooltip/tooltip';
|
|
import { PlaybackSelectors } from '/@/shared/constants/playback-selectors';
|
|
|
|
interface PlayerButtonProps extends Omit<ActionIconProps, 'icon' | 'variant'> {
|
|
icon: ReactNode;
|
|
isActive?: boolean;
|
|
tooltip?: Omit<TooltipProps, 'children'>;
|
|
variant: 'main' | 'secondary' | 'tertiary';
|
|
}
|
|
|
|
export const PlayerButton = forwardRef<HTMLButtonElement, PlayerButtonProps>(
|
|
({ icon, isActive, tooltip, variant, ...rest }: PlayerButtonProps, ref) => {
|
|
if (tooltip) {
|
|
return (
|
|
<Tooltip {...tooltip}>
|
|
<ActionIcon
|
|
className={clsx({
|
|
[styles.active]: isActive,
|
|
})}
|
|
ref={ref}
|
|
{...rest}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
rest.onClick?.(e);
|
|
}}
|
|
variant="subtle"
|
|
>
|
|
{icon}
|
|
</ActionIcon>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ActionIcon
|
|
className={clsx(styles.playerButton, styles[variant], {
|
|
[styles.active]: isActive,
|
|
})}
|
|
ref={ref}
|
|
{...rest}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
rest.onClick?.(e);
|
|
}}
|
|
variant="subtle"
|
|
>
|
|
{icon}
|
|
</ActionIcon>
|
|
);
|
|
},
|
|
);
|
|
|
|
interface PlayButtonProps extends Omit<ActionIconProps, 'icon' | 'variant'> {
|
|
isPaused?: boolean;
|
|
}
|
|
|
|
export const PlayButton = forwardRef<HTMLButtonElement, PlayButtonProps>(
|
|
({ isPaused, onClick, ...props }: PlayButtonProps, ref) => {
|
|
const playerStateClass = isPaused
|
|
? PlaybackSelectors.playerStatePaused
|
|
: PlaybackSelectors.playerStatePlaying;
|
|
|
|
return (
|
|
<ActionIcon
|
|
className={clsx(styles.main, playerStateClass)}
|
|
icon={isPaused ? 'mediaPlay' : 'mediaPause'}
|
|
iconProps={{
|
|
size: 'lg',
|
|
}}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onClick?.(e);
|
|
}}
|
|
ref={ref}
|
|
tooltip={{
|
|
label: isPaused
|
|
? (t('player.play', { postProcess: 'sentenceCase' }) as string)
|
|
: (t('player.pause', { postProcess: 'sentenceCase' }) as string),
|
|
}}
|
|
{...props}
|
|
/>
|
|
);
|
|
},
|
|
);
|