diff --git a/ui/src/album/AlbumDetails.js b/ui/src/album/AlbumDetails.js index 36a6a2472..9cb8f6e16 100644 --- a/ui/src/album/AlbumDetails.js +++ b/ui/src/album/AlbumDetails.js @@ -22,65 +22,73 @@ import { } from '../common' import config from '../config' -const useStyles = makeStyles((theme) => ({ - root: { - [theme.breakpoints.down('xs')]: { - padding: '0.7em', - minWidth: '20em', +const useStyles = makeStyles( + (theme) => ({ + root: { + [theme.breakpoints.down('xs')]: { + padding: '0.7em', + minWidth: '20em', + }, + [theme.breakpoints.up('sm')]: { + padding: '1em', + minWidth: '32em', + }, }, - [theme.breakpoints.up('sm')]: { - padding: '1em', - minWidth: '32em', + cardContents: { + display: 'flex', }, - }, - cardContents: { - display: 'flex', - }, - details: { - display: 'flex', - flexDirection: 'column', - }, - content: { - flex: '2 0 auto', - }, - coverParent: { - [theme.breakpoints.down('xs')]: { - height: '8em', - width: '8em', - minWidth: '8em', + details: { + display: 'flex', + flexDirection: 'column', }, - [theme.breakpoints.up('sm')]: { - height: '10em', - width: '10em', - minWidth: '10em', + content: { + flex: '2 0 auto', }, - [theme.breakpoints.up('lg')]: { - height: '15em', - width: '15em', - minWidth: '15em', + coverParent: { + [theme.breakpoints.down('xs')]: { + height: '8em', + width: '8em', + minWidth: '8em', + }, + [theme.breakpoints.up('sm')]: { + height: '10em', + width: '10em', + minWidth: '10em', + }, + [theme.breakpoints.up('lg')]: { + height: '15em', + width: '15em', + minWidth: '15em', + }, }, - }, - cover: { - objectFit: 'contain', - cursor: 'pointer', - display: 'block', - width: '100%', - height: '100%', - }, - loveButton: { - top: theme.spacing(-0.2), - left: theme.spacing(0.5), - }, - commentBlock: { - display: 'inline-block', - marginTop: '1em', - float: 'left', - wordBreak: 'break-all', - }, - pointerCursor: { - cursor: 'pointer', - }, -})) + cover: { + objectFit: 'contain', + cursor: 'pointer', + display: 'block', + width: '100%', + height: '100%', + }, + loveButton: { + top: theme.spacing(-0.2), + left: theme.spacing(0.5), + }, + commentBlock: { + display: 'inline-block', + marginTop: '1em', + float: 'left', + wordBreak: 'break-all', + }, + pointerCursor: { + cursor: 'pointer', + }, + recordName: {}, + recordArtist: {}, + recordMeta: {}, + }), + { + name: 'NDAlbumDetails', + } +) const AlbumComment = ({ record }) => { const classes = useStyles() @@ -159,7 +167,7 @@ const AlbumDetails = ({ record }) => {
- + {record.name} {config.enableFavourites && ( { /> )} - + - {genreYear(record)} - + + {genreYear(record)} + + {record.songCount}{' '} {translate('resources.song.name', { smart_count: record.songCount, diff --git a/ui/src/album/AlbumGridView.js b/ui/src/album/AlbumGridView.js index cac54e106..b00216717 100644 --- a/ui/src/album/AlbumGridView.js +++ b/ui/src/album/AlbumGridView.js @@ -19,59 +19,64 @@ import { RangeField, } from '../common' -const useStyles = makeStyles((theme) => ({ - root: { - margin: '20px', - }, - tileBar: { - transition: 'all 150ms ease-out', - opacity: 0, - textAlign: 'left', - marginBottom: '3px', - background: - 'linear-gradient(to top, rgba(0,0,0,0.7) 0%,rgba(0,0,0,0.4) 70%,rgba(0,0,0,0) 100%)', - }, - tileBarMobile: { - textAlign: 'left', - marginBottom: '3px', - background: - 'linear-gradient(to top, rgba(0,0,0,0.7) 0%,rgba(0,0,0,0.4) 70%,rgba(0,0,0,0) 100%)', - }, - albumArtistName: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - textAlign: 'left', - fontSize: '1em', - }, - albumName: { - fontSize: '14px', - color: theme.palette.type === 'dark' ? '#eee' : 'black', - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }, - albumSubtitle: { - fontSize: '12px', - color: theme.palette.type === 'dark' ? '#c5c5c5' : '#696969', - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }, - link: { - position: 'relative', - display: 'block', - textDecoration: 'none', - '&:hover $tileBar': { - opacity: 1, +const useStyles = makeStyles( + (theme) => ({ + root: { + margin: '20px', }, - }, - albumLink: { - position: 'relative', - display: 'block', - textDecoration: 'none', - }, -})) + tileBar: { + transition: 'all 150ms ease-out', + opacity: 0, + textAlign: 'left', + marginBottom: '3px', + background: + 'linear-gradient(to top, rgba(0,0,0,0.7) 0%,rgba(0,0,0,0.4) 70%,rgba(0,0,0,0) 100%)', + }, + tileBarMobile: { + textAlign: 'left', + marginBottom: '3px', + background: + 'linear-gradient(to top, rgba(0,0,0,0.7) 0%,rgba(0,0,0,0.4) 70%,rgba(0,0,0,0) 100%)', + }, + albumArtistName: { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + textAlign: 'left', + fontSize: '1em', + }, + albumName: { + fontSize: '14px', + color: theme.palette.type === 'dark' ? '#eee' : 'black', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + }, + albumSubtitle: { + fontSize: '12px', + color: theme.palette.type === 'dark' ? '#c5c5c5' : '#696969', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + }, + link: { + position: 'relative', + display: 'block', + textDecoration: 'none', + '&:hover $tileBar': { + opacity: 1, + }, + }, + albumLink: { + position: 'relative', + display: 'block', + textDecoration: 'none', + }, + albumContainer: {}, + albumPlayButton: {}, + }), + { name: 'NDAlbumGridView' } +) const useCoverStyles = makeStyles({ cover: { @@ -112,7 +117,7 @@ const AlbumGridTile = ({ showArtist, record, basePath }) => { const classes = useStyles() return ( -
+
{ } + subtitle={ + + } actionIcon={} /> diff --git a/ui/src/album/AlbumShow.js b/ui/src/album/AlbumShow.js index 8cfd2729f..ee37d443f 100644 --- a/ui/src/album/AlbumShow.js +++ b/ui/src/album/AlbumShow.js @@ -5,13 +5,24 @@ import { useShowContext, useShowController, } from 'react-admin' +import { makeStyles } from '@material-ui/core/styles' import AlbumSongs from './AlbumSongs' import AlbumDetails from './AlbumDetails' import AlbumActions from './AlbumActions' +const useStyles = makeStyles( + (theme) => ({ + albumActions: {}, + }), + { + name: 'NDAlbumShow', + } +) + const AlbumShowLayout = (props) => { const { loading, ...context } = useShowContext(props) const { record } = context + const classes = useStyles() return ( <> @@ -29,7 +40,9 @@ const AlbumShowLayout = (props) => { } + actions={ + + } /> )} diff --git a/ui/src/audioplayer/Player.js b/ui/src/audioplayer/Player.js index e63a7e40d..8ff68c0a1 100644 --- a/ui/src/audioplayer/Player.js +++ b/ui/src/audioplayer/Player.js @@ -26,18 +26,21 @@ import { sendNotification, baseUrl } from '../utils' import { keyMap } from '../hotkeys' import useCurrentTheme from '../themes/useCurrentTheme' -const useStyle = makeStyles((theme) => ({ - audioTitle: { - textDecoration: 'none', - color: theme.palette.primary.dark, - '&.songTitle': { - fontWeight: 'bold', +const useStyle = makeStyles( + (theme) => ({ + audioTitle: { + textDecoration: 'none', + color: theme.palette.primary.dark, + '&.songTitle': { + fontWeight: 'bold', + }, }, - }, - player: { - display: (props) => (props.visible ? 'block' : 'none'), - }, -})) + player: { + display: (props) => (props.visible ? 'block' : 'none'), + }, + }), + { name: 'NDAudioPlayer' } +) let audioInstance = null diff --git a/ui/src/playlist/PlaylistDetails.js b/ui/src/playlist/PlaylistDetails.js index c64f5cdbf..6b5e629d5 100644 --- a/ui/src/playlist/PlaylistDetails.js +++ b/ui/src/playlist/PlaylistDetails.js @@ -4,36 +4,41 @@ import { makeStyles } from '@material-ui/core/styles' import { useTranslate } from 'react-admin' import { DurationField, SizeField } from '../common' -const useStyles = makeStyles((theme) => ({ - container: { - [theme.breakpoints.down('xs')]: { - padding: '0.7em', - minWidth: '24em', +const useStyles = makeStyles( + (theme) => ({ + container: { + [theme.breakpoints.down('xs')]: { + padding: '0.7em', + minWidth: '24em', + }, + [theme.breakpoints.up('sm')]: { + padding: '1em', + minWidth: '32em', + }, }, - [theme.breakpoints.up('sm')]: { - padding: '1em', - minWidth: '32em', + details: { + display: 'inline-block', + verticalAlign: 'top', + [theme.breakpoints.down('xs')]: { + width: '14em', + }, + [theme.breakpoints.up('sm')]: { + width: '26em', + }, + [theme.breakpoints.up('lg')]: { + width: '38em', + }, }, - }, - details: { - display: 'inline-block', - verticalAlign: 'top', - [theme.breakpoints.down('xs')]: { - width: '14em', + title: { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', }, - [theme.breakpoints.up('sm')]: { - width: '26em', - }, - [theme.breakpoints.up('lg')]: { - width: '38em', - }, - }, - title: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, -})) + }), + { + name: 'NDPlaylistDetails', + } +) const PlaylistDetails = (props) => { const { record = {} } = props diff --git a/ui/src/playlist/PlaylistShow.js b/ui/src/playlist/PlaylistShow.js index 676792934..cf52ebf55 100644 --- a/ui/src/playlist/PlaylistShow.js +++ b/ui/src/playlist/PlaylistShow.js @@ -5,14 +5,26 @@ import { useShowContext, useShowController, } from 'react-admin' +import { makeStyles } from '@material-ui/core/styles' import PlaylistDetails from './PlaylistDetails' import PlaylistSongs from './PlaylistSongs' import PlaylistActions from './PlaylistActions' import { Title, isReadOnly } from '../common' +const useStyles = makeStyles( + (theme) => ({ + playlistActions: {}, + }), + { + name: 'NDPlaylistShow', + } +) + const PlaylistShowLayout = (props) => { const { loading, ...context } = useShowContext(props) const { record } = context + const classes = useStyles() + return ( <> {record && } @@ -30,7 +42,12 @@ const PlaylistShowLayout = (props) => { {...props} readOnly={isReadOnly(record.owner)} title={} - actions={<PlaylistActions record={record} />} + actions={ + <PlaylistActions + className={classes.playlistActions} + record={record} + /> + } resource={'playlistTrack'} exporter={false} perPage={0} diff --git a/ui/src/themes/green.js b/ui/src/themes/green.js new file mode 100644 index 000000000..a0991c73f --- /dev/null +++ b/ui/src/themes/green.js @@ -0,0 +1,34 @@ +import green from '@material-ui/core/colors/green' + +export default { + themeName: 'Green', + palette: { + primary: { + light: green['300'], + main: green['500'], + }, + secondary: { + main: green['900'], + contrastText: '#fff', + }, + type: 'dark', + }, + overrides: { + MuiFormGroup: { + root: { + color: 'white', + }, + }, + NDLogin: { + systemNameLink: { + color: '#fff', + }, + welcome: { + color: '#eee', + }, + }, + }, + player: { + theme: 'dark', + }, +} diff --git a/ui/src/themes/index.js b/ui/src/themes/index.js index d8279eb22..3db54edb8 100644 --- a/ui/src/themes/index.js +++ b/ui/src/themes/index.js @@ -1,5 +1,6 @@ import LightTheme from './light' import DarkTheme from './dark' +import GreenTheme from './green' import SpotifyTheme from './spotify' -export default { LightTheme, DarkTheme, SpotifyTheme } +export default { LightTheme, DarkTheme, GreenTheme, SpotifyTheme } diff --git a/ui/src/themes/spotify.js b/ui/src/themes/spotify.js index e1837550e..84d92e332 100644 --- a/ui/src/themes/spotify.js +++ b/ui/src/themes/spotify.js @@ -1,30 +1,348 @@ -import green from '@material-ui/core/colors/green' +const spotifyGreen = { + 300: '#62ec83', + 500: '#1db954', + 900: '#008827', +} + +// For Album, Playlist +const musicListActions = { + padding: '1rem 0', + alignItems: 'center', + '@global': { + button: { + margin: 5, + border: '1px solid transparent', + backgroundColor: 'inherit', + color: '#b3b3b3', + '&:hover': { + border: '1px solid #b3b3b3', + backgroundColor: 'inherit !important', + }, + }, + 'button:first-child': { + '@media screen and (max-width: 720px)': { + transform: 'scale(1.5)', + margin: '1rem', + '&:hover': { + transform: 'scale(1.6) !important', + }, + }, + transform: 'scale(2)', + margin: '1.5rem', + minWidth: 0, + padding: 5, + transition: 'transform .3s ease', + background: spotifyGreen['500'], + color: '#fff', + borderRadius: 500, + border: 0, + '&:hover': { + transform: 'scale(2.1)', + backgroundColor: `${spotifyGreen['500']} !important`, + border: 0, + }, + }, + 'button:first-child>span:first-child': { + padding: 0, + }, + 'button:first-child>span:first-child>span': { + display: 'none', + }, + 'button>span:first-child>span, button:not(:first-child)>span:first-child>svg': { + color: '#b3b3b3', + }, + }, +} export default { themeName: 'Spotify-ish', + typography: { + fontFamily: "system-ui, 'Helvetica Neue', Helvetica, Arial", + h6: { + fontSize: '1rem', // AppBar title + }, + }, palette: { primary: { - light: green['300'], - main: green['500'], + light: spotifyGreen['300'], + main: spotifyGreen['500'], }, secondary: { - main: green['900'], + main: '#fff', contrastText: '#fff', }, + background: { + default: '#121212', + paper: 'inherit', + }, type: 'dark', }, overrides: { + MuiPopover: { + paper: { + backgroundColor: '#121212', + }, + }, + MuiDialog: { + paper: { + backgroundColor: '#121212', + }, + }, MuiFormGroup: { root: { - color: 'white', + color: spotifyGreen['500'], + }, + }, + MuiMenuItem: { + root: { + fontSize: '0.875rem', + }, + }, + MuiDivider: { + root: { + margin: '.75rem 0', + }, + }, + MuiIconButton: { + label: { + // color: '#fff' + }, + }, + MuiButton: { + root: { + background: spotifyGreen['500'], + color: '#fff', + // margin: '5px', + border: '1px solid transparent', + borderRadius: 500, + '&:hover': { + background: `${spotifyGreen['900']} !important`, + }, + }, + textSecondary: { + border: '1px solid #b3b3b3', + background: '#000', + '&:hover': { + border: '1px solid #fff !important', + background: '#000 !important', + }, + }, + label: { + color: '#fff', + paddingRight: '1rem', + paddingLeft: '0.7rem', + }, + }, + MuiDrawer: { + root: { + background: '#000', + paddingTop: '10px', + }, + }, + MuiTableRow: { + root: { + padding: '10px 0', + transition: 'background-color .3s ease', + '&:hover': { + backgroundColor: '#1d1d1d !important', + }, + '@global': { + 'td:nth-child(4)': { + color: '#fff !important', + }, + }, + }, + }, + MuiTableCell: { + root: { + borderBottom: '1px solid #1d1d1d', + padding: '10px !important', + color: '#b3b3b3 !important', + }, + head: { + borderBottom: '1px solid #282828', + fontSize: '0.75rem', + textTransform: 'uppercase', + letterSpacing: 1.2, + }, + }, + MuiAppBar: { + positionFixed: { + backgroundColor: '#000 !important', + boxShadow: 'none', + }, + }, + NDAlbumGridView: { + albumName: { + marginTop: '0.5rem', + fontWeight: 700, + textTransform: 'none', + color: '#fff', + }, + albumSubtitle: { + color: '#b3b3b3', + }, + albumContainer: { + backgroundColor: '#181818', + borderRadius: '.5rem', + padding: '.75rem', + transition: 'background-color .3s ease', + '&:hover': { + backgroundColor: '#282828', + }, + }, + albumPlayButton: { + backgroundColor: spotifyGreen['500'], + borderRadius: '50%', + boxShadow: '0 8px 8px rgb(0 0 0 / 30%)', + padding: '0.35rem', + transition: 'padding .3s ease', + '&:hover': { + background: `${spotifyGreen['500']} !important`, + padding: '0.45rem', + }, + }, + }, + NDPlaylistDetails: { + container: { + background: 'linear-gradient(#1d1d1d, transparent)', + borderRadius: 0, + paddingTop: '2.5rem !important', + boxShadow: 'none', + }, + title: { + fontSize: 'calc(1.5rem + 1.5vw);', + fontWeight: 700, + color: '#fff', + }, + details: { + fontSize: '.875rem', + color: 'rgba(255,255,255, 0.8)', + }, + }, + NDAlbumDetails: { + root: { + background: 'linear-gradient(#1d1d1d, transparent)', + borderRadius: 0, + boxShadow: 'none', + }, + cardContents: { + alignItems: 'center', + paddingTop: '1.5rem', + }, + recordName: { + fontSize: 'calc(1rem + 1.5vw);', + fontWeight: 700, + }, + recordArtist: { + fontSize: '.875rem', + fontWeight: 700, + }, + recordMeta: { + fontSize: '.875rem', + color: 'rgba(255,255,255, 0.8)', + }, + commentBlock: { + fontSize: '.875rem', + color: 'rgba(255,255,255, 0.8)', + }, + }, + NDAlbumShow: { + albumActions: musicListActions, + }, + NDPlaylistShow: { + playlistActions: musicListActions, + }, + NDAudioPlayer: { + audioTitle: { + color: '#fff', + fontSize: '0.875rem', + '&.songTitle': { + fontWeight: 400, + }, + '&.songInfo': { + fontSize: '0.675rem', + color: '#b3b3b3', + }, + }, + player: { + border: '10px solid blue', }, }, NDLogin: { + main: { + boxShadow: 'inset 0 0 0 2000px rgba(0, 0, 0, .8)', + }, systemNameLink: { color: '#fff', + textDecoration: 'none', }, - welcome: { - color: '#eee', + systemName: { + marginTop: '0.5em', + // borderBottom: '1px solid #282828', + marginBottom: '1em', + }, + icon: { + backgroundColor: 'inherit', + }, + card: { + // background: 'none', + background: 'none', + boxShadow: 'none', + padding: '10px 0', + minWidth: 360, + }, + avatar: { + marginBottom: 0, + }, + }, + RaLayout: { + content: { + padding: '0 !important', + background: 'linear-gradient(#171717, #121212)', + }, + }, + RaListToolbar: { + toolbar: { + padding: '0 .55rem !important', + }, + }, + RaSearchInput: { + input: { + // borderRadius: 500, + // width: '20rem', + paddingLeft: '.9rem', + border: 0, + // height: '2.5rem', + }, + }, + RaFilterButton: { + root: { + marginRight: '1rem', + }, + }, + RaPaginationActions: { + button: { + backgroundColor: 'inherit', + minWidth: 48, + margin: '0 4px', + border: '1px solid #282828', + '@global': { + '> .MuiButton-label': { + padding: 0, + }, + }, + }, + actions: { + '@global': { + '.next-page': { + marginLeft: 8, + marginRight: 8, + }, + '.previous-page': { + marginRight: 8, + }, + }, }, }, },