Migrate to Mantine v8 and Design Changes (#961)

* mantine v8 migration

* various design changes and improvements
This commit is contained in:
Jeff
2025-06-24 00:04:36 -07:00
committed by GitHub
parent bea55d48a8
commit c1330d92b2
473 changed files with 12469 additions and 11607 deletions
@@ -1,10 +1,8 @@
import type { UnstyledButtonProps } from '@mantine/core';
import clsx from 'clsx';
import { MouseEvent, useState } from 'react';
import React, { MouseEvent, useState } from 'react';
import { RiHeartFill, RiHeartLine, RiMoreFill, RiPlayFill } from 'react-icons/ri';
import styled from 'styled-components';
import styles from './grid-card-controls.module.css';
import { _Button } from '/@/renderer/components/button';
import {
ALBUM_CONTEXT_MENU_ITEMS,
ARTIST_CONTEXT_MENU_ITEMS,
@@ -12,105 +10,16 @@ import {
} from '/@/renderer/features/context-menu/context-menu-items';
import { useHandleGridContextMenu } from '/@/renderer/features/context-menu/hooks/use-handle-context-menu';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Button } from '/@/shared/components/button/button';
import { Icon } from '/@/shared/components/icon/icon';
import { LibraryItem } from '/@/shared/types/domain-types';
import { Play, PlayQueueAddOptions } from '/@/shared/types/types';
type PlayButtonType = React.ComponentPropsWithoutRef<'button'> & UnstyledButtonProps;
const PlayButton = styled.button<PlayButtonType>`
position: absolute;
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
background-color: rgb(255 255 255);
border: none;
border-radius: 50%;
opacity: 0.8;
transition: opacity 0.2s ease-in-out;
transition: scale 0.1s ease-in-out;
&:hover {
opacity: 1;
scale: 1.1;
}
&:active {
opacity: 1;
scale: 1;
}
svg {
fill: rgb(0 0 0);
stroke: rgb(0 0 0);
}
`;
const SecondaryButton = styled(_Button)`
opacity: 0.8;
transition: opacity 0.2s ease-in-out;
transition: scale 0.2s linear;
&:hover {
opacity: 1;
scale: 1.1;
}
&:active {
opacity: 1;
scale: 1;
}
`;
const GridCardControlsContainer = styled.div<{ $isFavorite?: boolean }>`
position: absolute;
z-index: 100;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
`;
const FavoriteBanner = styled.div`
position: absolute;
top: -50px;
left: -50px;
width: 80px;
height: 80px;
pointer-events: none;
content: '';
background-color: var(--primary-color);
box-shadow: 0 0 10px 8px rgb(0 0 0 / 80%);
transform: rotate(-45deg);
`;
const ControlsRow = styled.div`
width: 100%;
height: calc(100% / 3);
`;
const BottomControls = styled(ControlsRow)`
position: absolute;
bottom: 0;
display: flex;
gap: 0.5rem;
align-items: flex-end;
justify-content: flex-end;
padding: 1rem 0.5rem;
`;
const FavoriteWrapper = styled.span<{ isFavorite: boolean }>`
svg {
fill: ${(props) => props.isFavorite && 'var(--primary-color)'};
}
`;
export const GridCardControls = ({
handleFavorite,
handlePlayQueueAdd,
isHovered,
itemData,
itemType,
resetInfiniteLoaderCache,
@@ -122,6 +31,7 @@ export const GridCardControls = ({
serverId: string;
}) => void;
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
isHovered?: boolean;
itemData: any;
itemType: LibraryItem;
resetInfiniteLoaderCache?: () => void;
@@ -168,50 +78,46 @@ export const GridCardControls = ({
return (
<>
{isFavorite ? <FavoriteBanner /> : null}
<GridCardControlsContainer
$isFavorite
className="card-controls"
>
<PlayButton onClick={handlePlay}>
<RiPlayFill size={25} />
</PlayButton>
<BottomControls>
{itemType !== LibraryItem.PLAYLIST && (
<SecondaryButton
onClick={(e) => handleFavorites(e, itemData?.serverId)}
p={5}
variant="subtle"
>
<FavoriteWrapper isFavorite={itemData?.isFavorite}>
{isFavorite ? (
<RiHeartFill size={20} />
) : (
<RiHeartLine
color="white"
size={20}
/>
)}
</FavoriteWrapper>
</SecondaryButton>
)}
<SecondaryButton
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleContextMenu(e, [itemData]);
}}
p={5}
variant="subtle"
{isFavorite ? <div className={styles.favoriteBanner} /> : null}
{isHovered && (
<div className={clsx(styles.gridCardControlsContainer)}>
<Button
classNames={{ root: styles.playButton }}
onClick={handlePlay}
variant="filled"
>
<RiMoreFill
color="white"
size={20}
<Icon
icon="mediaPlay"
size="xl"
/>
</SecondaryButton>
</BottomControls>
</GridCardControlsContainer>
</Button>
<div className={styles.bottomControls}>
{itemType !== LibraryItem.PLAYLIST && (
<ActionIcon
classNames={{ root: styles.secondaryButton }}
icon={isFavorite ? 'favorite' : 'favorite'}
iconProps={{
fill: isFavorite ? 'primary' : undefined,
}}
onClick={(e) => handleFavorites(e, itemData?.serverId)}
size="sm"
variant="transparent"
/>
)}
<ActionIcon
classNames={{ root: styles.secondaryButton }}
icon="ellipsisHorizontal"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleContextMenu(e, [itemData]);
}}
size="sm"
variant="transparent"
/>
</div>
</div>
)}
</>
);
};