Feat/improve mobile display (#843)
* Ok 1 * Finished * Fix PR * Fix PR * Fix desktop * Fix * Fix absolute listen click outside * console.log * Fix according to code review --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,5 +1,3 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatePresence, LayoutGroup } from 'framer-motion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -11,10 +9,9 @@ import { CommandMenu } from '@/command-menu/components/CommandMenu';
|
||||
import { NavbarAnimatedContainer } from '@/ui/navbar/components/NavbarAnimatedContainer';
|
||||
import { MOBILE_VIEWPORT } from '@/ui/themes/themes';
|
||||
import { AppNavbar } from '~/AppNavbar';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
import { CompaniesMockMode } from '~/pages/companies/CompaniesMockMode';
|
||||
|
||||
import { AppPath } from '../../../types/AppPath';
|
||||
import { useAutoNavigateOnboarding } from '../hooks/useAutoNavigateOnboarding';
|
||||
import { isNavbarOpenedState } from '../states/isNavbarOpenedState';
|
||||
|
||||
const StyledLayout = styled.div`
|
||||
@ -46,72 +43,30 @@ type OwnProps = {
|
||||
};
|
||||
|
||||
export function DefaultLayout({ children }: OwnProps) {
|
||||
const navigate = useNavigate();
|
||||
const isMatchingLocation = useIsMatchingLocation();
|
||||
useAutoNavigateOnboarding();
|
||||
|
||||
const onboardingStatus = useOnboardingStatus();
|
||||
|
||||
useEffect(() => {
|
||||
const isMachinOngoingUserCreationRoute =
|
||||
isMatchingLocation(AppPath.SignUp) ||
|
||||
isMatchingLocation(AppPath.SignIn) ||
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
isMatchingLocation(AppPath.Verify);
|
||||
|
||||
const isMatchingOnboardingRoute =
|
||||
isMatchingLocation(AppPath.SignUp) ||
|
||||
isMatchingLocation(AppPath.SignIn) ||
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
isMatchingLocation(AppPath.Verify) ||
|
||||
isMatchingLocation(AppPath.CreateWorkspace) ||
|
||||
isMatchingLocation(AppPath.CreateProfile);
|
||||
|
||||
if (
|
||||
onboardingStatus === OnboardingStatus.OngoingUserCreation &&
|
||||
!isMachinOngoingUserCreationRoute
|
||||
) {
|
||||
navigate(AppPath.SignIn);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.OngoingWorkspaceCreation &&
|
||||
!isMatchingLocation(AppPath.CreateWorkspace)
|
||||
) {
|
||||
navigate(AppPath.CreateWorkspace);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.OngoingProfileCreation &&
|
||||
!isMatchingLocation(AppPath.CreateProfile)
|
||||
) {
|
||||
navigate(AppPath.CreateProfile);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.Completed &&
|
||||
isMatchingOnboardingRoute
|
||||
) {
|
||||
navigate('/');
|
||||
}
|
||||
}, [onboardingStatus, navigate, isMatchingLocation]);
|
||||
|
||||
return (
|
||||
<StyledLayout>
|
||||
<>
|
||||
<CommandMenu />
|
||||
<NavbarAnimatedContainer>
|
||||
<AppNavbar />
|
||||
</NavbarAnimatedContainer>
|
||||
<MainContainer>
|
||||
{onboardingStatus &&
|
||||
onboardingStatus !== OnboardingStatus.Completed ? (
|
||||
<>
|
||||
<CompaniesMockMode />
|
||||
<AnimatePresence mode="wait">
|
||||
<LayoutGroup>
|
||||
<AuthModal>{children}</AuthModal>
|
||||
</LayoutGroup>
|
||||
</AnimatePresence>
|
||||
</>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</MainContainer>
|
||||
</>
|
||||
<CommandMenu />
|
||||
<NavbarAnimatedContainer>
|
||||
<AppNavbar />
|
||||
</NavbarAnimatedContainer>
|
||||
<MainContainer>
|
||||
{onboardingStatus && onboardingStatus !== OnboardingStatus.Completed ? (
|
||||
<>
|
||||
<CompaniesMockMode />
|
||||
<AnimatePresence mode="wait">
|
||||
<LayoutGroup>
|
||||
<AuthModal>{children}</AuthModal>
|
||||
</LayoutGroup>
|
||||
</AnimatePresence>
|
||||
</>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</MainContainer>
|
||||
</StyledLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ type LeftContainerProps = {
|
||||
|
||||
const StyledLeftContainer = styled.div<LeftContainerProps>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
11
front/src/modules/ui/layout/components/ShowPageContainer.tsx
Normal file
11
front/src/modules/ui/layout/components/ShowPageContainer.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
|
||||
export const ShowPageContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: ${() => (useIsMobile() ? 'column' : 'row')};
|
||||
gap: ${({ theme }) => (useIsMobile() ? theme.spacing(3) : '0')};
|
||||
height: 100%;
|
||||
width: ${() => (useIsMobile() ? `calc(100% - 2px);` : '100%')};
|
||||
`;
|
||||
@ -12,7 +12,7 @@ const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export function NoTopBarContainer({ children }: OwnProps) {
|
||||
export function SubMenuTopBarContainer({ children }: OwnProps) {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<RightDrawerContainer topMargin={16}>{children}</RightDrawerContainer>
|
||||
@ -0,0 +1,52 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useIsMatchingLocation } from '../../../../hooks/useIsMatchingLocation';
|
||||
import { useOnboardingStatus } from '../../../auth/hooks/useOnboardingStatus';
|
||||
import { OnboardingStatus } from '../../../auth/utils/getOnboardingStatus';
|
||||
import { AppPath } from '../../../types/AppPath';
|
||||
|
||||
export function useAutoNavigateOnboarding() {
|
||||
const navigate = useNavigate();
|
||||
const isMatchingLocation = useIsMatchingLocation();
|
||||
|
||||
const onboardingStatus = useOnboardingStatus();
|
||||
|
||||
useEffect(() => {
|
||||
const isMachinOngoingUserCreationRoute =
|
||||
isMatchingLocation(AppPath.SignUp) ||
|
||||
isMatchingLocation(AppPath.SignIn) ||
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
isMatchingLocation(AppPath.Verify);
|
||||
|
||||
const isMatchingOnboardingRoute =
|
||||
isMatchingLocation(AppPath.SignUp) ||
|
||||
isMatchingLocation(AppPath.SignIn) ||
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
isMatchingLocation(AppPath.Verify) ||
|
||||
isMatchingLocation(AppPath.CreateWorkspace) ||
|
||||
isMatchingLocation(AppPath.CreateProfile);
|
||||
|
||||
if (
|
||||
onboardingStatus === OnboardingStatus.OngoingUserCreation &&
|
||||
!isMachinOngoingUserCreationRoute
|
||||
) {
|
||||
navigate(AppPath.SignIn);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.OngoingWorkspaceCreation &&
|
||||
!isMatchingLocation(AppPath.CreateWorkspace)
|
||||
) {
|
||||
navigate(AppPath.CreateWorkspace);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.OngoingProfileCreation &&
|
||||
!isMatchingLocation(AppPath.CreateProfile)
|
||||
) {
|
||||
navigate(AppPath.CreateProfile);
|
||||
} else if (
|
||||
onboardingStatus === OnboardingStatus.Completed &&
|
||||
isMatchingOnboardingRoute
|
||||
) {
|
||||
navigate('/');
|
||||
}
|
||||
}, [onboardingStatus, navigate, isMatchingLocation]);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
export function useIsSubNavbarDisplayed() {
|
||||
export function useIsSubMenuNavbarDisplayed() {
|
||||
const currentPath = useLocation().pathname;
|
||||
return currentPath.match(/\/settings\//g) !== null;
|
||||
}
|
||||
@ -1,13 +1,23 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
|
||||
export const ShowPageLeftContainer = styled.div`
|
||||
background: ${({ theme }) => theme.background.secondary};
|
||||
border-bottom-left-radius: 8px;
|
||||
border-right: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-right: 1px solid
|
||||
${({ theme }) => {
|
||||
const isMobile = useIsMobile();
|
||||
return !isMobile ? theme.border.color.medium : 0;
|
||||
}};
|
||||
border-top-left-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(3)};
|
||||
padding: 0px ${({ theme }) => theme.spacing(3)};
|
||||
width: 320px;
|
||||
width: ${({ theme }) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return isMobile ? `calc(100% - ${theme.spacing(6)})` : '320px';
|
||||
}};
|
||||
`;
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import { ReactNode, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { IconButton } from '@/ui/button/components/IconButton';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { IconChevronLeft, IconPlus } from '@/ui/icon/index';
|
||||
import NavCollapseButton from '@/ui/navbar/components/NavCollapseButton';
|
||||
|
||||
import { navbarIconSize } from '../../../navbar/constants';
|
||||
import { OverflowingTextWithTooltip } from '../../../tooltip/OverflowingTextWithTooltip';
|
||||
import { isNavbarOpenedState } from '../../states/isNavbarOpenedState';
|
||||
|
||||
export const TOP_BAR_MIN_HEIGHT = 40;
|
||||
|
||||
@ -20,6 +24,7 @@ const TopBarContainer = styled.div`
|
||||
justify-content: space-between;
|
||||
min-height: ${TOP_BAR_MIN_HEIGHT}px;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
padding-left: 0;
|
||||
padding-right: ${({ theme }) => theme.spacing(3)};
|
||||
`;
|
||||
|
||||
@ -37,10 +42,22 @@ const TitleContainer = styled.div`
|
||||
max-width: 50%;
|
||||
`;
|
||||
|
||||
const TopBarButtonContainer = styled.div`
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const BackIconButton = styled(IconButton)`
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledTopBarIconTitleContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
title: string;
|
||||
hasBackButton?: boolean;
|
||||
@ -57,21 +74,38 @@ export function TopBar({
|
||||
const navigate = useNavigate();
|
||||
const navigateBack = useCallback(() => navigate(-1), [navigate]);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const isNavbarOpened = useRecoilValue(isNavbarOpenedState);
|
||||
|
||||
const showNavCollapseButton = isMobile || !isNavbarOpened;
|
||||
|
||||
const iconSize = useIsMobile()
|
||||
? navbarIconSize.mobile
|
||||
: navbarIconSize.desktop;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TopBarContainer>
|
||||
<StyledLeftContainer>
|
||||
<NavCollapseButton hideIfOpen={true} />
|
||||
{hasBackButton && (
|
||||
<BackIconButton
|
||||
icon={<IconChevronLeft size={16} />}
|
||||
onClick={navigateBack}
|
||||
/>
|
||||
{showNavCollapseButton && (
|
||||
<TopBarButtonContainer>
|
||||
<NavCollapseButton direction="right" />
|
||||
</TopBarButtonContainer>
|
||||
)}
|
||||
{icon}
|
||||
<TitleContainer data-testid="top-bar-title">
|
||||
<OverflowingTextWithTooltip text={title} />
|
||||
</TitleContainer>
|
||||
{hasBackButton && (
|
||||
<TopBarButtonContainer>
|
||||
<BackIconButton
|
||||
icon={<IconChevronLeft size={iconSize} />}
|
||||
onClick={navigateBack}
|
||||
/>
|
||||
</TopBarButtonContainer>
|
||||
)}
|
||||
<StyledTopBarIconTitleContainer>
|
||||
{icon}
|
||||
<TitleContainer data-testid="top-bar-title">
|
||||
<OverflowingTextWithTooltip text={title} />
|
||||
</TitleContainer>
|
||||
</StyledTopBarIconTitleContainer>
|
||||
</StyledLeftContainer>
|
||||
{onAddButtonClick && (
|
||||
<IconButton
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import NavCollapseButton from '@/ui/navbar/components/NavCollapseButton';
|
||||
|
||||
const TitleAndCollapseContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
@ -22,7 +20,6 @@ type OwnProps = {
|
||||
export function TopTitle({ title }: OwnProps) {
|
||||
return (
|
||||
<TitleAndCollapseContainer>
|
||||
<NavCollapseButton hideIfOpen={true} hideOnDesktop={true} />
|
||||
<TitleContainer data-testid="top-bar-title">{title}</TitleContainer>
|
||||
</TitleAndCollapseContainer>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user