From 21d5133564709c22f00abafe3fc5ce124958a434 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Sun, 23 Jul 2023 19:53:35 +0200 Subject: [PATCH] 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 --- front/package.json | 1 + front/src/AppNavbar.tsx | 82 ++++++------- .../components/CommentThreadComments.tsx | 6 +- .../CommentThreadRelationPicker.tsx | 4 +- .../right-drawer/components/CommentThread.tsx | 5 +- .../timeline/components/Timeline.tsx | 16 ++- .../components/CommandMenuStyles.tsx | 7 +- .../settings/components/SettingsNavbar.tsx | 114 +++++++++--------- .../BoardCardEditableFieldEditMode.tsx | 4 +- .../ui/board/components/BoardColumnMenu.tsx | 4 +- .../hooks/useRegisterCloseFieldHandlers.ts | 4 +- .../components/DropdownMenuContainer.tsx | 4 +- .../useListenClickOutsideArrayOfRef.test.tsx | 6 +- front/src/modules/ui/hooks/useIsMobile.ts | 7 ++ ...ArrayOfRef.ts => useListenClickOutside.ts} | 10 +- .../ui/layout/components/DefaultLayout.tsx | 85 +++---------- .../components/RightDrawerContainer.tsx | 1 + .../layout/components/ShowPageContainer.tsx | 11 ++ ...ntainer.tsx => SubMenuTopBarContainer.tsx} | 2 +- .../layout/hooks/useAutoNavigateOnboarding.ts | 52 ++++++++ ...ayed.ts => useIsSubMenuNavbarDisplayed.ts} | 2 +- .../components/ShowPageLeftContainer.tsx | 14 ++- .../ui/layout/top-bar/components/TopBar.tsx | 54 +++++++-- .../ui/layout/top-bar/components/TopTitle.tsx | 3 - .../ui/navbar/components/MainNavbar.tsx | 4 +- .../ui/navbar/components/NavBackButton.tsx | 3 - .../navbar/components/NavCollapseButton.tsx | 45 +++---- .../modules/ui/navbar/components/NavItem.tsx | 22 ++-- .../navbar/components/NavWorkspaceButton.tsx | 2 +- .../components/NavbarAnimatedContainer.tsx | 30 +++-- .../{SubNavbar.tsx => SubMenuNavbar.tsx} | 12 +- .../src/modules/ui/navbar/constants/index.ts | 14 +++ .../components/SingleEntitySelect.tsx | 4 +- .../right-drawer/components/RightDrawer.tsx | 18 ++- .../components/RightDrawerTopBar.tsx | 6 +- .../ui/table/components/EntityTable.tsx | 4 +- .../hooks/useRegisterCloseCellHandlers.ts | 4 +- front/src/modules/ui/themes/themes.ts | 1 - front/src/pages/companies/CompanyShow.tsx | 49 ++++---- front/src/pages/people/PersonShow.tsx | 5 +- .../src/pages/settings/SettingsExperience.tsx | 6 +- front/src/pages/settings/SettingsProfile.tsx | 6 +- .../src/pages/settings/SettingsWorkspace.tsx | 6 +- .../settings/SettingsWorkspaceMembers.tsx | 6 +- front/yarn.lock | 34 +++++- 45 files changed, 464 insertions(+), 315 deletions(-) create mode 100644 front/src/modules/ui/hooks/useIsMobile.ts rename front/src/modules/ui/hooks/{useListenClickOutsideArrayOfRef.ts => useListenClickOutside.ts} (86%) create mode 100644 front/src/modules/ui/layout/components/ShowPageContainer.tsx rename front/src/modules/ui/layout/components/{NoTopBarContainer.tsx => SubMenuTopBarContainer.tsx} (86%) create mode 100644 front/src/modules/ui/layout/hooks/useAutoNavigateOnboarding.ts rename front/src/modules/ui/layout/hooks/{useIsSubNavbarDisplayed.ts => useIsSubMenuNavbarDisplayed.ts} (75%) rename front/src/modules/ui/navbar/components/{SubNavbar.tsx => SubMenuNavbar.tsx} (55%) create mode 100644 front/src/modules/ui/navbar/constants/index.ts diff --git a/front/package.json b/front/package.json index 22f1f020c..2101ad308 100644 --- a/front/package.json +++ b/front/package.json @@ -37,6 +37,7 @@ "react-hotkeys-hook": "^4.4.0", "react-loading-skeleton": "^3.3.1", "react-modal": "^3.16.1", + "react-responsive": "^9.0.2", "react-router-dom": "^6.4.4", "react-textarea-autosize": "^8.4.1", "react-tooltip": "^5.13.1", diff --git a/front/src/AppNavbar.tsx b/front/src/AppNavbar.tsx index 0a0008e12..7e4167e73 100644 --- a/front/src/AppNavbar.tsx +++ b/front/src/AppNavbar.tsx @@ -11,7 +11,7 @@ import { IconTargetArrow, IconUser, } from '@/ui/icon/index'; -import { useIsSubNavbarDisplayed } from '@/ui/layout/hooks/useIsSubNavbarDisplayed'; +import { useIsSubMenuNavbarDisplayed } from '@/ui/layout/hooks/useIsSubMenuNavbarDisplayed'; import MainNavbar from '@/ui/navbar/components/MainNavbar'; import NavItem from '@/ui/navbar/components/NavItem'; import NavTitle from '@/ui/navbar/components/NavTitle'; @@ -21,51 +21,49 @@ export function AppNavbar() { const currentPath = useLocation().pathname; const { openCommandMenu } = useCommandMenu(); - const isSubNavbarDisplayed = useIsSubNavbarDisplayed(); + const isInSubMenu = useIsSubMenuNavbarDisplayed(); return ( <> - {!isSubNavbarDisplayed ? ( + {!isInSubMenu ? ( - <> - } - onClick={() => { - openCommandMenu(); - }} - /> - } - soon={true} - /> - } - /> - - } - active={currentPath === '/companies'} - /> - } - active={currentPath === '/people'} - /> - } - active={currentPath === '/opportunities'} - /> - + } + onClick={() => { + openCommandMenu(); + }} + /> + } + soon={true} + /> + } + /> + + } + active={currentPath === '/companies'} + /> + } + active={currentPath === '/people'} + /> + } + active={currentPath === '/opportunities'} + /> ) : ( diff --git a/front/src/modules/activities/components/CommentThreadComments.tsx b/front/src/modules/activities/components/CommentThreadComments.tsx index 245f46c92..fdc40f912 100644 --- a/front/src/modules/activities/components/CommentThreadComments.tsx +++ b/front/src/modules/activities/components/CommentThreadComments.tsx @@ -4,6 +4,7 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; import { currentUserState } from '@/auth/states/currentUserState'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; import { AutosizeTextInput } from '@/ui/input/components/AutosizeTextInput'; import { CommentThread, useCreateCommentMutation } from '~/generated/graphql'; import { isNonEmptyString } from '~/utils/isNonEmptyString'; @@ -38,7 +39,10 @@ const StyledCommentActionBar = styled.div` border-top: 1px solid ${({ theme }) => theme.border.color.light}; display: flex; padding: 16px 24px 16px 48px; - width: calc(${({ theme }) => theme.rightDrawerWidth} - 48px - 24px); + width: calc( + ${({ theme }) => (useIsMobile() ? '100%' : theme.rightDrawerWidth)} - 48px - + 24px + ); `; const StyledThreadCommentTitle = styled.div` diff --git a/front/src/modules/activities/components/CommentThreadRelationPicker.tsx b/front/src/modules/activities/components/CommentThreadRelationPicker.tsx index e7222c109..70d0dc653 100644 --- a/front/src/modules/activities/components/CommentThreadRelationPicker.tsx +++ b/front/src/modules/activities/components/CommentThreadRelationPicker.tsx @@ -12,7 +12,7 @@ import { CompanyChip } from '@/companies/components/CompanyChip'; import { useFilteredSearchCompanyQuery } from '@/companies/queries'; import { PersonChip } from '@/people/components/PersonChip'; import { useFilteredSearchPeopleQuery } from '@/people/queries'; -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { usePreviousHotkeyScope } from '@/ui/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys'; import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope'; @@ -194,7 +194,7 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) { placement: 'bottom-start', }); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [refs.floating, refs.domReference], callback: () => { exitEditMode(); diff --git a/front/src/modules/activities/right-drawer/components/CommentThread.tsx b/front/src/modules/activities/right-drawer/components/CommentThread.tsx index df2de9c4e..97da21200 100644 --- a/front/src/modules/activities/right-drawer/components/CommentThread.tsx +++ b/front/src/modules/activities/right-drawer/components/CommentThread.tsx @@ -9,6 +9,7 @@ import { CommentThreadTypeDropdown } from '@/activities/components/CommentThread import { GET_COMMENT_THREAD } from '@/activities/queries'; import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox'; import { PropertyBoxItem } from '@/ui/editable-field/property-box/components/PropertyBoxItem'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; import { IconArrowUpRight } from '@/ui/icon/index'; import { useGetCommentThreadQuery, @@ -43,7 +44,8 @@ const StyledTopContainer = styled.div` align-items: flex-start; align-self: stretch; background: ${({ theme }) => theme.background.secondary}; - border-bottom: 1px solid ${({ theme }) => theme.border.color.medium}; + border-bottom: ${({ theme }) => + useIsMobile() ? 'none' : `1px solid ${theme.border.color.medium}`}; display: flex; flex-direction: column; gap: 24px; @@ -187,7 +189,6 @@ export function CommentThread({ onChange={updateTitleFromBody} /> - {showComment && ( + useIsMobile() ? `1px solid ${theme.border.color.medium}` : 'none'}; display: flex; flex: 1 0 0; flex-direction: column; + justify-content: center; `; const StyledTimelineContainer = styled.div` align-items: center; align-self: stretch; + display: flex; flex: 1 0 0; flex-direction: column; gap: 4px; justify-content: flex-start; overflow-y: auto; + padding: 12px 16px 12px 16px; `; @@ -175,9 +181,13 @@ const StyledTooltip = styled(Tooltip)` const StyledTopActionBar = styled.div` align-items: flex-start; align-self: stretch; - backdrop-filter: blur(5px); - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - border-top-right-radius: 8px; + backdrop-filter: ${() => (useIsMobile() ? 'none' : `blur(5px)`)}; + + border-bottom: ${({ theme }) => + useIsMobile() ? 'none' : `1px solid ${theme.border.color.medium}`}; + + border-top-right-radius: ${() => (useIsMobile() ? 'none' : `8px`)}; + display: flex; flex-direction: column; left: 0px; diff --git a/front/src/modules/command-menu/components/CommandMenuStyles.tsx b/front/src/modules/command-menu/components/CommandMenuStyles.tsx index 44cb3a947..c3f138bd2 100644 --- a/front/src/modules/command-menu/components/CommandMenuStyles.tsx +++ b/front/src/modules/command-menu/components/CommandMenuStyles.tsx @@ -1,6 +1,8 @@ import styled from '@emotion/styled'; import { Command } from 'cmdk'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; + export const StyledDialog = styled(Command.Dialog)` background: ${({ theme }) => theme.background.primary}; border-radius: ${({ theme }) => theme.border.radius.md}; @@ -13,8 +15,9 @@ export const StyledDialog = styled(Command.Dialog)` padding: ${({ theme }) => theme.spacing(1)}; position: fixed; top: 30%; - transform: translateX(-50%); - width: 100%; + transform: ${() => + useIsMobile() ? 'translateX(-49.5%)' : 'translateX(-50%)'}; + width: ${() => (useIsMobile() ? 'calc(100% - 40px)' : '100%')}; z-index: 1000; `; diff --git a/front/src/modules/settings/components/SettingsNavbar.tsx b/front/src/modules/settings/components/SettingsNavbar.tsx index 91fbe6b8f..2b27d4649 100644 --- a/front/src/modules/settings/components/SettingsNavbar.tsx +++ b/front/src/modules/settings/components/SettingsNavbar.tsx @@ -12,7 +12,7 @@ import { } from '@/ui/icon/index'; import NavItem from '@/ui/navbar/components/NavItem'; import NavTitle from '@/ui/navbar/components/NavTitle'; -import SubNavbar from '@/ui/navbar/components/SubNavbar'; +import SubMenuNavbar from '@/ui/navbar/components/SubMenuNavbar'; export function SettingsNavbar() { const theme = useTheme(); @@ -24,62 +24,60 @@ export function SettingsNavbar() { }, [signOut]); return ( - - <> - - } - active={ - !!useMatch({ - path: useResolvedPath('/settings/profile').pathname, - end: true, - }) - } - /> - } - active={ - !!useMatch({ - path: useResolvedPath('/settings/profile/experience').pathname, - end: true, - }) - } - /> - - } - active={ - !!useMatch({ - path: useResolvedPath('/settings/workspace-members').pathname, - end: true, - }) - } - /> - } - active={ - !!useMatch({ - path: useResolvedPath('/settings/workspace').pathname, - end: true, - }) - } - /> - - } - danger={true} - /> - - + + + } + active={ + !!useMatch({ + path: useResolvedPath('/settings/profile').pathname, + end: true, + }) + } + /> + } + active={ + !!useMatch({ + path: useResolvedPath('/settings/profile/experience').pathname, + end: true, + }) + } + /> + + } + active={ + !!useMatch({ + path: useResolvedPath('/settings/workspace-members').pathname, + end: true, + }) + } + /> + } + active={ + !!useMatch({ + path: useResolvedPath('/settings/workspace').pathname, + end: true, + }) + } + /> + + } + danger={true} + /> + ); } diff --git a/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx b/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx index 8dffcb6a9..f8ab84dcd 100644 --- a/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx +++ b/front/src/modules/ui/board/card-field/components/BoardCardEditableFieldEditMode.tsx @@ -1,7 +1,7 @@ import { ReactElement, useRef } from 'react'; import styled from '@emotion/styled'; -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys'; import { overlayBackground } from '@/ui/themes/effects'; @@ -43,7 +43,7 @@ export function BoardCardEditableFieldEditMode({ }: OwnProps) { const wrapperRef = useRef(null); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [wrapperRef], callback: () => { onExit(); diff --git a/front/src/modules/ui/board/components/BoardColumnMenu.tsx b/front/src/modules/ui/board/components/BoardColumnMenu.tsx index a733b6a5f..8fb9a1a4e 100644 --- a/front/src/modules/ui/board/components/BoardColumnMenu.tsx +++ b/front/src/modules/ui/board/components/BoardColumnMenu.tsx @@ -7,7 +7,7 @@ import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSelectableItem } from '@/ui/dropdown/components/DropdownMenuSelectableItem'; import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton'; -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { BoardColumnEditTitleMenu } from './BoardColumnEditTitleMenu'; @@ -35,7 +35,7 @@ export function BoardColumnMenu({ const [openMenu, setOpenMenu] = useState('actions'); const boardColumnMenuRef = useRef(null); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [boardColumnMenuRef], callback: onClose, }); diff --git a/front/src/modules/ui/editable-field/hooks/useRegisterCloseFieldHandlers.ts b/front/src/modules/ui/editable-field/hooks/useRegisterCloseFieldHandlers.ts index 767cb8383..f6982ca04 100644 --- a/front/src/modules/ui/editable-field/hooks/useRegisterCloseFieldHandlers.ts +++ b/front/src/modules/ui/editable-field/hooks/useRegisterCloseFieldHandlers.ts @@ -1,4 +1,4 @@ -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys'; import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope'; @@ -12,7 +12,7 @@ export function useRegisterCloseFieldHandlers( ) { const { closeEditableField, isFieldInEditMode } = useEditableField(); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [wrapperRef], callback: () => { if (isFieldInEditMode) { diff --git a/front/src/modules/ui/filter-n-sort/components/DropdownMenuContainer.tsx b/front/src/modules/ui/filter-n-sort/components/DropdownMenuContainer.tsx index 1a5bbe0ac..2c67a55d8 100644 --- a/front/src/modules/ui/filter-n-sort/components/DropdownMenuContainer.tsx +++ b/front/src/modules/ui/filter-n-sort/components/DropdownMenuContainer.tsx @@ -2,7 +2,7 @@ import { useRef } from 'react'; import styled from '@emotion/styled'; import { DropdownMenu } from '../../dropdown/components/DropdownMenu'; -import { useListenClickOutsideArrayOfRef } from '../../hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '../../hooks/useListenClickOutside'; export const StyledDropdownMenuContainer = styled.ul` position: absolute; @@ -19,7 +19,7 @@ export function DropdownMenuContainer({ }) { const dropdownRef = useRef(null); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [dropdownRef], callback: () => { onClose?.(); diff --git a/front/src/modules/ui/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx b/front/src/modules/ui/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx index b289994c9..eb719bc63 100644 --- a/front/src/modules/ui/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx +++ b/front/src/modules/ui/hooks/__tests__/useListenClickOutsideArrayOfRef.test.tsx @@ -1,14 +1,14 @@ import { useRef } from 'react'; import { fireEvent, render } from '@testing-library/react'; -import { useListenClickOutsideArrayOfRef } from '../useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '../useListenClickOutside'; const onOutsideClick = jest.fn(); function TestComponentDomMode() { const buttonRef = useRef(null); const buttonRef2 = useRef(null); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [buttonRef, buttonRef2], callback: onOutsideClick, }); @@ -22,7 +22,7 @@ function TestComponentDomMode() { ); } -test('useListenClickOutsideArrayOfRef hook works in dom mode', async () => { +test('useListenClickOutside hook works in dom mode', async () => { const { getByText } = render(); const inside = getByText('Inside'); const inside2 = getByText('Inside 2'); diff --git a/front/src/modules/ui/hooks/useIsMobile.ts b/front/src/modules/ui/hooks/useIsMobile.ts new file mode 100644 index 000000000..db6128cc1 --- /dev/null +++ b/front/src/modules/ui/hooks/useIsMobile.ts @@ -0,0 +1,7 @@ +import { useMediaQuery } from 'react-responsive'; + +import { MOBILE_VIEWPORT } from '@/ui/themes/themes'; + +export function useIsMobile() { + return useMediaQuery({ query: `(max-width: ${MOBILE_VIEWPORT}px)` }); +} diff --git a/front/src/modules/ui/hooks/useListenClickOutsideArrayOfRef.ts b/front/src/modules/ui/hooks/useListenClickOutside.ts similarity index 86% rename from front/src/modules/ui/hooks/useListenClickOutsideArrayOfRef.ts rename to front/src/modules/ui/hooks/useListenClickOutside.ts index a3a601723..e6160059d 100644 --- a/front/src/modules/ui/hooks/useListenClickOutsideArrayOfRef.ts +++ b/front/src/modules/ui/hooks/useListenClickOutside.ts @@ -5,7 +5,7 @@ export enum ClickOutsideMode { dom = 'dom', } -export function useListenClickOutsideArrayOfRef({ +export function useListenClickOutside({ refs, callback, mode = ClickOutsideMode.dom, @@ -37,9 +37,13 @@ export function useListenClickOutsideArrayOfRef({ const { x, y, width, height } = ref.current.getBoundingClientRect(); const clientX = - 'clientX' in event ? event.clientX : event.touches[0].clientX; + 'clientX' in event + ? event.clientX + : event.changedTouches[0].clientX; const clientY = - 'clientY' in event ? event.clientY : event.touches[0].clientY; + 'clientY' in event + ? event.clientY + : event.changedTouches[0].clientY; if ( clientX < x || diff --git a/front/src/modules/ui/layout/components/DefaultLayout.tsx b/front/src/modules/ui/layout/components/DefaultLayout.tsx index 4536166aa..fc6b7c5ce 100644 --- a/front/src/modules/ui/layout/components/DefaultLayout.tsx +++ b/front/src/modules/ui/layout/components/DefaultLayout.tsx @@ -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 ( - <> - - - - - - {onboardingStatus && - onboardingStatus !== OnboardingStatus.Completed ? ( - <> - - - - {children} - - - - ) : ( - <>{children} - )} - - + + + + + + {onboardingStatus && onboardingStatus !== OnboardingStatus.Completed ? ( + <> + + + + {children} + + + + ) : ( + <>{children} + )} + ); } diff --git a/front/src/modules/ui/layout/components/RightDrawerContainer.tsx b/front/src/modules/ui/layout/components/RightDrawerContainer.tsx index cc9c5fc52..2a161b8fe 100644 --- a/front/src/modules/ui/layout/components/RightDrawerContainer.tsx +++ b/front/src/modules/ui/layout/components/RightDrawerContainer.tsx @@ -28,6 +28,7 @@ type LeftContainerProps = { const StyledLeftContainer = styled.div` display: flex; + flex-direction: column; position: relative; width: 100%; `; diff --git a/front/src/modules/ui/layout/components/ShowPageContainer.tsx b/front/src/modules/ui/layout/components/ShowPageContainer.tsx new file mode 100644 index 000000000..7128806d8 --- /dev/null +++ b/front/src/modules/ui/layout/components/ShowPageContainer.tsx @@ -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%')}; +`; diff --git a/front/src/modules/ui/layout/components/NoTopBarContainer.tsx b/front/src/modules/ui/layout/components/SubMenuTopBarContainer.tsx similarity index 86% rename from front/src/modules/ui/layout/components/NoTopBarContainer.tsx rename to front/src/modules/ui/layout/components/SubMenuTopBarContainer.tsx index cde2a9ae8..6056604a0 100644 --- a/front/src/modules/ui/layout/components/NoTopBarContainer.tsx +++ b/front/src/modules/ui/layout/components/SubMenuTopBarContainer.tsx @@ -12,7 +12,7 @@ const StyledContainer = styled.div` width: 100%; `; -export function NoTopBarContainer({ children }: OwnProps) { +export function SubMenuTopBarContainer({ children }: OwnProps) { return ( {children} diff --git a/front/src/modules/ui/layout/hooks/useAutoNavigateOnboarding.ts b/front/src/modules/ui/layout/hooks/useAutoNavigateOnboarding.ts new file mode 100644 index 000000000..ff92361e8 --- /dev/null +++ b/front/src/modules/ui/layout/hooks/useAutoNavigateOnboarding.ts @@ -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]); +} diff --git a/front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts b/front/src/modules/ui/layout/hooks/useIsSubMenuNavbarDisplayed.ts similarity index 75% rename from front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts rename to front/src/modules/ui/layout/hooks/useIsSubMenuNavbarDisplayed.ts index fbc9bff39..1696c292f 100644 --- a/front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts +++ b/front/src/modules/ui/layout/hooks/useIsSubMenuNavbarDisplayed.ts @@ -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; } diff --git a/front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx b/front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx index 4d4e73025..f1838ba81 100644 --- a/front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx +++ b/front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx @@ -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'; + }}; `; diff --git a/front/src/modules/ui/layout/top-bar/components/TopBar.tsx b/front/src/modules/ui/layout/top-bar/components/TopBar.tsx index a5b2ae82b..194b65c45 100644 --- a/front/src/modules/ui/layout/top-bar/components/TopBar.tsx +++ b/front/src/modules/ui/layout/top-bar/components/TopBar.tsx @@ -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 ( <> - - {hasBackButton && ( - } - onClick={navigateBack} - /> + {showNavCollapseButton && ( + + + )} - {icon} - - - + {hasBackButton && ( + + } + onClick={navigateBack} + /> + + )} + + {icon} + + + + {onAddButtonClick && ( - {title} ); diff --git a/front/src/modules/ui/navbar/components/MainNavbar.tsx b/front/src/modules/ui/navbar/components/MainNavbar.tsx index 660eb90a6..57b30a191 100644 --- a/front/src/modules/ui/navbar/components/MainNavbar.tsx +++ b/front/src/modules/ui/navbar/components/MainNavbar.tsx @@ -4,11 +4,11 @@ import NavItemsContainer from './NavItemsContainer'; import NavWorkspaceButton from './NavWorkspaceButton'; type OwnProps = { - children: JSX.Element; + children: React.ReactNode; }; const StyledContainer = styled.div` - width: ${({ theme }) => theme.leftNavBarWidth}; + width: 100%; `; export default function MainNavbar({ children }: OwnProps) { diff --git a/front/src/modules/ui/navbar/components/NavBackButton.tsx b/front/src/modules/ui/navbar/components/NavBackButton.tsx index da1504e4b..792b60f33 100644 --- a/front/src/modules/ui/navbar/components/NavBackButton.tsx +++ b/front/src/modules/ui/navbar/components/NavBackButton.tsx @@ -5,8 +5,6 @@ import { useRecoilState } from 'recoil'; import { IconChevronLeft } from '@/ui/icon/index'; import { isNavbarSwitchingSizeState } from '@/ui/layout/states/isNavbarSwitchingSizeState'; -import NavCollapseButton from './NavCollapseButton'; - type OwnProps = { title: string; }; @@ -50,7 +48,6 @@ export default function NavBackButton({ title }: OwnProps) { {title} - ); diff --git a/front/src/modules/ui/navbar/components/NavCollapseButton.tsx b/front/src/modules/ui/navbar/components/NavCollapseButton.tsx index 6753bcc1d..97fe718f5 100644 --- a/front/src/modules/ui/navbar/components/NavCollapseButton.tsx +++ b/front/src/modules/ui/navbar/components/NavCollapseButton.tsx @@ -1,14 +1,16 @@ import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; import { IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightCollapse, } from '@/ui/icon'; import { isNavbarOpenedState } from '@/ui/layout/states/isNavbarOpenedState'; -import { MOBILE_VIEWPORT } from '@/ui/themes/themes'; -const CollapseButton = styled.button<{ hideOnDesktop: boolean | undefined }>` +import { navbarIconSize } from '../constants'; + +const CollapseButton = styled.button` align-items: center; background: inherit; border: 0; @@ -25,46 +27,33 @@ const CollapseButton = styled.button<{ hideOnDesktop: boolean | undefined }>` justify-content: center; padding: 0; + user-select: none; - width: 32px; - - ${(props) => - props.hideOnDesktop && - `@media (min-width: ${MOBILE_VIEWPORT}px) { - display:none; - } - `} `; type CollapseButtonProps = { - hideIfOpen?: boolean; - hideIfClosed?: boolean; - hideOnDesktop?: boolean; + direction?: 'left' | 'right'; }; export default function NavCollapseButton({ - hideIfOpen, - hideOnDesktop, + direction = 'left', }: CollapseButtonProps) { const [isNavOpen, setIsNavOpen] = useRecoilState(isNavbarOpenedState); + const iconSize = useIsMobile() + ? navbarIconSize.mobile + : navbarIconSize.desktop; + return ( <> - {isNavOpen && !hideIfOpen && ( - setIsNavOpen(!isNavOpen)} - hideOnDesktop={hideOnDesktop} - > - + {direction === 'left' ? ( + setIsNavOpen(!isNavOpen)}> + - )} - {!isNavOpen && ( - setIsNavOpen(!isNavOpen)} - hideOnDesktop={hideOnDesktop} - > - + ) : ( + setIsNavOpen(!isNavOpen)}> + )} diff --git a/front/src/modules/ui/navbar/components/NavItem.tsx b/front/src/modules/ui/navbar/components/NavItem.tsx index f733e7756..857f8e447 100644 --- a/front/src/modules/ui/navbar/components/NavItem.tsx +++ b/front/src/modules/ui/navbar/components/NavItem.tsx @@ -1,9 +1,13 @@ import { ReactNode } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from '@emotion/styled'; +import { useRecoilState } from 'recoil'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; import { MOBILE_VIEWPORT } from '@/ui/themes/themes'; +import { isNavbarOpenedState } from '../../layout/states/isNavbarOpenedState'; + type OwnProps = { label: string; to?: string; @@ -79,21 +83,25 @@ const StyledSoonPill = styled.div` function NavItem({ label, icon, to, onClick, active, danger, soon }: OwnProps) { const navigate = useNavigate(); + const [, setIsNavbarOpened] = useRecoilState(isNavbarOpenedState); + + const isMobile = useIsMobile(); + + function handleItemClick() { + if (isMobile) { + setIsNavbarOpened(false); + } - const onItemClick = () => { if (onClick) { onClick(); - return; - } - if (to) { + } else if (to) { navigate(to); - return; } - }; + } return ( {currentWorkspace?.displayName ?? 'Twenty'} - + ); } diff --git a/front/src/modules/ui/navbar/components/NavbarAnimatedContainer.tsx b/front/src/modules/ui/navbar/components/NavbarAnimatedContainer.tsx index dfe22abe0..0d798e972 100644 --- a/front/src/modules/ui/navbar/components/NavbarAnimatedContainer.tsx +++ b/front/src/modules/ui/navbar/components/NavbarAnimatedContainer.tsx @@ -3,10 +3,12 @@ import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { useRecoilState, useRecoilValue } from 'recoil'; -import { useIsSubNavbarDisplayed } from '@/ui/layout/hooks/useIsSubNavbarDisplayed'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; +import { useIsSubMenuNavbarDisplayed } from '@/ui/layout/hooks/useIsSubMenuNavbarDisplayed'; import { isNavbarOpenedState } from '@/ui/layout/states/isNavbarOpenedState'; import { isNavbarSwitchingSizeState } from '@/ui/layout/states/isNavbarSwitchingSizeState'; -import { MOBILE_VIEWPORT } from '@/ui/themes/themes'; + +import { leftNavbarWidth, leftSubMenuNavbarWidth } from '../constants'; const StyledNavbarContainer = styled(motion.div)` align-items: end; @@ -15,35 +17,37 @@ const StyledNavbarContainer = styled(motion.div)` 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) { +export function NavbarAnimatedContainer({ children }: NavbarProps) { const isMenuOpened = useRecoilValue(isNavbarOpenedState); const [, setIsNavbarSwitchingSize] = useRecoilState( isNavbarSwitchingSizeState, ); - const isSubNavbarDisplayed = useIsSubNavbarDisplayed(); + const isInSubMenu = useIsSubMenuNavbarDisplayed(); const theme = useTheme(); + const isMobile = useIsMobile(); + + const leftBarWidth = isInSubMenu + ? isMobile + ? leftSubMenuNavbarWidth.mobile + : leftSubMenuNavbarWidth.desktop + : isMobile + ? leftNavbarWidth.mobile + : leftNavbarWidth.desktop; + return ( { setIsNavbarSwitchingSize(false); }} animate={{ - width: isMenuOpened ? (isSubNavbarDisplayed ? '520px' : '220px') : '0', + width: isMenuOpened ? leftBarWidth : '0', opacity: isMenuOpened ? 1 : 0, }} transition={{ diff --git a/front/src/modules/ui/navbar/components/SubNavbar.tsx b/front/src/modules/ui/navbar/components/SubMenuNavbar.tsx similarity index 55% rename from front/src/modules/ui/navbar/components/SubNavbar.tsx rename to front/src/modules/ui/navbar/components/SubMenuNavbar.tsx index 9cdc05398..2e2b14e1c 100644 --- a/front/src/modules/ui/navbar/components/SubNavbar.tsx +++ b/front/src/modules/ui/navbar/components/SubMenuNavbar.tsx @@ -1,21 +1,25 @@ import styled from '@emotion/styled'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; + +import { leftNavbarWidth } from '../constants'; + import NavBackButton from './NavBackButton'; import NavItemsContainer from './NavItemsContainer'; type OwnProps = { - children: JSX.Element; + children: React.ReactNode; backButtonTitle: string; }; const StyledContainer = styled.div` display: flex; flex-direction: column; - padding-top: ${({ theme }) => theme.spacing(6)}; - width: 220px; + padding-top: ${({ theme }) => theme.spacing(2)}; + width: ${({ theme }) => (useIsMobile() ? '100%' : leftNavbarWidth.desktop)}; `; -export default function SubNavbar({ children, backButtonTitle }: OwnProps) { +export default function SubMenuNavbar({ children, backButtonTitle }: OwnProps) { return ( diff --git a/front/src/modules/ui/navbar/constants/index.ts b/front/src/modules/ui/navbar/constants/index.ts new file mode 100644 index 000000000..415925d63 --- /dev/null +++ b/front/src/modules/ui/navbar/constants/index.ts @@ -0,0 +1,14 @@ +export const leftNavbarWidth = { + mobile: 'calc(100% - 16px)', + desktop: '220px', +}; + +export const leftSubMenuNavbarWidth = { + mobile: 'calc(100% - 16px)', + desktop: '520px', +}; + +export const navbarIconSize = { + mobile: 18, + desktop: 16, +}; diff --git a/front/src/modules/ui/relation-picker/components/SingleEntitySelect.tsx b/front/src/modules/ui/relation-picker/components/SingleEntitySelect.tsx index 33d41c9ec..3cb5ee184 100644 --- a/front/src/modules/ui/relation-picker/components/SingleEntitySelect.tsx +++ b/front/src/modules/ui/relation-picker/components/SingleEntitySelect.tsx @@ -6,7 +6,7 @@ import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem'; import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch'; import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator'; -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { IconPlus } from '@/ui/icon'; import { isDefined } from '~/utils/isDefined'; @@ -46,7 +46,7 @@ export function SingleEntitySelect< const showCreateButton = isDefined(onCreate) && searchFilter !== ''; - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [containerRef], callback: () => { onCancel?.(); diff --git a/front/src/modules/ui/right-drawer/components/RightDrawer.tsx b/front/src/modules/ui/right-drawer/components/RightDrawer.tsx index 5ac4394c4..d9e4c82c4 100644 --- a/front/src/modules/ui/right-drawer/components/RightDrawer.tsx +++ b/front/src/modules/ui/right-drawer/components/RightDrawer.tsx @@ -5,13 +5,15 @@ import { motion } from 'framer-motion'; import { useRecoilState } from 'recoil'; import { Key } from 'ts-key-enum'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; import { ClickOutsideMode, - useListenClickOutsideArrayOfRef, -} from '@/ui/hooks/useListenClickOutsideArrayOfRef'; + useListenClickOutside, +} from '@/ui/hooks/useListenClickOutside'; import { isDefined } from '~/utils/isDefined'; import { useScopedHotkeys } from '../../hotkey/hooks/useScopedHotkeys'; +import { leftNavbarWidth } from '../../navbar/constants'; import { useRightDrawer } from '../hooks/useRightDrawer'; import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState'; import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState'; @@ -51,7 +53,7 @@ export function RightDrawer() { const rightDrawerRef = useRef(null); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [rightDrawerRef], callback: () => closeRightDrawer(), mode: ClickOutsideMode.absolute, @@ -66,16 +68,22 @@ export function RightDrawer() { [setIsRightDrawerOpen], ); + const isMobile = useIsMobile(); + const rightDrawerWidthExpanded = `calc(100% - ${ - theme.leftNavBarWidth + leftNavbarWidth.desktop } - ${theme.spacing(2)})`; const rightDrawerWidth = isRightDrawerOpen - ? isRightDrawerExpanded + ? isMobile + ? '100%' + : isRightDrawerExpanded ? rightDrawerWidthExpanded : theme.rightDrawerWidth : '0'; + console.log(rightDrawerWidth); + if (!isDefined(rightDrawerPage)) { return <>; } diff --git a/front/src/modules/ui/right-drawer/components/RightDrawerTopBar.tsx b/front/src/modules/ui/right-drawer/components/RightDrawerTopBar.tsx index 82f2b102e..9b192ea7b 100644 --- a/front/src/modules/ui/right-drawer/components/RightDrawerTopBar.tsx +++ b/front/src/modules/ui/right-drawer/components/RightDrawerTopBar.tsx @@ -1,5 +1,7 @@ import styled from '@emotion/styled'; +import { useIsMobile } from '@/ui/hooks/useIsMobile'; + import { RightDrawerTopBarCloseButton } from './RightDrawerTopBarCloseButton'; import { RightDrawerTopBarExpandButton } from './RightDrawerTopBarExpandButton'; @@ -20,10 +22,12 @@ const StyledRightDrawerTopBar = styled.div` `; export function RightDrawerTopBar() { + const isMobile = useIsMobile(); + return ( - + {!isMobile && } ); } diff --git a/front/src/modules/ui/table/components/EntityTable.tsx b/front/src/modules/ui/table/components/EntityTable.tsx index 33097fa25..57b65d202 100644 --- a/front/src/modules/ui/table/components/EntityTable.tsx +++ b/front/src/modules/ui/table/components/EntityTable.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { TableColumn } from '@/people/table/components/peopleColumns'; import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface'; -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus'; import { TableHeader } from '../table-header/components/TableHeader'; @@ -90,7 +90,7 @@ export function EntityTable({ const leaveTableFocus = useLeaveTableFocus(); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [tableBodyRef], callback: () => { leaveTableFocus(); diff --git a/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts b/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts index a85f5ecc5..9d509b3da 100644 --- a/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts +++ b/front/src/modules/ui/table/editable-cell/hooks/useRegisterCloseCellHandlers.ts @@ -1,4 +1,4 @@ -import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef'; +import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside'; import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys'; import { useMoveSoftFocus } from '../../hooks/useMoveSoftFocus'; @@ -14,7 +14,7 @@ export function useRegisterCloseCellHandlers( ) { const { closeEditableCell } = useEditableCell(); const { isCurrentCellInEditMode } = useCurrentCellEditMode(); - useListenClickOutsideArrayOfRef({ + useListenClickOutside({ refs: [wrapperRef], callback: (event) => { if (isCurrentCellInEditMode) { diff --git a/front/src/modules/ui/themes/themes.ts b/front/src/modules/ui/themes/themes.ts index d52ddd08d..8c5ed9e08 100644 --- a/front/src/modules/ui/themes/themes.ts +++ b/front/src/modules/ui/themes/themes.ts @@ -37,7 +37,6 @@ const common = { checkboxColumnWidth: '32px', }, rightDrawerWidth: '500px', - leftNavBarWidth: '220px', clickableElementBackgroundTransition: 'background 0.1s ease', lastLayerZIndex: 2147483647, }; diff --git a/front/src/pages/companies/CompanyShow.tsx b/front/src/pages/companies/CompanyShow.tsx index 708ed9e2f..64ca1281c 100644 --- a/front/src/pages/companies/CompanyShow.tsx +++ b/front/src/pages/companies/CompanyShow.tsx @@ -18,6 +18,7 @@ import { CommentableType } from '~/generated/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; import { CompanyNameEditableField } from '../../modules/companies/editable-field/components/CompanyNameEditableField'; +import { ShowPageContainer } from '../../modules/ui/layout/components/ShowPageContainer'; export function CompanyShow() { const companyId = useParams().companyId ?? ''; @@ -35,29 +36,31 @@ export function CompanyShow() { hasBackButton icon={} > - - ( - - )} - /> - - - - - - - - - - - + + + ( + + )} + /> + + + + + + + + + + + + ); } diff --git a/front/src/pages/people/PersonShow.tsx b/front/src/pages/people/PersonShow.tsx index 9f6e51331..89f4ca5ec 100644 --- a/front/src/pages/people/PersonShow.tsx +++ b/front/src/pages/people/PersonShow.tsx @@ -12,6 +12,7 @@ import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSu import { CommentableType } from '~/generated/graphql'; import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField'; +import { ShowPageContainer } from '../../modules/ui/layout/components/ShowPageContainer'; export function PersonShow() { const personId = useParams().personId ?? ''; @@ -27,7 +28,7 @@ export function PersonShow() { icon={} hasBackButton > - <> + - + ); } diff --git a/front/src/pages/settings/SettingsExperience.tsx b/front/src/pages/settings/SettingsExperience.tsx index 00a3c5aaa..f58258a57 100644 --- a/front/src/pages/settings/SettingsExperience.tsx +++ b/front/src/pages/settings/SettingsExperience.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { ColorSchemePicker } from '@/ui/color-scheme/components/ColorSchemePicker'; -import { NoTopBarContainer } from '@/ui/layout/components/NoTopBarContainer'; +import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; import { useColorScheme } from '@/ui/themes/hooks/useColorScheme'; import { MainSectionTitle } from '@/ui/title/components/MainSectionTitle'; import { SubSectionTitle } from '@/ui/title/components/SubSectionTitle'; @@ -27,7 +27,7 @@ export function SettingsExperience() { const { colorScheme, setColorScheme } = useColorScheme(); return ( - +
Experience @@ -37,6 +37,6 @@ export function SettingsExperience() {
-
+ ); } diff --git a/front/src/pages/settings/SettingsProfile.tsx b/front/src/pages/settings/SettingsProfile.tsx index 8b110932d..8335d450a 100644 --- a/front/src/pages/settings/SettingsProfile.tsx +++ b/front/src/pages/settings/SettingsProfile.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; import { EmailField } from '@/settings/profile/components/EmailField'; import { NameFields } from '@/settings/profile/components/NameFields'; import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader'; -import { NoTopBarContainer } from '@/ui/layout/components/NoTopBarContainer'; +import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; import { MainSectionTitle } from '@/ui/title/components/MainSectionTitle'; import { SubSectionTitle } from '@/ui/title/components/SubSectionTitle'; @@ -26,7 +26,7 @@ const StyledSectionContainer = styled.div` export function SettingsProfile() { return ( - +
Profile @@ -50,6 +50,6 @@ export function SettingsProfile() {
-
+ ); } diff --git a/front/src/pages/settings/SettingsWorkspace.tsx b/front/src/pages/settings/SettingsWorkspace.tsx index 376fd5d0e..ca8c3a995 100644 --- a/front/src/pages/settings/SettingsWorkspace.tsx +++ b/front/src/pages/settings/SettingsWorkspace.tsx @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; import { NameField } from '@/settings/workspace/components/NameField'; import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader'; -import { NoTopBarContainer } from '@/ui/layout/components/NoTopBarContainer'; +import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; import { MainSectionTitle } from '@/ui/title/components/MainSectionTitle'; import { SubSectionTitle } from '@/ui/title/components/SubSectionTitle'; @@ -24,7 +24,7 @@ const StyledSectionContainer = styled.div` export function SettingsWorksapce() { return ( - +
General @@ -41,6 +41,6 @@ export function SettingsWorksapce() {
-
+ ); } diff --git a/front/src/pages/settings/SettingsWorkspaceMembers.tsx b/front/src/pages/settings/SettingsWorkspaceMembers.tsx index 820fe9f05..24ac47196 100644 --- a/front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -5,7 +5,7 @@ import { useRecoilState } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; import { Button } from '@/ui/button/components/Button'; import { IconTrash } from '@/ui/icon'; -import { NoTopBarContainer } from '@/ui/layout/components/NoTopBarContainer'; +import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; import { MainSectionTitle } from '@/ui/title/components/MainSectionTitle'; import { SubSectionTitle } from '@/ui/title/components/SubSectionTitle'; import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink'; @@ -75,7 +75,7 @@ export function SettingsWorkspaceMembers() { }; return ( - + Members {workspace?.inviteHash && ( @@ -112,6 +112,6 @@ export function SettingsWorkspaceMembers() { /> ))} - + ); } diff --git a/front/yarn.lock b/front/yarn.lock index 2ee6bb4bf..262be2270 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -8275,6 +8275,11 @@ css-loader@^6.5.1, css-loader@^6.7.1, css-loader@^6.7.3: postcss-value-parser "^4.2.0" semver "^7.3.8" +css-mediaquery@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0" + integrity sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q== + css-minimizer-webpack-plugin@^3.2.0: version "3.4.1" resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" @@ -11054,6 +11059,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +hyphenate-style-name@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -13201,6 +13211,13 @@ markdown-to-jsx@^7.1.8: resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.2.1.tgz#87061fd3176ad926ef3d99493e5c57f6335e0c51" integrity sha512-9HrdzBAo0+sFz9ZYAGT5fB8ilzTW+q6lPocRxrIesMO+aB40V9MgFfbfMXxlGjf22OpRy+IXlvVaQenicdpgbg== +matchmediaquery@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/matchmediaquery/-/matchmediaquery-0.3.1.tgz#8247edc47e499ebb7c58f62a9ff9ccf5b815c6d7" + integrity sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ== + dependencies: + css-mediaquery "^0.1.2" + mdast-util-definitions@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" @@ -15306,7 +15323,7 @@ prompts@^2.0.1, prompts@^2.4.0, prompts@^2.4.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.6.1, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -15850,6 +15867,16 @@ react-remove-scroll@2.5.4: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" +react-responsive@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-9.0.2.tgz#34531ca77a61e7a8775714016d21241df7e4205c" + integrity sha512-+4CCab7z8G8glgJoRjAwocsgsv6VA2w7JPxFWHRc7kvz8mec1/K5LutNC2MG28Mn8mu6+bu04XZxHv5gyfT7xQ== + dependencies: + hyphenate-style-name "^1.0.0" + matchmediaquery "^0.3.0" + prop-types "^15.6.1" + shallow-equal "^1.2.1" + react-router-dom@^6.4.4: version "6.14.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.14.1.tgz#0ad7ba7abdf75baa61169d49f096f0494907a36f" @@ -16795,6 +16822,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallow-equal@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" + integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA== + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"