fix mouseover state causing rerender in fullscreen player (#1535)

This commit is contained in:
jeffvli
2026-01-17 03:02:05 -08:00
parent b4b0c6cedd
commit 3f3540dd2b
4 changed files with 36 additions and 31 deletions
@@ -91,7 +91,7 @@ export const FullScreenPlayerQueue = () => {
pos="relative"
size="lg"
uppercase
variant="subtle"
variant="transparent"
>
{item.label}
</Button>
@@ -10,8 +10,31 @@
@media screen and (orientation: portrait) {
padding: 2rem 2rem 1rem;
}
&:hover .controls-container {
[data-variant='subtle'] {
color: var(--theme-colors-foreground);
background: var(--theme-colors-surface);
border: 1px solid transparent;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background: lighten(var(--theme-colors-surface), 5%);
}
@mixin light {
background: lighten(var(--theme-colors-surface), 5%);
}
}
}
}
}
.responsive-container {
display: grid;
grid-template-rows: minmax(0, 1fr);
@@ -220,11 +220,7 @@ const BackgroundImageOverlay = memo(
BackgroundImageOverlay.displayName = 'BackgroundImageOverlay';
interface ControlsProps {
isPageHovered: boolean;
}
const Controls = ({ isPageHovered }: ControlsProps) => {
const Controls = () => {
const { t } = useTranslation();
const {
dynamicBackground,
@@ -271,6 +267,7 @@ const Controls = ({ isPageHovered }: ControlsProps) => {
return (
<Group
className={styles.controlsContainer}
gap="sm"
p="1rem"
pos="absolute"
@@ -285,7 +282,7 @@ const Controls = ({ isPageHovered }: ControlsProps) => {
iconProps={{ size: 'lg' }}
onClick={handleToggleFullScreenPlayer}
tooltip={{ label: t('common.minimize', { postProcess: 'titleCase' }) }}
variant={isPageHovered ? 'default' : 'subtle'}
variant="subtle"
/>
<Popover position="bottom-start">
<Popover.Target>
@@ -293,7 +290,7 @@ const Controls = ({ isPageHovered }: ControlsProps) => {
icon="settings2"
iconProps={{ size: 'lg' }}
tooltip={{ label: t('common.configure', { postProcess: 'titleCase' }) }}
variant={isPageHovered ? 'default' : 'subtle'}
variant="subtle"
/>
</Popover.Target>
<Popover.Dropdown>
@@ -556,7 +553,7 @@ const Controls = ({ isPageHovered }: ControlsProps) => {
</Popover>
<ListConfigMenu
buttonProps={{
variant: isPageHovered ? 'default' : 'subtle',
variant: 'subtle',
}}
displayTypes={[{ hidden: true, value: ListDisplayType.GRID }]}
listKey={ItemListKey.FULL_SCREEN}
@@ -616,20 +613,11 @@ interface PlayerContainerProps {
children: ReactNode;
dynamicBackground: boolean | undefined;
dynamicIsImage: boolean | undefined;
onMouseEnter: () => void;
onMouseLeave: () => void;
windowBarStyle: Platform;
}
const PlayerContainer = memo(
({
children,
dynamicBackground,
dynamicIsImage,
onMouseEnter,
onMouseLeave,
windowBarStyle,
}: PlayerContainerProps) => {
({ children, dynamicBackground, dynamicIsImage, windowBarStyle }: PlayerContainerProps) => {
const currentSong = usePlayerSong();
const imageUrl = useItemImageUrl({
id: currentSong?.imageId || undefined,
@@ -650,8 +638,6 @@ const PlayerContainer = memo(
custom={{ background, dynamicBackground, windowBarStyle }}
exit="closed"
initial="closed"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
transition={{ duration: 2 }}
variants={containerVariants}
>
@@ -672,8 +658,6 @@ export const FullScreenPlayer = () => {
const { setStore } = useFullScreenPlayerStoreActions();
const { windowBarStyle } = useWindowSettings();
const [isPageHovered, setIsPageHovered] = useState(false);
const location = useLocation();
const isOpenedRef = useRef<boolean | null>(null);
@@ -689,11 +673,9 @@ export const FullScreenPlayer = () => {
<PlayerContainer
dynamicBackground={dynamicBackground}
dynamicIsImage={dynamicIsImage}
onMouseEnter={() => setIsPageHovered(true)}
onMouseLeave={() => setIsPageHovered(false)}
windowBarStyle={windowBarStyle}
>
<Controls isPageHovered={isPageHovered} />
<Controls />
<BackgroundImageOverlay
dynamicBackground={dynamicBackground}
dynamicImageBlur={dynamicImageBlur}
+5 -5
View File
@@ -1,4 +1,4 @@
import { memo, ReactNode, useMemo } from 'react';
import { ReactNode, useMemo } from 'react';
import styles from './option.module.css';
@@ -12,7 +12,7 @@ interface OptionProps extends GroupProps {
const defaultClassNames = { root: styles.root };
export const Option = memo(({ children, classNames, ...props }: OptionProps) => {
export const Option = ({ children, classNames, ...props }: OptionProps) => {
const mergedClassNames = useMemo(
() => (classNames ? { ...defaultClassNames, ...classNames } : defaultClassNames),
[classNames],
@@ -23,7 +23,7 @@ export const Option = memo(({ children, classNames, ...props }: OptionProps) =>
{children}
</Group>
);
});
};
Option.displayName = 'Option';
@@ -43,5 +43,5 @@ const Control = ({ children }: ControlProps) => {
return <Flex justify="flex-end">{children}</Flex>;
};
(Option as typeof Option & { Label: typeof Label }).Label = Label;
(Option as typeof Option & { Control: typeof Control }).Control = Control;
Option.Label = Label;
Option.Control = Control;