Design fixes (#665)

This commit is contained in:
Charles Bochet
2023-07-14 18:43:16 -07:00
committed by GitHub
parent 0a319bcf86
commit b971464fe5
22 changed files with 464 additions and 138 deletions

View File

@ -7,7 +7,7 @@ import { AppNavbar } from '~/AppNavbar';
import { MOBILE_VIEWPORT } from '../themes/themes';
import { NavbarContainer } from './navbar/NavbarContainer';
import { NavbarAnimatedContainer } from './navbar/NavbarAnimatedContainer';
import { isNavbarOpenedState } from './states/isNavbarOpenedState';
const StyledLayout = styled.div`
@ -47,9 +47,9 @@ export function DefaultLayout({ children }: OwnProps) {
{userIsAuthenticated ? (
<>
<CommandMenu />
<NavbarContainer>
<NavbarAnimatedContainer>
<AppNavbar />
</NavbarContainer>
</NavbarAnimatedContainer>
<MainContainer>{children}</MainContainer>
</>
) : (

View File

@ -0,0 +1,6 @@
import { useLocation } from 'react-router-dom';
export function useIsSubNavbarDisplayed() {
const currentPath = useLocation().pathname;
return currentPath.match(/\/settings\//g) !== null;
}

View File

@ -0,0 +1,21 @@
import styled from '@emotion/styled';
import NavItemsContainer from './NavItemsContainer';
import NavWorkspaceButton from './NavWorkspaceButton';
type OwnProps = {
children: JSX.Element;
};
const StyledContainer = styled.div`
width: 220px;
`;
export default function MainNavbar({ children }: OwnProps) {
return (
<StyledContainer>
<NavWorkspaceButton />
<NavItemsContainer>{children}</NavItemsContainer>
</StyledContainer>
);
}

View File

@ -8,7 +8,6 @@ const StyledNavItemsContainer = styled.div`
display: flex;
flex-direction: column;
margin-top: 40px;
min-width: 220px;
`;
function NavItemsContainer({ children }: OwnProps) {

View File

@ -0,0 +1,57 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { useRecoilState, useRecoilValue } from 'recoil';
import { MOBILE_VIEWPORT } from '@/ui/themes/themes';
import { useIsSubNavbarDisplayed } from '../hooks/useIsSubNavbarDisplayed';
import { isNavbarOpenedState } from '../states/isNavbarOpenedState';
import { isNavbarSwitchingSizeState } from '../states/isNavbarSwitchingSizeState';
const StyledNavbarContainer = styled(motion.div)`
align-items: end;
display: flex;
flex-direction: column;
flex-shrink: 0;
overflow: hidden;
padding: ${({ theme }) => theme.spacing(2)};
@media (max-width: ${MOBILE_VIEWPORT}px) {
width: ${(props) =>
useRecoilValue(isNavbarOpenedState)
? `calc(100% - ` + props.theme.spacing(4) + `)`
: '0'};
}
`;
type NavbarProps = {
children: React.ReactNode;
layout?: string;
};
export function NavbarAnimatedContainer({ children, layout }: NavbarProps) {
const isMenuOpened = useRecoilValue(isNavbarOpenedState);
const [, setIsNavbarSwitchingSize] = useRecoilState(
isNavbarSwitchingSizeState,
);
const isSubNavbarDisplayed = useIsSubNavbarDisplayed();
const theme = useTheme();
return (
<StyledNavbarContainer
onAnimationComplete={() => {
setIsNavbarSwitchingSize(false);
}}
animate={{
width: isMenuOpened ? (isSubNavbarDisplayed ? '520px' : '220px') : '0',
opacity: isMenuOpened ? 1 : 0,
}}
transition={{
duration: theme.animation.duration.visible,
}}
>
{children}
</StyledNavbarContainer>
);
}

View File

@ -1,38 +0,0 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { MOBILE_VIEWPORT } from '@/ui/themes/themes';
import { isNavbarOpenedState } from '../states/isNavbarOpenedState';
const StyledNavbarContainer = styled.div`
flex-direction: column;
flex-shrink: 0;
overflow: hidden;
padding: ${({ theme }) => theme.spacing(2)};
width: ${(props) => (useRecoilValue(isNavbarOpenedState) ? 'auto' : '0')};
@media (max-width: ${MOBILE_VIEWPORT}px) {
width: ${(props) =>
useRecoilValue(isNavbarOpenedState)
? `calc(100% - ` + props.theme.spacing(4) + `)`
: '0'};
}
`;
const NavbarContent = styled.div`
display: ${() => (useRecoilValue(isNavbarOpenedState) ? 'block' : 'none')};
`;
type NavbarProps = {
children: React.ReactNode;
layout?: string;
};
export function NavbarContainer({ children, layout }: NavbarProps) {
return (
<StyledNavbarContainer>
<NavbarContent>{children}</NavbarContent>
</StyledNavbarContainer>
);
}

View File

@ -1,8 +1,10 @@
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { IconChevronLeft } from '@/ui/icons/index';
import { isNavbarSwitchingSizeState } from '../../states/isNavbarSwitchingSizeState';
import NavCollapseButton from '../NavCollapseButton';
type OwnProps = {
@ -32,12 +34,18 @@ const StyledContainer = styled.div`
export default function NavBackButton({ title }: OwnProps) {
const navigate = useNavigate();
const [, setIsNavbarSwitchingSize] = useRecoilState(
isNavbarSwitchingSizeState,
);
return (
<>
<StyledContainer>
<IconAndButtonContainer
onClick={() => navigate('/', { replace: true })}
onClick={() => {
setIsNavbarSwitchingSize(true);
navigate('/', { replace: true });
}}
>
<IconChevronLeft />
<span>{title}</span>

View File

@ -1,5 +1,7 @@
import styled from '@emotion/styled';
import NavItemsContainer from '../NavItemsContainer';
import NavBackButton from './NavBackButton';
type OwnProps = {
@ -10,23 +12,15 @@ type OwnProps = {
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
padding-left: 300px;
padding-top: ${({ theme }) => theme.spacing(6)};
width: 220px;
`;
const StyledNavItemsContainer = styled.div`
display: flex;
flex-direction: column;
`;
export default function SubNavbarContainer({
children,
backButtonTitle,
}: OwnProps) {
export default function SubNavbar({ children, backButtonTitle }: OwnProps) {
return (
<StyledContainer>
<NavBackButton title={backButtonTitle} />
<StyledNavItemsContainer>{children}</StyledNavItemsContainer>
<NavItemsContainer>{children}</NavItemsContainer>
</StyledContainer>
);
}

View File

@ -1,5 +1,7 @@
import { useRef } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { useRecoilState } from 'recoil';
import {
@ -13,16 +15,15 @@ import { rightDrawerPageState } from '../states/rightDrawerPageState';
import { RightDrawerRouter } from './RightDrawerRouter';
const StyledContainer = styled.div`
const StyledContainer = styled(motion.div)`
background: ${({ theme }) => theme.background.primary};
box-shadow: ${({ theme }) => theme.boxShadow.strong};
height: 100%;
overflow-x: hidden;
position: fixed;
right: 0;
top: 0;
transition: width 0.5s;
width: ${({ theme }) => theme.rightDrawerWidth};
z-index: 2;
`;
@ -45,17 +46,23 @@ export function RightDrawer() {
callback: () => setIsRightDrawerOpen(false),
mode: OutsideClickAlerterMode.absolute,
});
if (!isRightDrawerOpen || !isDefined(rightDrawerPage)) {
const theme = useTheme();
if (!isDefined(rightDrawerPage)) {
return <></>;
}
return (
<>
<StyledContainer>
<StyledRightDrawer ref={rightDrawerRef}>
<RightDrawerRouter />
</StyledRightDrawer>
</StyledContainer>
</>
<StyledContainer
animate={{
width: isRightDrawerOpen ? theme.rightDrawerWidth : '0',
}}
transition={{
duration: theme.animation.duration.visible,
}}
>
<StyledRightDrawer ref={rightDrawerRef}>
<RightDrawerRouter />
</StyledRightDrawer>
</StyledContainer>
);
}

View File

@ -0,0 +1,6 @@
import { atom } from 'recoil';
export const isNavbarSwitchingSizeState = atom({
key: 'ui/isNavbarSwitchingSizeState',
default: true,
});

View File

@ -1,6 +1,7 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
import { IconButton } from '@/ui/components/buttons/IconButton';
import { IconPlus } from '@/ui/icons/index';
import NavCollapseButton from '../navbar/NavCollapseButton';
@ -16,6 +17,7 @@ const TopBarContainer = styled.div`
font-size: 14px;
min-height: ${TOP_BAR_MIN_HEIGHT}px;
padding: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(3)};
`;
const TitleContainer = styled.div`
@ -26,22 +28,6 @@ const TitleContainer = styled.div`
width: 100%;
`;
const AddButtonContainer = styled.div`
align-items: center;
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${({ theme }) => theme.font.color.tertiary};
cursor: pointer;
display: flex;
flex-shrink: 0;
height: 28px;
justify-content: center;
justify-self: flex-end;
margin-right: ${({ theme }) => theme.spacing(1)};
user-select: none;
width: 28px;
`;
type OwnProps = {
title: string;
icon: ReactNode;
@ -56,12 +42,13 @@ export function TopBar({ title, icon, onAddButtonClick }: OwnProps) {
{icon}
<TitleContainer data-testid="top-bar-title">{title}</TitleContainer>
{onAddButtonClick && (
<AddButtonContainer
<IconButton
icon={<IconPlus size={16} />}
size="large"
data-testid="add-button"
onClick={onAddButtonClick}
>
<IconPlus size={16} />
</AddButtonContainer>
variant="border"
/>
)}
</TopBarContainer>
</>