Update look and feel

This commit is contained in:
jeffvli
2022-11-14 18:12:24 -08:00
parent 8dad9a8109
commit 8d5a05c329
27 changed files with 116 additions and 102 deletions
+13 -2
View File
@@ -45,7 +45,7 @@ export const App = () => {
outlineOffset: '-1px',
}),
},
fontFamily: 'Inter, sans-serif',
fontFamily: 'var(--content-font-family)',
fontSizes: {
lg: 16,
md: 14,
@@ -74,7 +74,18 @@ export const App = () => {
}}
transitionDuration={200}
>
<ModalsProvider modals={{ base: BaseContextModal }}>
<ModalsProvider
modalProps={{
centered: true,
exitTransitionDuration: 300,
overflow: 'inside',
overlayBlur: 5,
overlayOpacity: 0.9,
transition: 'slide-down',
transitionDuration: 300,
}}
modals={{ base: BaseContextModal }}
>
<SelectRouter>
<AppRouter />
</SelectRouter>
@@ -22,13 +22,13 @@ type MenuDropdownProps = MantineMenuDropdownProps;
const StyledMenu = styled(MantineMenu)<MenuProps>``;
const StyledMenuLabel = styled(MantineMenu.Label)<MenuLabelProps>`
font-family: var(--label-font-family);
font-family: var(--content-font-family);
`;
const StyledMenuItem = styled(MantineMenu.Item)<MenuItemProps>`
padding: 0.8rem;
font-size: 0.9em;
font-family: var(--label-font-family);
font-family: var(--content-font-family);
background-color: var(--dropdown-menu-bg);
&:disabled {
+1 -1
View File
@@ -13,7 +13,7 @@ const StyledPopover = styled(MantinePopover)``;
const StyledDropdown = styled(MantinePopover.Dropdown)<PopoverDropdownProps>`
padding: 0.5rem;
font-size: 0.9em;
font-family: var(--label-font-family);
font-family: var(--content-font-family);
background-color: var(--dropdown-menu-bg);
& .mantine-Menu-itemIcon {
@@ -12,7 +12,7 @@ const StyledSegmentedControl = styled(
)<MantineSegmentedControlProps>`
& .mantine-SegmentedControl-label {
color: var(--input-fg);
font-family: var(--label-font-family);
font-family: var(--content-font-family);
}
background-color: var(--input-bg);
+1 -1
View File
@@ -23,7 +23,7 @@ interface TextProps extends MantineTextDivProps {
const BaseText = styled(MantineText)<TextProps>`
color: ${(props) =>
props.$secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)'};
font-family: ${(props) => props.font};
font-family: ${(props) => props.font || 'var(--content-font-family)'};
cursor: ${(props) => (props.$link ? 'cursor' : 'default')};
user-select: ${(props) => (props.$noSelect ? 'none' : 'auto')};
${(props) => props.overflow === 'hidden' && textEllipsis}
@@ -8,7 +8,6 @@ import { ListChildComponentProps } from 'react-window';
import styled from 'styled-components';
import { Text } from '@/renderer/components/text';
import { GridCardControls } from '@/renderer/components/virtual-grid/grid-card/grid-card-controls';
import { fadeIn } from '@/renderer/styles';
import {
PlayQueueAddOptions,
LibraryItem,
@@ -90,12 +89,7 @@ const ImageSection = styled.div<{ size?: number }>`
`;
const Image = styled(SimpleImg)`
object-fit: cover;
border: 0;
border-radius: var(--card-default-radius);
${fadeIn}
animation: fadein 0.3s ease-in-out;
`;
const ControlsContainer = styled.div`
@@ -157,6 +151,8 @@ export const DefaultCard = ({
const { handlePlayQueueAdd, itemType, cardRows, route, playButtonBehavior } =
controls;
const cardSize = itemWidth - 24;
if (data) {
return (
<CardWrapper
@@ -184,10 +180,11 @@ export const DefaultCard = ({
{data?.imageUrl ? (
<Image
animationDuration={0.2}
height={itemWidth - 24}
height={cardSize}
imgStyle={{ objectFit: 'cover' }}
placeholder="var(--card-default-bg)"
src={data?.imageUrl}
width={itemWidth - 24}
width={cardSize}
/>
) : (
<Center
@@ -89,7 +89,6 @@ interface ImageProps {
}
const Image = styled(SimpleImg)<ImageProps>`
object-fit: cover;
border: 0;
border-radius: var(--card-poster-radius);
`;
@@ -177,6 +176,7 @@ export const PosterCard = ({
<Image
animationDuration={0.2}
height={itemWidth}
imgStyle={{ objectFit: 'cover' }}
placeholder="var(--card-default-bg)"
src={data?.imageUrl}
width={itemWidth}
@@ -122,7 +122,9 @@ export const LeftControls = () => {
>
<Button
compact
variant="subtle"
radius={0}
size="xs"
variant="default"
onClick={(e) => {
e.preventDefault();
setSidebar({ image: true });
@@ -152,7 +154,12 @@ export const LeftControls = () => {
{artists?.map((artist, index) => (
<React.Fragment key={`bar-${artist.id}`}>
{index > 0 && (
<Text $secondary style={{ display: 'inline-block' }}>
<Text
$link
$secondary
size="xs"
style={{ display: 'inline-block' }}
>
,
</Text>
)}{' '}
@@ -160,7 +167,7 @@ export const LeftControls = () => {
$link
component={Link}
overflow="hidden"
size="sm"
size="xs"
to={
artist.id
? generatePath(AppRoute.LIBRARY_ARTISTS_DETAIL, {
@@ -180,8 +187,7 @@ export const LeftControls = () => {
$link
component={Link}
overflow="hidden"
size="sm"
sx={{ '&:hover': { textDecoration: 'underline' } }}
size="xs"
to={
album?.id
? generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
@@ -80,7 +80,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
type="submit"
variant="filled"
>
Submit
Add
</Button>
</Group>
</Stack>
@@ -99,7 +99,7 @@ export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
Cancel
</Button>
<Button type="submit" variant="filled">
Update
Save
</Button>
</Group>
</Stack>
@@ -1,16 +1,10 @@
import { Group } from '@mantine/core';
import { openContextModal } from '@mantine/modals';
import { RiServerFill } from 'react-icons/ri';
import {
Text,
Button,
ContextModalVars,
Accordion,
} from '@/renderer/components';
import { RiAddFill, RiServerFill } from 'react-icons/ri';
import { Button, ContextModalVars, Accordion } from '@/renderer/components';
import { ServerListItem } from '@/renderer/features/servers/components/server-list-item';
import { useServerList } from '@/renderer/features/servers/queries/use-server-list';
import { usePermissions } from '@/renderer/features/shared';
import { Font } from '@/renderer/styles';
import { titleCase } from '@/renderer/utils';
import { AddServerForm } from './add-server-form';
@@ -20,17 +14,13 @@ export const ServerList = () => {
const handleAddServerModal = () => {
openContextModal({
centered: true,
exitTransitionDuration: 300,
innerProps: {
modalBody: (vars: ContextModalVars) => (
<AddServerForm onCancel={() => vars.context.closeModal(vars.id)} />
),
},
modal: 'base',
overflow: 'inside',
title: 'Add server',
transition: 'slide-down',
});
};
@@ -41,15 +31,17 @@ export const ServerList = () => {
position="right"
sx={{
position: 'absolute',
right: 45,
transform: 'translateY(-35px)',
right: 55,
transform: 'translateY(-4rem)',
}}
>
{permissions.isAdmin && (
<Button
autoFocus
compact
variant="default"
leftIcon={<RiAddFill size={15} />}
size="sm"
variant="filled"
onClick={handleAddServerModal}
>
Add server
@@ -61,9 +53,7 @@ export const ServerList = () => {
<Accordion.Item key={s.id} value={s.name}>
<Accordion.Control icon={<RiServerFill size={15} />}>
<Group position="apart">
<Text font={Font.GOTHAM}>
{titleCase(s.type)} - {s.name}
</Text>
{titleCase(s.type)} - {s.name}
</Group>
</Accordion.Control>
<Accordion.Panel>
@@ -12,7 +12,7 @@ const Container = styled.div``;
const Section = styled.div`
padding: 1rem;
border: 1px solid var(--generic-border-color);
border: 1px dashed var(--generic-border-color);
`;
export const ServerSection = ({ title, children }: ServerSectionProps) => {
@@ -112,7 +112,7 @@ export const GeneralTab = () => {
];
return (
<Stack mt="1rem" spacing="xl">
<Stack spacing="xl">
{options.map((option) => (
<SettingsOptions key={`general-${option.title}`} {...option} />
))}
@@ -343,7 +343,7 @@ export const PlaybackTab = () => {
];
return (
<Stack my={10} spacing="xl">
<Stack spacing="xl">
{playerOptions
.filter((o) => !o.isHidden)
.map((option) => (
@@ -1,4 +1,5 @@
import { Box } from '@mantine/core';
import { Variants, motion } from 'framer-motion';
import { Tabs } from '@/renderer/components';
import { GeneralTab } from '@/renderer/features/settings/components/general-tab';
import { PlaybackTab } from '@/renderer/features/settings/components/playback-tab';
@@ -7,10 +8,26 @@ import { useSettingsStore } from '@/renderer/store/settings.store';
export const Settings = () => {
const currentTab = useSettingsStore((state) => state.tab);
const update = useSettingsStore((state) => state.setSettings);
const tabVariants: Variants = {
in: {
opacity: 1,
transition: {
duration: 0.3,
},
x: 0,
},
out: {
opacity: 0,
x: 50,
},
};
return (
<Box pr={15} sx={{ height: '800px', maxHeight: '50vh' }}>
<Box m={5} sx={{ height: '800px', maxHeight: '50vh', overflowX: 'hidden' }}>
<Tabs
orientation="horizontal"
keepMounted={false}
orientation="vertical"
styles={{
tab: {
fontSize: '1.1rem',
@@ -18,8 +35,7 @@ export const Settings = () => {
},
}}
value={currentTab}
variant="default"
onChange={(e) => console.log(e)}
variant="pills"
onTabChange={(e) => e && update({ tab: e })}
>
<Tabs.List>
@@ -27,10 +43,14 @@ export const Settings = () => {
<Tabs.Tab value="playback">Playback</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="general">
<GeneralTab />
<motion.div animate="in" initial="out" variants={tabVariants}>
<GeneralTab />
</motion.div>
</Tabs.Panel>
<Tabs.Panel value="playback">
<PlaybackTab />
<motion.div animate="in" initial="out" variants={tabVariants}>
<PlaybackTab />
</motion.div>
</Tabs.Panel>
</Tabs>
</Box>
@@ -11,6 +11,7 @@ interface ListItemProps {
const StyledItem = styled.div`
display: flex;
width: 100%;
font-family: var(--content-font-family);
&:focus-visible {
border: 1px solid var(--primary-color);
@@ -22,6 +23,7 @@ const ItemStyle = css`
width: 100%;
padding: 0.5rem 1rem;
color: var(--sidebar-btn-color);
font-family: var(--content-font-family);
border: 1px transparent solid;
transition: color 0.2s ease-in-out;
@@ -205,7 +205,8 @@ export const Sidebar = () => {
>
<Button
compact
variant="subtle"
size="xs"
variant="default"
onClick={(e) => {
e.preventDefault();
setSidebar({ image: false });
@@ -73,7 +73,7 @@ export const ActivityMenu = () => {
{isTaskRunning ? (
<StyledActivitySvg color="var(--primary-color)" size={15} />
) : (
<FiActivity color="var(--titlebar-fg)" size={15} />
<FiActivity size={15} />
)}
</Button>
</Popover.Target>
@@ -51,18 +51,13 @@ export const AppMenu = () => {
const handleManageServersModal = () => {
openModal({
centered: true,
children: <ServerList />,
exitTransitionDuration: 300,
overflow: 'inside',
title: 'Manage Servers',
transition: 'slide-down',
});
};
const handleEditProfileModal = () => {
openModal({
centered: true,
children: (
<EditUserForm
repeatPassword
@@ -70,31 +65,21 @@ export const AppMenu = () => {
onCancel={closeAllModals}
/>
),
exitTransitionDuration: 300,
overflow: 'inside',
size: 'lg',
title: 'Edit Profile',
transition: 'slide-down',
});
};
const handleManageUsersModal = () => {
openModal({
centered: true,
children: <UserList />,
exitTransitionDuration: 300,
overflow: 'inside',
title: 'Manage Users',
transition: 'slide-down',
});
};
const handleSettingsModal = () => {
openModal({
centered: true,
children: <Settings />,
exitTransitionDuration: 300,
overflow: 'inside',
size: 'xl',
title: (
<Group position="center">
@@ -102,7 +87,6 @@ export const AppMenu = () => {
<Text>Settings</Text>
</Group>
),
transition: 'slide-down',
});
};
@@ -109,7 +109,7 @@ export const AddUserForm = ({ onCancel }: AddUserFormProps) => {
type="submit"
variant="filled"
>
Submit
Add
</Button>
</Group>
</Stack>
@@ -201,7 +201,7 @@ export const EditUserForm = ({
type="submit"
variant="filled"
>
Submit
Save
</Button>
</Group>
</Stack>
@@ -146,9 +146,7 @@ export const EditUserPermissionsForm = ({
<Accordion.Item key={`server-permission-${s.id}`} value={s.name}>
<Accordion.Control icon={<RiServerFill />}>
<Group>
<Text>
{s.name} ({titleCase(s.type)})
</Text>
{s.name} ({titleCase(s.type)})
</Group>
</Accordion.Control>
<Accordion.Panel>
@@ -2,6 +2,7 @@ import React from 'react';
import { Avatar, Group, Stack } from '@mantine/core';
import { openContextModal } from '@mantine/modals';
import {
RiAddFill,
RiAdminLine,
RiDeleteBin2Line,
RiEdit2Line,
@@ -29,24 +30,18 @@ export const UserList = () => {
const handleAddUserModal = () => {
openContextModal({
centered: true,
exitTransitionDuration: 300,
innerProps: {
modalBody: (vars: ContextModalVars) => (
<AddUserForm onCancel={() => vars.context.closeModal(vars.id)} />
),
},
modal: 'base',
overflow: 'inside',
title: 'Add User',
transition: 'slide-down',
});
};
const handleEditUserModal = (user: User) => {
openContextModal({
centered: true,
exitTransitionDuration: 300,
innerProps: {
modalBody: (vars: ContextModalVars) => (
<EditUserForm
@@ -56,10 +51,8 @@ export const UserList = () => {
),
},
modal: 'base',
overflow: 'inside',
size: 'lg',
title: `Edit User (${user.username})`,
transition: 'slide-down',
});
};
@@ -82,8 +75,6 @@ export const UserList = () => {
const handleEdituserPermissionsModal = (user: User) => {
openContextModal({
centered: true,
exitTransitionDuration: 300,
innerProps: {
modalBody: (vars: ContextModalVars) => (
<EditUserPermissionsForm
@@ -93,9 +84,7 @@ export const UserList = () => {
),
},
modal: 'base',
overflow: 'inside',
title: `Edit Permissions (${user.username})`,
transition: 'slide-down',
});
};
@@ -106,14 +95,16 @@ export const UserList = () => {
position="right"
sx={{
position: 'absolute',
right: 45,
transform: 'translateY(-35px)',
right: 55,
transform: 'translateY(-4rem)',
}}
>
<Button
autoFocus
compact
variant="default"
leftIcon={<RiAddFill size={15} />}
size="sm"
variant="filled"
onClick={handleAddUserModal}
>
Add user
+7 -4
View File
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { motion } from 'framer-motion';
import throttle from 'lodash/throttle';
import { Outlet } from 'react-router';
import styled from 'styled-components';
import { SideQueue } from '@/renderer/features/side-queue/components/side-queue';
@@ -152,14 +153,16 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
[isResizing, isResizingRight, setSidebar, sidebar.rightWidth]
);
const throttledResize = useMemo(() => throttle(resize, 50), [resize]);
useEffect(() => {
window.addEventListener('mousemove', resize);
window.addEventListener('mousemove', throttledResize);
window.addEventListener('mouseup', stopResizing);
return () => {
window.removeEventListener('mousemove', resize);
window.removeEventListener('mousemove', throttledResize);
window.removeEventListener('mouseup', stopResizing);
};
}, [resize, stopResizing]);
}, [throttledResize, stopResizing]);
return (
<>
+1
View File
@@ -19,6 +19,7 @@ html {
overflow-y: hidden;
color: var(--content-text-color);
background: var(--content-bg);
font-family: var(--content-font-family);
font-size: 12px;
}
+19 -9
View File
@@ -1,11 +1,12 @@
@use 'sass:color' as color;
:root {
--label-font-family: Poppins, sans-serif;
--content-font-family: Sora, sans-serif;
--header-font-family: Poppins, sans-serif;
--icon-color: rgb(255, 255, 255);
--primary-color: rgb(58, 129, 237);
--primary-color: rgb(52, 109, 219);
--secondary-color: rgb(255, 120, 120);
--success-color: green;
--warning-color: orange;
@@ -13,7 +14,7 @@
--generic-border-color: rgba(50, 50, 50, 0.7);
--main-bg: rgb(18, 18, 18);
--main-fg: rgb(240, 240, 240);
--main-fg: rgb(245, 245, 245);
--main-fg-secondary: rgb(150, 150, 150);
--titlebar-fg: rgb(255, 255, 255);
@@ -53,19 +54,19 @@
--scrollbar-thumb-bg: #5a5a5a;
--btn-primary-bg: var(--primary-color);
--btn-primary-bg-hover: rgb(47, 122, 237);
--btn-primary-bg-hover: rgb(41, 100, 216);
--btn-primary-fg: #ffffff;
--btn-primary-fg-hover: #ffffff;
--btn-default-bg: rgb(41, 41, 41);
--btn-default-bg-hover: rgb(51, 51, 51);
--btn-default-bg: rgb(39, 39, 39);
--btn-default-bg-hover: rgb(63, 63, 63);
--btn-default-fg: rgb(193, 193, 193);
--btn-default-fg-hover: rgb(193, 193, 193);
--btn-subtle-bg: transparent;
--btn-subtle-bg-hover: rgba(100, 100, 100, 0.5);
--btn-subtle-bg-hover: transparent;
--btn-subtle-fg: rgb(150, 150, 150);
--btn-subtle-fg-hover: rgb(200, 200, 200);
--btn-subtle-fg-hover: rgb(240, 240, 240);
--input-bg: rgb(56, 56, 56);
--input-fg: rgb(193, 193, 193);
@@ -74,7 +75,7 @@
--input-active-bg: rgba(255, 255, 255, 0.1);
--dropdown-menu-bg: rgb(24, 24, 24);
--dropdown-menu-fg: rgb(193, 194, 197);
--dropdown-menu-fg: rgb(220, 220, 220);
--dropdown-menu-bg-hover: rgb(37, 38, 43);
--dropdown-menu-border: 1px rgba(50, 50, 50, 0.7) solid;
--dropdown-menu-border-radius: 4px;
@@ -133,5 +134,14 @@
.mantine-Modal-modal {
background: var(--modal-bg);
border-radius: 10px;
}
.mantine-Modal-header {
font-weight: bold;
font-size: medium;
padding-bottom: 1rem;
margin-right: 0.5rem;
border-bottom: 1px solid var(--generic-border-color);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
body[data-theme='defaultLight'] {
--primary-color: rgb(117, 172, 255);
--primary-color: rgb(79, 149, 255);
--icon-color: #ffffff;
--main-bg: rgb(255, 255, 255);