mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 13:17:46 +00:00
feat: updates
This commit is contained in:
parent
d4d8dd817b
commit
4c90db789b
14 changed files with 144 additions and 82 deletions
|
|
@ -38,19 +38,21 @@ const ArtistRow = ({
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
{title && (
|
{title && (
|
||||||
<h4 className='mb-6 text-12 font-medium uppercase dark:text-neutral-300 lg:text-14 lg:font-bold'>
|
<h4
|
||||||
|
className={cx(
|
||||||
|
'text-12 font-medium uppercase dark:text-neutral-300 lg:text-14',
|
||||||
|
'mx-2.5 mb-6 lg:mx-0 lg:font-bold'
|
||||||
|
)}
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
</h4>
|
</h4>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Artists */}
|
{/* Artists */}
|
||||||
{artists && (
|
{artists && (
|
||||||
<div className='no-scrollbar -ml-2.5 flex w-screen snap-x overflow-x-scroll lg:ml-auto lg:grid lg:w-auto lg:grid-cols-5 lg:gap-10'>
|
<div className='no-scrollbar flex snap-x overflow-x-scroll lg:grid lg:w-auto lg:grid-cols-5 lg:gap-10'>
|
||||||
{artists.map(artist => (
|
{artists.map(artist => (
|
||||||
<div
|
<div className='snap-start px-2.5 lg:px-0' key={artist.id}>
|
||||||
className='mr-5 snap-start first-of-type:ml-2.5 last-of-type:mr-2.5 lg:mr-0'
|
|
||||||
key={artist.id}
|
|
||||||
>
|
|
||||||
<Artist artist={artist} key={artist.id} />
|
<Artist artist={artist} key={artist.id} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -59,12 +61,9 @@ const ArtistRow = ({
|
||||||
|
|
||||||
{/* Placeholder */}
|
{/* Placeholder */}
|
||||||
{placeholderRow && !artists && (
|
{placeholderRow && !artists && (
|
||||||
<div className='no-scrollbar -ml-2.5 flex w-screen overflow-x-scroll lg:ml-auto lg:grid lg:w-auto lg:grid-cols-5 lg:gap-10'>
|
<div className='no-scrollbar flex snap-x overflow-x-scroll lg:grid lg:w-auto lg:grid-cols-5 lg:gap-10'>
|
||||||
{[...new Array(placeholderRow * 5).keys()].map(i => (
|
{[...new Array(placeholderRow * 5).keys()].map(i => (
|
||||||
<div
|
<div className='snap-start px-2.5 lg:px-0' key={i}>
|
||||||
className='mr-5 first-of-type:ml-2.5 last-of-type:mr-2.5 lg:mr-0'
|
|
||||||
key={i}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className='aspect-square w-full rounded-full bg-white dark:bg-neutral-800'
|
className='aspect-square w-full rounded-full bg-white dark:bg-neutral-800'
|
||||||
style={{
|
style={{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import useBreakpoint from '@/web/hooks/useBreakpoint'
|
import useBreakpoint from '@/web/hooks/useBreakpoint'
|
||||||
import { ReactQueryDevtools } from 'react-query/devtools'
|
import { ReactQueryDevtools } from 'react-query/devtools'
|
||||||
|
import useIsMobile from '@/web/hooks/useIsMobile'
|
||||||
|
|
||||||
const Devtool = () => {
|
const Devtool = () => {
|
||||||
const breakpoint = useBreakpoint()
|
const isMobile = useIsMobile()
|
||||||
const isMobile = ['sm', 'md'].includes(breakpoint)
|
|
||||||
return (
|
return (
|
||||||
<ReactQueryDevtools
|
<ReactQueryDevtools
|
||||||
initialIsOpen={false}
|
initialIsOpen={false}
|
||||||
|
|
@ -12,7 +12,7 @@ const Devtool = () => {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
bottom: isMobile ? 'auto' : 0,
|
bottom: isMobile ? 'auto' : 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
top: isMobile ? 0 : 1,
|
top: isMobile ? 0 : 'auto',
|
||||||
left: 'auto',
|
left: 'auto',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const LayoutMobile = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='layout' className='select-none bg-white pb-32 pt-3 dark:bg-black'>
|
<div id='layout' className='select-none bg-white pb-32 pt-3 dark:bg-black'>
|
||||||
<main className='min-h-screen overflow-y-auto overflow-x-hidden px-2.5 pb-16'>
|
<main className='min-h-screen overflow-y-auto overflow-x-hidden pb-16'>
|
||||||
<TopbarMobile />
|
<TopbarMobile />
|
||||||
<Router />
|
<Router />
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -47,6 +47,19 @@ const LayoutMobile = () => {
|
||||||
|
|
||||||
<MenuBar />
|
<MenuBar />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Notch background */}
|
||||||
|
{isIOS && isSafari && isPWA && (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
'fixed left-0 right-0 bg-black/30 backdrop-blur-sm',
|
||||||
|
css`
|
||||||
|
top: -50px;
|
||||||
|
height: 50px;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ const PlayLikedSongsCard = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'flex flex-col justify-between rounded-24 p-8 dark:bg-night-600',
|
'mx-2.5 flex flex-col justify-between rounded-24 p-8 dark:bg-white/10 lg:mx-0',
|
||||||
css`
|
css`
|
||||||
height: 322px;
|
height: 322px;
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ const Tabs = ({
|
||||||
tabs,
|
tabs,
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
className,
|
||||||
}: {
|
}: {
|
||||||
tabs: {
|
tabs: {
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -11,9 +12,10 @@ const Tabs = ({
|
||||||
}[]
|
}[]
|
||||||
value: string
|
value: string
|
||||||
onChange: (id: string) => void
|
onChange: (id: string) => void
|
||||||
|
className?: string
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className='no-scrollbar flex overflow-y-auto'>
|
<div className={cx('no-scrollbar flex overflow-y-auto', className)}>
|
||||||
{tabs.map(tab => (
|
{tabs.map(tab => (
|
||||||
<div
|
<div
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import SettingsButton from './SettingsButton'
|
||||||
|
|
||||||
const TopbarMobile = () => {
|
const TopbarMobile = () => {
|
||||||
return (
|
return (
|
||||||
<div className='mb-5 mt-7 flex'>
|
<div className='mb-5 mt-7 flex px-2.5'>
|
||||||
<div className='flex-grow'>
|
<div className='flex-grow'>
|
||||||
<SearchBox />
|
<SearchBox />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { player } from '@/web/store'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import Wave from './Wave'
|
import Wave from './Wave'
|
||||||
import Icon from '@/web/components/Icon'
|
import Icon from '@/web/components/Icon'
|
||||||
|
import useIsMobile from '@/web/hooks/useIsMobile'
|
||||||
|
|
||||||
const TrackList = ({
|
const TrackList = ({
|
||||||
tracks,
|
tracks,
|
||||||
|
|
@ -20,9 +21,14 @@ const TrackList = ({
|
||||||
() => playerSnapshot.track,
|
() => playerSnapshot.track,
|
||||||
[playerSnapshot.track]
|
[playerSnapshot.track]
|
||||||
)
|
)
|
||||||
|
const isMobile = useIsMobile()
|
||||||
|
|
||||||
const handleClick = (e: React.MouseEvent<HTMLElement>, trackID: number) => {
|
const handleClick = (e: React.MouseEvent<HTMLElement>, trackID: number) => {
|
||||||
if (e.detail === 2) onPlay?.(trackID)
|
if (isMobile) {
|
||||||
|
onPlay?.(trackID)
|
||||||
|
} else {
|
||||||
|
if (e.detail === 2) onPlay?.(trackID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const playing = useMemo(
|
const playing = useMemo(
|
||||||
|
|
@ -38,7 +44,12 @@ const TrackList = ({
|
||||||
onClick={e => handleClick(e, track.id)}
|
onClick={e => handleClick(e, track.id)}
|
||||||
className='group relative flex items-center py-2 text-16 font-medium text-neutral-200 transition duration-300 ease-in-out'
|
className='group relative flex items-center py-2 text-16 font-medium text-neutral-200 transition duration-300 ease-in-out'
|
||||||
>
|
>
|
||||||
<div className='mr-6'>{String(track.no).padStart(2, '0')}</div>
|
{/* Track no */}
|
||||||
|
<div className='mr-3 lg:mr-6'>
|
||||||
|
{String(track.no).padStart(2, '0')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Track name */}
|
||||||
<div className='flex flex-grow items-center'>
|
<div className='flex flex-grow items-center'>
|
||||||
{track.name}
|
{track.name}
|
||||||
{playingTrack?.id === track.id && (
|
{playingTrack?.id === track.id && (
|
||||||
|
|
@ -47,7 +58,9 @@ const TrackList = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='mr-12 flex opacity-0 transition-opacity group-hover:opacity-100'>
|
|
||||||
|
{/* Desktop context menu */}
|
||||||
|
<div className='mr-12 hidden opacity-0 transition-opacity group-hover:opacity-100 lg:flex'>
|
||||||
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-brand-600 text-white/80'>
|
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-brand-600 text-white/80'>
|
||||||
{/* <Icon name='play' className='h-7 w-7' /> */}
|
{/* <Icon name='play' className='h-7 w-7' /> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -58,7 +71,14 @@ const TrackList = ({
|
||||||
{/* <Icon name='play' className='h-7 w-7' /> */}
|
{/* <Icon name='play' className='h-7 w-7' /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='text-right'>
|
|
||||||
|
{/* Mobile menu */}
|
||||||
|
<div className='lg:hidden'>
|
||||||
|
<div className='h-10 w-10 rounded-full bg-night-900'></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Track duration */}
|
||||||
|
<div className='hidden text-right lg:block'>
|
||||||
{formatDuration(track.dt, 'en', 'hh:mm:ss')}
|
{formatDuration(track.dt, 'en', 'hh:mm:ss')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Icon from '@/web/components/Icon'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import Image from './Image'
|
import Image from './Image'
|
||||||
|
import useIsMobile from '@/web/hooks/useIsMobile'
|
||||||
|
|
||||||
const TrackListHeader = ({
|
const TrackListHeader = ({
|
||||||
album,
|
album,
|
||||||
|
|
@ -18,18 +19,22 @@ const TrackListHeader = ({
|
||||||
const duration = album?.songs?.reduce((acc, cur) => acc + cur.dt, 0) || 0
|
const duration = album?.songs?.reduce((acc, cur) => acc + cur.dt, 0) || 0
|
||||||
return formatDuration(duration, 'en', 'hh[hr] mm[min]')
|
return formatDuration(duration, 'en', 'hh[hr] mm[min]')
|
||||||
}, [album?.songs])
|
}, [album?.songs])
|
||||||
|
const isMobile = useIsMobile()
|
||||||
|
|
||||||
const cover = album?.picUrl || playlist?.coverImgUrl || ''
|
const cover = album?.picUrl || playlist?.coverImgUrl || ''
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'grid grid-rows-1 gap-10',
|
'mx-2.5 rounded-48 p-8 dark:bg-white/10',
|
||||||
css`
|
'lg:mx-0 lg:grid lg:grid-rows-1 lg:gap-10 lg:rounded-none lg:p-0 lg:dark:bg-transparent',
|
||||||
grid-template-columns: 318px auto;
|
!isMobile &&
|
||||||
`
|
css`
|
||||||
|
grid-template-columns: 318px auto;
|
||||||
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{/* Cover */}
|
||||||
<Image
|
<Image
|
||||||
className='z-10 aspect-square w-full rounded-24'
|
className='z-10 aspect-square w-full rounded-24'
|
||||||
src={resizeImage(cover, 'lg')}
|
src={resizeImage(cover, 'lg')}
|
||||||
|
|
@ -37,57 +42,77 @@ const TrackListHeader = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Blur bg */}
|
{/* Blur bg */}
|
||||||
<img
|
{!isMobile && (
|
||||||
className={cx(
|
<img
|
||||||
'absolute z-0 object-cover opacity-70',
|
className={cx(
|
||||||
css`
|
'absolute z-0 object-cover opacity-70',
|
||||||
top: -400px;
|
css`
|
||||||
left: -370px;
|
top: -400px;
|
||||||
width: 1572px;
|
left: -370px;
|
||||||
height: 528px;
|
width: 1572px;
|
||||||
filter: blur(256px) saturate(1.2);
|
height: 528px;
|
||||||
`
|
filter: blur(256px) saturate(1.2);
|
||||||
)}
|
`
|
||||||
src={resizeImage(cover, 'sm')}
|
)}
|
||||||
/>
|
src={resizeImage(cover, 'sm')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className='flex flex-col justify-between'>
|
<div className='flex flex-col justify-between'>
|
||||||
<div>
|
<div>
|
||||||
<div className='text-36 font-medium dark:text-neutral-100'>
|
{/* Name */}
|
||||||
|
<div className='mt-2.5 text-28 font-semibold dark:text-night-50 lg:mt-0 lg:text-36 lg:font-medium'>
|
||||||
{album?.name || playlist?.name}
|
{album?.name || playlist?.name}
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-6 text-24 font-medium dark:text-neutral-600'>
|
|
||||||
|
{/* Creator */}
|
||||||
|
<div className='mt-2.5 text-24 font-medium dark:text-night-400 lg:mt-6'>
|
||||||
{album?.artist.name || playlist?.creator.nickname}
|
{album?.artist.name || playlist?.creator.nickname}
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-1 flex items-center text-14 font-bold dark:text-neutral-600'>
|
|
||||||
|
{/* Extra info */}
|
||||||
|
<div className='mt-1 flex items-center text-12 font-medium dark:text-night-400 lg:text-14 lg:font-bold'>
|
||||||
|
{/* Album info */}
|
||||||
{!!album && (
|
{!!album && (
|
||||||
<>
|
<>
|
||||||
{album?.mark === 1056768 && (
|
{album?.mark === 1056768 && (
|
||||||
<Icon name='explicit' className='mb-px mr-1 h-3.5 w-3.5 ' />
|
<Icon
|
||||||
|
name='explicit'
|
||||||
|
className='mb-px mr-1 h-3 w-3 lg:h-3.5 lg:w-3.5 '
|
||||||
|
/>
|
||||||
)}{' '}
|
)}{' '}
|
||||||
{dayjs(album?.publishTime || 0).year()} · {album?.songs.length}{' '}
|
{dayjs(album?.publishTime || 0).year()} · {album?.songs.length}{' '}
|
||||||
Tracks, {albumDuration}
|
tracks, {albumDuration}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Playlist info */}
|
||||||
{!!playlist && (
|
{!!playlist && (
|
||||||
<>
|
<>
|
||||||
Updated at {formatDate(playlist?.updateTime || 0, 'en')} ·{' '}
|
Updated at {formatDate(playlist?.updateTime || 0, 'en')} ·{' '}
|
||||||
{playlist.trackCount} Tracks
|
{playlist.trackCount} tracks
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='line-clamp-3 mt-6 whitespace-pre-wrap text-14 font-bold dark:text-neutral-600'>
|
|
||||||
{album?.description || playlist?.description}
|
{/* Description */}
|
||||||
</div>
|
{!isMobile && (
|
||||||
|
<div className='line-clamp-3 mt-6 whitespace-pre-wrap text-14 font-bold dark:text-night-400 '>
|
||||||
|
{album?.description || playlist?.description}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='z-10 flex'>
|
{/* Actions */}
|
||||||
|
<div className='mt-11 flex items-end justify-between lg:z-10 lg:mt-4 lg:justify-start'>
|
||||||
|
<div className='flex items-end'>
|
||||||
|
<button className='mr-2.5 h-14 w-14 rounded-full dark:bg-white/10 lg:mr-6 lg:h-[72px] lg:w-[72px]'></button>
|
||||||
|
<button className='h-14 w-14 rounded-full dark:bg-white/10 lg:mr-6 lg:h-[72px] lg:w-[72px]'></button>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => onPlay()}
|
onClick={() => onPlay()}
|
||||||
className='h-[72px] w-[170px] rounded-full dark:bg-brand-700'
|
className='h-14 w-[125px] rounded-full dark:bg-brand-700 lg:h-[72px] lg:w-[170px]'
|
||||||
></button>
|
></button>
|
||||||
<button className='ml-6 h-[72px] w-[72px] rounded-full dark:bg-white/10'></button>
|
|
||||||
<button className='ml-6 h-[72px] w-[72px] rounded-full dark:bg-white/10'></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { createBreakpoint } from 'react-use'
|
import { createBreakpoint } from 'react-use'
|
||||||
|
|
||||||
const useBreakpoint = createBreakpoint({
|
const useBreakpoint = createBreakpoint({
|
||||||
sm: 767,
|
sm: 640,
|
||||||
md: 1023,
|
md: 768,
|
||||||
lg: 1279,
|
lg: 1024,
|
||||||
xl: 1535,
|
xl: 1280,
|
||||||
'2xl': 1536,
|
'2xl': 1536,
|
||||||
}) as () => 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
}) as () => 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/public/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/src/public/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' www.googletagmanager.com;" />
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' www.googletagmanager.com;" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<title>YesPlayMusic</title>
|
<title>YesPlayMusic</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ const MoreByArtist = ({ album }: { album?: Album }) => {
|
||||||
album =>
|
album =>
|
||||||
['专辑', 'EP/Single', 'EP'].includes(album.type) && album.size > 1
|
['专辑', 'EP/Single', 'EP'].includes(album.type) && album.size > 1
|
||||||
)
|
)
|
||||||
const singles = allReleases.filter(album => album.type === 'Single')
|
const singles = allReleases.filter(
|
||||||
|
album => album.type === 'Single' || album.size === 1
|
||||||
|
)
|
||||||
|
|
||||||
const qualifiedAlbums = [...filteredAlbums, ...singles]
|
const qualifiedAlbums = [...filteredAlbums, ...singles]
|
||||||
|
|
||||||
|
|
@ -63,17 +65,10 @@ const MoreByArtist = ({ album }: { album?: Album }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* Dividing line */}
|
{/* Dividing line */}
|
||||||
<div
|
<div className={cx('mx-2.5 my-7.5 h-px bg-white/10 lg:mx-0')}></div>
|
||||||
className={cx(
|
|
||||||
'h-px bg-white/20',
|
|
||||||
css`
|
|
||||||
margin: 30px 0;
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
></div>
|
|
||||||
|
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<div className='mb-5 text-14 font-bold text-neutral-300'>
|
<div className='mx-2.5 mb-5 text-14 font-bold text-neutral-300 lg:mx-0'>
|
||||||
MORE BY{' '}
|
MORE BY{' '}
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/artist/${album?.artist.id}`}
|
to={`/artist/${album?.artist.id}`}
|
||||||
|
|
@ -83,7 +78,7 @@ const MoreByArtist = ({ album }: { album?: Album }) => {
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CoverRow albums={filteredAlbums} />
|
<CoverRow albums={filteredAlbums} className='mx-2.5 lg:mx-0' />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +115,7 @@ const Album = () => {
|
||||||
<TrackListHeader album={album?.album} onPlay={onPlay} />
|
<TrackListHeader album={album?.album} onPlay={onPlay} />
|
||||||
<TrackList
|
<TrackList
|
||||||
tracks={tracks?.songs || album?.songs || album?.album.songs}
|
tracks={tracks?.songs || album?.songs || album?.album.songs}
|
||||||
className='z-10 mt-10'
|
className='z-10 mx-2.5 mt-3 lg:mx-0 lg:mt-10'
|
||||||
onPlay={onPlay}
|
onPlay={onPlay}
|
||||||
/>
|
/>
|
||||||
<MoreByArtist album={album?.album} />
|
<MoreByArtist album={album?.album} />
|
||||||
|
|
|
||||||
|
|
@ -78,13 +78,14 @@ const My = () => {
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
value={selectedTab}
|
value={selectedTab}
|
||||||
onChange={(id: string) => setSelectedTab(id)}
|
onChange={(id: string) => setSelectedTab(id)}
|
||||||
|
className='px-2.5 lg:px-0'
|
||||||
/>
|
/>
|
||||||
<CoverRow
|
<CoverRow
|
||||||
playlists={
|
playlists={
|
||||||
selectedTab === 'playlists' ? playlists?.playlist : undefined
|
selectedTab === 'playlists' ? playlists?.playlist : undefined
|
||||||
}
|
}
|
||||||
albums={selectedTab === 'albums' ? albums?.data : undefined}
|
albums={selectedTab === 'albums' ? albums?.data : undefined}
|
||||||
className='mt-6'
|
className='mt-6 px-2.5 lg:px-0'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -138,4 +138,5 @@ a {
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
|
min-height: calc(100% + env(safe-area-inset-top));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,7 @@ module.exports = {
|
||||||
900: '#7EB000',
|
900: '#7EB000',
|
||||||
},
|
},
|
||||||
day: {
|
day: {
|
||||||
100: '#FCFCFC',
|
50: '#B6B6B6',
|
||||||
200: '#F8F8F8',
|
|
||||||
300: '#F4F4F4',
|
|
||||||
400: '#F0F0F0',
|
|
||||||
500: '#EDEDED',
|
|
||||||
600: '#E9E9E9',
|
|
||||||
700: '#E5E5E5',
|
|
||||||
800: '#E2E2E2',
|
|
||||||
900: '#DEDEDE',
|
|
||||||
},
|
|
||||||
night: {
|
|
||||||
50: '#545454',
|
|
||||||
100: '#535353',
|
100: '#535353',
|
||||||
200: '#505050',
|
200: '#505050',
|
||||||
300: '#484848',
|
300: '#484848',
|
||||||
|
|
@ -48,6 +37,17 @@ module.exports = {
|
||||||
600: '#0E0E0E',
|
600: '#0E0E0E',
|
||||||
700: '#060606',
|
700: '#060606',
|
||||||
800: '#020202',
|
800: '#020202',
|
||||||
|
},
|
||||||
|
night: {
|
||||||
|
50: '#BFBFBF',
|
||||||
|
100: '#A8A8A8',
|
||||||
|
200: '#7B7B7B',
|
||||||
|
300: '#606060',
|
||||||
|
400: '#585858',
|
||||||
|
500: '#4A4A4A',
|
||||||
|
600: '#464646',
|
||||||
|
700: '#3F3F3F',
|
||||||
|
800: '#373737',
|
||||||
900: '#313131',
|
900: '#313131',
|
||||||
},
|
},
|
||||||
neutral: {
|
neutral: {
|
||||||
|
|
@ -82,10 +82,14 @@ module.exports = {
|
||||||
12: '12px',
|
12: '12px',
|
||||||
20: '20px',
|
20: '20px',
|
||||||
24: '24px',
|
24: '24px',
|
||||||
|
48: '48px',
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
mono: ['Roboto Mono', 'ui-monospace'],
|
mono: ['Roboto Mono', 'ui-monospace'],
|
||||||
},
|
},
|
||||||
|
margin: {
|
||||||
|
7.5: '1.875rem',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
variants: {},
|
variants: {},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue