Adjust sidebar playlist styles
This commit is contained in:
parent
d54131b34a
commit
3981ad3eb5
2 changed files with 101 additions and 5 deletions
|
@ -1,8 +1,11 @@
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { createPolymorphicComponent, Flex, FlexProps } from '@mantine/core';
|
import { createPolymorphicComponent, Flex, FlexProps, Group } from '@mantine/core';
|
||||||
|
import { RiPlayFill } from 'react-icons/ri';
|
||||||
import type { LinkProps } from 'react-router-dom';
|
import type { LinkProps } from 'react-router-dom';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
|
import { Button } from '/@/renderer/components';
|
||||||
|
import { textEllipsis } from '/@/renderer/styles';
|
||||||
|
|
||||||
interface ListItemProps extends FlexProps {
|
interface ListItemProps extends FlexProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
@ -73,3 +76,78 @@ SidebarItem.defaultProps = {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
to: undefined,
|
to: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _PlaylistItemLink = styled(StyledItem)<LinkProps & { disabled?: boolean }>`
|
||||||
|
display: block;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0.3rem 0;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--sidebar-fg);
|
||||||
|
opacity: ${(props) => props.disabled && 0.6};
|
||||||
|
transition: color 0.2s ease-in-out;
|
||||||
|
pointer-events: ${(props) => props.disabled && 'none'};
|
||||||
|
${textEllipsis}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--sidebar-fg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
border: 1px solid var(--primary-color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PlaylistItemLink = createPolymorphicComponent<'a', ListItemProps>(_PlaylistItemLink);
|
||||||
|
|
||||||
|
export const PlaylistSidebarItem = ({
|
||||||
|
handlePlay,
|
||||||
|
to,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ListItemProps & { handlePlay: () => void }) => {
|
||||||
|
if (to) {
|
||||||
|
return (
|
||||||
|
<Group
|
||||||
|
noWrap
|
||||||
|
position="apart"
|
||||||
|
sx={{
|
||||||
|
'&:hover': {
|
||||||
|
button: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlaylistItemLink
|
||||||
|
component={Link}
|
||||||
|
to={to}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</PlaylistItemLink>
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
justify="flex-end"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
compact
|
||||||
|
sx={{ display: 'none' }}
|
||||||
|
variant="filled"
|
||||||
|
onClick={handlePlay}
|
||||||
|
>
|
||||||
|
<RiPlayFill />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledItem
|
||||||
|
tabIndex={0}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</StyledItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -29,12 +29,18 @@ import {
|
||||||
} from 'react-icons/ri';
|
} from 'react-icons/ri';
|
||||||
import { useNavigate, Link, useLocation, generatePath } from 'react-router-dom';
|
import { useNavigate, Link, useLocation, generatePath } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { SidebarItem } from '/@/renderer/features/sidebar/components/sidebar-item';
|
import {
|
||||||
|
PlaylistSidebarItem,
|
||||||
|
SidebarItem,
|
||||||
|
} from '/@/renderer/features/sidebar/components/sidebar-item';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { useSidebarStore, useAppStoreActions, useCurrentSong } from '/@/renderer/store';
|
import { useSidebarStore, useAppStoreActions, useCurrentSong } from '/@/renderer/store';
|
||||||
import { fadeIn } from '/@/renderer/styles';
|
import { fadeIn } from '/@/renderer/styles';
|
||||||
import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists';
|
import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists';
|
||||||
import { PlaylistListSort, SortOrder } from '/@/renderer/api/types';
|
import { PlaylistListSort, SortOrder } from '/@/renderer/api/types';
|
||||||
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
|
import { LibraryItem } from '/@/renderer/types';
|
||||||
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
|
|
||||||
const SidebarContainer = styled.div`
|
const SidebarContainer = styled.div`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -76,6 +82,18 @@ export const Sidebar = () => {
|
||||||
const { setSidebar } = useAppStoreActions();
|
const { setSidebar } = useAppStoreActions();
|
||||||
const imageUrl = useCurrentSong()?.imageUrl;
|
const imageUrl = useCurrentSong()?.imageUrl;
|
||||||
const showImage = sidebar.image;
|
const showImage = sidebar.image;
|
||||||
|
const handlePlayQueueAdd = usePlayQueueAdd();
|
||||||
|
const playButtonBehavior = usePlayButtonBehavior();
|
||||||
|
|
||||||
|
const handlePlayPlaylist = (id: string) => {
|
||||||
|
handlePlayQueueAdd?.({
|
||||||
|
byItemType: {
|
||||||
|
id: [id],
|
||||||
|
type: LibraryItem.PLAYLIST,
|
||||||
|
},
|
||||||
|
play: playButtonBehavior,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const playlistsQuery = usePlaylistList({
|
const playlistsQuery = usePlaylistList({
|
||||||
limit: 100,
|
limit: 100,
|
||||||
|
@ -290,13 +308,13 @@ export const Sidebar = () => {
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
{playlistsQuery?.data?.items?.map((playlist) => (
|
{playlistsQuery?.data?.items?.map((playlist) => (
|
||||||
<SidebarItem
|
<PlaylistSidebarItem
|
||||||
key={`sidebar-playlist-${playlist.id}`}
|
key={`sidebar-playlist-${playlist.id}`}
|
||||||
p={0}
|
handlePlay={() => handlePlayPlaylist(playlist.id)}
|
||||||
to={generatePath(AppRoute.PLAYLISTS_DETAIL, { playlistId: playlist.id })}
|
to={generatePath(AppRoute.PLAYLISTS_DETAIL, { playlistId: playlist.id })}
|
||||||
>
|
>
|
||||||
{playlist.name}
|
{playlist.name}
|
||||||
</SidebarItem>
|
</PlaylistSidebarItem>
|
||||||
))}
|
))}
|
||||||
</Accordion.Panel>
|
</Accordion.Panel>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
|
|
Reference in a new issue