From 83eb33d54a63b953fb3f606d759154afa131fe9f Mon Sep 17 00:00:00 2001 From: Nathan Panchout Date: Mon, 18 Nov 2024 09:46:15 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84(frontend)=20updating=20the=20heade?= =?UTF-8?q?r=20and=20leftpanel=20for=20responsive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously we added a left panel. We now need to adapt the layout so that it becomesresponsive. We therefore add a burger menu on the left on mobile which, when clicked, deploys the left-panel over all the content. --- CHANGELOG.md | 1 + .../e2e/__tests__/app-impress/header.spec.ts | 22 +--- .../__tests__/app-impress/left-panel.spec.ts | 25 ++++- .../src/features/header/assets/icon-docs.svg | 33 +----- .../src/features/header/components/Header.tsx | 104 ++++++++++-------- .../left-panel/components/LeftPanel.tsx | 95 +++++++++------- .../left-panel/components/LeftPanelHeader.tsx | 55 +++++++++ .../impress/src/features/left-panel/index.ts | 1 + .../src/features/left-panel/stores/index.ts | 1 + .../left-panel/stores/useLeftPanelStore.tsx | 11 ++ .../apps/impress/src/layouts/MainLayout.tsx | 15 ++- 11 files changed, 223 insertions(+), 140 deletions(-) create mode 100644 src/frontend/apps/impress/src/features/left-panel/components/LeftPanelHeader.tsx create mode 100644 src/frontend/apps/impress/src/features/left-panel/stores/index.ts create mode 100644 src/frontend/apps/impress/src/features/left-panel/stores/useLeftPanelStore.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index b1dd211b..b544febf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to - 🏗️(yjs-server) organize yjs server #528 - ♻️(frontend) better separation collaboration process #528 +- 💄(frontend) updating the header and leftpanel for responsive #421 ## [1.10.0] - 2024-12-17 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts index e1ade402..5f78d90c 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts @@ -75,29 +75,15 @@ test.describe('Header mobile', () => { test('it checks the header when mobile', async ({ page }) => { const header = page.locator('header').first(); + await expect(header.getByLabel('Open the header menu')).toBeVisible(); + await expect( + header.getByRole('link', { name: 'Docs Logo Docs' }), + ).toBeVisible(); await expect( header.getByRole('button', { name: 'Les services de La Suite numérique', }), ).toBeVisible(); - - await expect( - page.getByRole('button', { - name: 'Logout', - }), - ).toBeHidden(); - - await expect(page.getByText('English')).toBeHidden(); - - await header.getByLabel('Open the header menu').click(); - - await expect( - page.getByRole('button', { - name: 'Logout', - }), - ).toBeVisible(); - - await expect(page.getByText('English')).toBeVisible(); }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/left-panel.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/left-panel.spec.ts index 648f0819..576cf8b0 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/left-panel.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/left-panel.spec.ts @@ -7,6 +7,7 @@ test.describe('Left panel desktop', () => { test('checks all the elements are visible', async ({ page }) => { await expect(page.getByTestId('left-panel-desktop')).toBeVisible(); + await expect(page.getByTestId('left-panel-mobile')).toBeHidden(); await expect(page.getByRole('button', { name: 'house' })).toBeVisible(); await expect(page.getByRole('button', { name: 'New doc' })).toBeVisible(); }); @@ -19,7 +20,29 @@ test.describe('Left panel mobile', () => { await page.goto('/'); }); - test('checks all the desktop elements are hidden', async ({ page }) => { + test('checks all the desktop elements are hidden and all mobile elements are visible', async ({ + page, + }) => { await expect(page.getByTestId('left-panel-desktop')).toBeHidden(); + await expect(page.getByTestId('left-panel-mobile')).not.toBeInViewport(); + + const header = page.locator('header').first(); + const homeButton = page.getByRole('button', { name: 'house' }); + const newDocButton = page.getByRole('button', { name: 'New doc' }); + const languageButton = page.getByRole('combobox', { name: 'Language' }); + const logoutButton = page.getByRole('button', { name: 'Logout' }); + + await expect(homeButton).not.toBeInViewport(); + await expect(newDocButton).not.toBeInViewport(); + await expect(languageButton).not.toBeInViewport(); + await expect(logoutButton).not.toBeInViewport(); + + await header.getByLabel('Open the header menu').click(); + + await expect(page.getByTestId('left-panel-mobile')).toBeInViewport(); + await expect(homeButton).toBeInViewport(); + await expect(newDocButton).toBeInViewport(); + await expect(languageButton).toBeInViewport(); + await expect(logoutButton).toBeInViewport(); }); }); diff --git a/src/frontend/apps/impress/src/features/header/assets/icon-docs.svg b/src/frontend/apps/impress/src/features/header/assets/icon-docs.svg index 4db0531f..4f26ae3b 100644 --- a/src/frontend/apps/impress/src/features/header/assets/icon-docs.svg +++ b/src/frontend/apps/impress/src/features/header/assets/icon-docs.svg @@ -1,31 +1,4 @@ - - - - - - - - - - - - + + + diff --git a/src/frontend/apps/impress/src/features/header/components/Header.tsx b/src/frontend/apps/impress/src/features/header/components/Header.tsx index 2d5c02b7..75f5de11 100644 --- a/src/frontend/apps/impress/src/features/header/components/Header.tsx +++ b/src/frontend/apps/impress/src/features/header/components/Header.tsx @@ -1,67 +1,83 @@ +import { Button } from '@openfun/cunningham-react'; import Image from 'next/image'; import { useTranslation } from 'react-i18next'; +import { css } from 'styled-components'; -import { Box, StyledLink } from '@/components/'; +import { Box, Icon, StyledLink } from '@/components/'; import { ButtonLogin } from '@/core/auth'; +import { useCunninghamTheme } from '@/cunningham'; import { LanguagePicker } from '@/features/language'; +import { useLeftPanelStore } from '@/features/left-panel'; import { useResponsiveStore } from '@/stores'; import { default as IconDocs } from '../assets/icon-docs.svg?url'; +import { HEADER_HEIGHT } from '../conf'; -import { DropdownMenu } from './DropdownMenu'; import { LaGaufre } from './LaGaufre'; import Title from './Title/Title'; export const Header = () => { const { t } = useTranslation(); - const { isSmallMobile } = useResponsiveStore(); + const theme = useCunninghamTheme(); + const { isPanelOpen, togglePanel } = useLeftPanelStore(); + const { isDesktop } = useResponsiveStore(); + + const spacings = theme.spacingsTokens(); + const colors = theme.colorsTokens(); return ( - - - - - - - - + {!isDesktop && ( + } + /> + )} + + + + - {isSmallMobile ? ( - - - - - ) : ( - - - - - - )} - + + {!isDesktop ? ( + + + + ) : ( + + + + + + )} ); }; diff --git a/src/frontend/apps/impress/src/features/left-panel/components/LeftPanel.tsx b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanel.tsx index 6140f84a..a32a600b 100644 --- a/src/frontend/apps/impress/src/features/left-panel/components/LeftPanel.tsx +++ b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanel.tsx @@ -1,34 +1,29 @@ -import { Button } from '@openfun/cunningham-react'; -import { useRouter } from 'next/navigation'; import { PropsWithChildren } from 'react'; -import { useTranslation } from 'react-i18next'; +import { createGlobalStyle, css } from 'styled-components'; -import { Box, Icon, SeparatedSection } from '@/components'; +import { Box, SeparatedSection } from '@/components'; +import { ButtonLogin } from '@/core'; import { useCunninghamTheme } from '@/cunningham'; -import { useCreateDoc } from '@/features/docs'; import { HEADER_HEIGHT } from '@/features/header/conf'; +import { LanguagePicker } from '@/features/language'; import { useResponsiveStore } from '@/stores'; +import { useLeftPanelStore } from '../stores'; + +import { LeftPanelHeader } from './LeftPanelHeader'; + +const MobileLeftPanelStyle = createGlobalStyle` + body { + overflow: hidden; + } +`; + export const LeftPanel = ({ children }: PropsWithChildren) => { - const { t } = useTranslation(); - const router = useRouter(); const { isDesktop } = useResponsiveStore(); + const { isPanelOpen } = useLeftPanelStore(); const theme = useCunninghamTheme(); const colors = theme.colorsTokens(); - - const { mutate: createDoc } = useCreateDoc({ - onSuccess: (doc) => { - router.push(`/docs/${doc.id}`); - }, - }); - - const goToHome = () => { - router.push('/'); - }; - - const createNewDoc = () => { - createDoc({ title: t('Untitled document') }); - }; + const spacings = theme.spacingsTokens(); return ( <> @@ -42,29 +37,45 @@ export const LeftPanel = ({ children }: PropsWithChildren) => { border-right: 1px solid ${colors['greyscale-200']}; `} > -
- - - - - - - {children} -
+ {children} )} + + {!isDesktop && ( + <> + {isPanelOpen && } + + + {children} + + + + + + + + + + )} ); }; diff --git a/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelHeader.tsx b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelHeader.tsx new file mode 100644 index 00000000..37ce4520 --- /dev/null +++ b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelHeader.tsx @@ -0,0 +1,55 @@ +import { Button } from '@openfun/cunningham-react'; +import { t } from 'i18next'; +import { useRouter } from 'next/navigation'; +import { PropsWithChildren } from 'react'; + +import { Box, Icon, SeparatedSection } from '@/components'; +import { useCreateDoc } from '@/features/docs'; + +import { useLeftPanelStore } from '../stores'; + +export const LeftPanelHeader = ({ children }: PropsWithChildren) => { + const router = useRouter(); + const { togglePanel } = useLeftPanelStore(); + + const { mutate: createDoc } = useCreateDoc({ + onSuccess: (doc) => { + router.push(`/docs/${doc.id}`); + togglePanel(); + }, + }); + + const goToHome = () => { + router.push('/'); + togglePanel(); + }; + + const createNewDoc = () => { + createDoc({ title: t('Untitled document') }); + }; + + return ( + + + + + + + + {children} + + ); +}; diff --git a/src/frontend/apps/impress/src/features/left-panel/index.ts b/src/frontend/apps/impress/src/features/left-panel/index.ts index 07635cbb..70605fb7 100644 --- a/src/frontend/apps/impress/src/features/left-panel/index.ts +++ b/src/frontend/apps/impress/src/features/left-panel/index.ts @@ -1 +1,2 @@ export * from './components'; +export * from './stores'; diff --git a/src/frontend/apps/impress/src/features/left-panel/stores/index.ts b/src/frontend/apps/impress/src/features/left-panel/stores/index.ts new file mode 100644 index 00000000..9db6dd9c --- /dev/null +++ b/src/frontend/apps/impress/src/features/left-panel/stores/index.ts @@ -0,0 +1 @@ +export * from './useLeftPanelStore'; diff --git a/src/frontend/apps/impress/src/features/left-panel/stores/useLeftPanelStore.tsx b/src/frontend/apps/impress/src/features/left-panel/stores/useLeftPanelStore.tsx new file mode 100644 index 00000000..f9fd5783 --- /dev/null +++ b/src/frontend/apps/impress/src/features/left-panel/stores/useLeftPanelStore.tsx @@ -0,0 +1,11 @@ +import { create } from 'zustand'; + +interface LeftPanelState { + isPanelOpen: boolean; + togglePanel: () => void; +} + +export const useLeftPanelStore = create((set) => ({ + isPanelOpen: false, + togglePanel: () => set((state) => ({ isPanelOpen: !state.isPanelOpen })), +})); diff --git a/src/frontend/apps/impress/src/layouts/MainLayout.tsx b/src/frontend/apps/impress/src/layouts/MainLayout.tsx index 21af21eb..b20e5136 100644 --- a/src/frontend/apps/impress/src/layouts/MainLayout.tsx +++ b/src/frontend/apps/impress/src/layouts/MainLayout.tsx @@ -1,4 +1,5 @@ import { PropsWithChildren } from 'react'; +import { css } from 'styled-components'; import { Box } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; @@ -27,7 +28,11 @@ export function MainLayout({ return (
- + {children}