Improve grid card components

- Dynamic placeholder depending on item type
- Fix skeleton for default card
This commit is contained in:
jeffvli 2023-05-09 18:55:26 -07:00
parent b5da8aeb55
commit 2100c1495d
2 changed files with 103 additions and 25 deletions

View file

@ -1,4 +1,7 @@
import { Center, Stack } from '@mantine/core';
import { RiAlbumFill, RiUserVoiceFill, RiPlayListFill } from 'react-icons/ri';
import { generatePath, useNavigate } from 'react-router-dom'; import { generatePath, useNavigate } from 'react-router-dom';
import { SimpleImg } from 'react-simple-img';
import { ListChildComponentProps } from 'react-window'; import { ListChildComponentProps } from 'react-window';
import styled from 'styled-components'; import styled from 'styled-components';
import { Album, AlbumArtist, Artist, LibraryItem } from '/@/renderer/api/types'; import { Album, AlbumArtist, Artist, LibraryItem } from '/@/renderer/api/types';
@ -88,14 +91,6 @@ const ImageContainer = styled.div`
} }
`; `;
const Image = styled.img`
width: 100%;
max-width: 100%;
height: auto;
object-fit: contain;
border: 0;
`;
const DetailContainer = styled.div` const DetailContainer = styled.div`
margin-top: 0.5rem; margin-top: 0.5rem;
`; `;
@ -120,6 +115,26 @@ export const DefaultCard = ({
}, {}), }, {}),
); );
let Placeholder = RiAlbumFill;
switch (controls.itemType) {
case LibraryItem.ALBUM:
Placeholder = RiAlbumFill;
break;
case LibraryItem.ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.ALBUM_ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.PLAYLIST:
Placeholder = RiPlayListFill;
break;
default:
Placeholder = RiAlbumFill;
break;
}
return ( return (
<DefaultCardContainer <DefaultCardContainer
key={`card-${columnIndex}-${listChildProps.index}`} key={`card-${columnIndex}-${listChildProps.index}`}
@ -127,10 +142,29 @@ export const DefaultCard = ({
> >
<InnerCardContainer> <InnerCardContainer>
<ImageContainer> <ImageContainer>
<Image {data?.imageUrl ? (
placeholder={data?.imagePlaceholderUrl || 'var(--placeholder-bg)'} <SimpleImg
src={data?.imageUrl} imgStyle={{ objectFit: 'cover' }}
/> importance="auto"
placeholder={data?.imagePlaceholderUrl || 'var(--placeholder-bg)'}
src={data?.imageUrl}
/>
) : (
<Center
sx={{
background: 'var(--placeholder-bg)',
borderRadius: 'var(--card-default-radius)',
height: '100%',
width: '100%',
}}
>
<Placeholder
color="var(--placeholder-fg)"
size={35}
/>
</Center>
)}
<GridCardControls <GridCardControls
handleFavorite={controls.handleFavorite} handleFavorite={controls.handleFavorite}
handlePlayQueueAdd={controls.handlePlayQueueAdd} handlePlayQueueAdd={controls.handlePlayQueueAdd}
@ -161,6 +195,18 @@ export const DefaultCard = ({
radius="sm" radius="sm"
/> />
</ImageContainer> </ImageContainer>
<DetailContainer>
<Stack spacing="sm">
{controls.cardRows.map((row) => (
<Skeleton
key={row.arrayProperty}
visible
height={14}
radius="sm"
/>
))}
</Stack>
</DetailContainer>
</InnerCardContainer> </InnerCardContainer>
</DefaultCardContainer> </DefaultCardContainer>
); );

View file

@ -1,5 +1,7 @@
import { Stack } from '@mantine/core'; import { Center, Stack } from '@mantine/core';
import { RiAlbumFill, RiPlayListFill, RiUserVoiceFill } from 'react-icons/ri';
import { generatePath, useNavigate } from 'react-router-dom'; import { generatePath, useNavigate } from 'react-router-dom';
import { SimpleImg } from 'react-simple-img';
import { ListChildComponentProps } from 'react-window'; import { ListChildComponentProps } from 'react-window';
import styled from 'styled-components'; import styled from 'styled-components';
import { Album, AlbumArtist, Artist, LibraryItem } from '/@/renderer/api/types'; import { Album, AlbumArtist, Artist, LibraryItem } from '/@/renderer/api/types';
@ -77,14 +79,6 @@ const ImageContainer = styled.div`
} }
`; `;
const Image = styled.img`
width: 100%;
max-width: 100%;
height: auto;
object-fit: cover;
border: 0;
`;
const DetailContainer = styled.div` const DetailContainer = styled.div`
margin-top: 0.5rem; margin-top: 0.5rem;
`; `;
@ -109,14 +103,52 @@ export const PosterCard = ({
}, {}), }, {}),
); );
let Placeholder = RiAlbumFill;
switch (controls.itemType) {
case LibraryItem.ALBUM:
Placeholder = RiAlbumFill;
break;
case LibraryItem.ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.ALBUM_ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.PLAYLIST:
Placeholder = RiPlayListFill;
break;
default:
Placeholder = RiAlbumFill;
break;
}
return ( return (
<PosterCardContainer key={`card-${columnIndex}-${listChildProps.index}`}> <PosterCardContainer key={`card-${columnIndex}-${listChildProps.index}`}>
<LinkContainer onClick={() => navigate(path)}> <LinkContainer onClick={() => navigate(path)}>
<ImageContainer> <ImageContainer>
<Image {data?.imageUrl ? (
placeholder={data?.imagePlaceholderUrl || 'var(--card-default-bg)'} <SimpleImg
src={data?.imageUrl} imgStyle={{ objectFit: 'cover' }}
/> importance="auto"
placeholder={data?.imagePlaceholderUrl || 'var(--card-default-bg)'}
src={data?.imageUrl}
/>
) : (
<Center
sx={{
background: 'var(--placeholder-bg)',
borderRadius: 'var(--card-default-radius)',
height: '100%',
width: '100%',
}}
>
<Placeholder
color="var(--placeholder-fg)"
size={35}
/>
</Center>
)}
<GridCardControls <GridCardControls
handleFavorite={controls.handleFavorite} handleFavorite={controls.handleFavorite}
handlePlayQueueAdd={controls.handlePlayQueueAdd} handlePlayQueueAdd={controls.handlePlayQueueAdd}