mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-17 00:44:23 +02:00
Migrate to Mantine v8 and Design Changes (#961)
* mantine v8 migration * various design changes and improvements
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user