From 43a3620700cb4df72dcc6eab75815cdc2c6d9993 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 21 May 2026 12:04:35 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=B1(frontend)=20reduce=20breakpoint=20?= =?UTF-8?q?mobile=20view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the application was switching to mobile view at the medium breakpoint. Medium breakpoint let enough place to display most of the application features and it is more user friendly to switch to mobile view at the small breakpoint. We are switching to mobile view at the small breakpoint to give more place to the application features and to be more user friendly. --- .../__tests__/app-impress/left-panel.spec.ts | 36 ++++++++++--------- .../docs/doc-header/components/DocTitle.tsx | 8 ++--- .../doc-header/components/FloatingBar.tsx | 4 +-- .../doc-search/components/DocSearchModal.tsx | 14 ++++++-- .../docs/docs-grid/components/DocsGrid.tsx | 2 +- .../src/features/header/components/Header.tsx | 6 ++-- .../left-panel/components/LeftPanel.tsx | 4 +-- .../components/LeftPanelFavoriteItem.tsx | 4 +-- .../components/ResizableLeftPanel.tsx | 18 +++++----- .../apps/impress/src/layouts/MainLayout.tsx | 4 +-- .../apps/impress/src/layouts/PageLayout.tsx | 4 +-- .../impress/src/stores/useResponsiveStore.tsx | 6 ++-- 12 files changed, 61 insertions(+), 49 deletions(-) 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 f19f1909e..b6f4cb367 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 @@ -84,16 +84,13 @@ test.describe('Left panel desktop', () => { }); }); -test.describe('Left panel mobile', () => { - test.use({ viewport: { width: 500, height: 1200 } }); - - test.beforeEach(async ({ page }) => { - await page.goto('/'); - }); - - test('checks all the desktop elements are hidden and all mobile elements are visible', async ({ +test.describe('Left panel responsive', () => { + test('checks elements visibility on different screen sizes', async ({ page, }) => { + await page.setViewportSize({ width: 500, height: 1200 }); + await page.goto('/'); + await expect(page.getByTestId('left-panel-desktop')).toBeHidden(); await expect(page.getByTestId('left-panel-mobile')).not.toBeInViewport(); @@ -120,12 +117,27 @@ test.describe('Left panel mobile', () => { await expect(newDocButton).toBeInViewport(); await expect(languageButton).toBeInViewport(); await expect(logoutButton).toBeInViewport(); + + await header.getByLabel('Close the header menu').click(); + + // Tablet size - like in desktop, left panel should be visible + await page.setViewportSize({ width: 900, height: 1200 }); + await page.goto('/'); + + await expect(page.getByRole('link', { name: 'All docs' })).toBeInViewport(); + await expect(newDocButton).toBeInViewport(); + await expect(languageButton).toBeInViewport(); + await expect(logoutButton).toBeInViewport(); + await expect(header.getByLabel('Open the header menu')).toBeHidden(); }); test('checks panel closes when clicking on a subdoc', async ({ page, browserName, }) => { + await page.setViewportSize({ width: 500, height: 1200 }); + await page.goto('/'); + const [docTitle] = await createDoc( page, 'mobile-doc-test', @@ -162,12 +174,4 @@ test.describe('Left panel mobile', () => { await verifyDocName(page, docChild); await expect(page.getByTestId('left-panel-mobile')).not.toBeInViewport(); }); - - test('checks resize handle is not present on mobile', async ({ page }) => { - await page.goto('/'); - - // Verify the resize handle is NOT present on mobile - const resizeHandle = page.locator('[data-panel-resize-handle-id]'); - await expect(resizeHandle).toBeHidden(); - }); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx index a7f238792..7a3ce2ea2 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx @@ -110,7 +110,7 @@ const DocTitleEmojiPicker = ({ doc }: DocTitleProps) => { }; const DocTitleInput = ({ doc }: DocTitleProps) => { - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const { t } = useTranslation(); const { isTopRoot } = useDocUtils(doc); const { untitledDocument } = useTrans(); @@ -227,9 +227,9 @@ const DocTitleInput = ({ doc }: DocTitleProps) => { pointer-events: none; font-style: italic; } - font-size: ${isDesktop - ? css`var(--c--globals--font--sizes--h2)` - : css`var(--c--globals--font--sizes--sm)`}; + font-size: ${isLargeScreen + ? 'var(--c--globals--font--sizes--h2)' + : 'var(--c--globals--font--sizes--sm)'}; font-weight: 700; outline: none; `} diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/FloatingBar.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/FloatingBar.tsx index 45a94108e..bcd24d2c5 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/FloatingBar.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/FloatingBar.tsx @@ -16,7 +16,7 @@ import { useResponsiveStore } from '@/stores'; */ export const FloatingBar = () => { const { spacingsTokens } = useCunninghamTheme(); - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const FLOATING_STYLES = useMemo(() => { const base = spacingsTokens['base']; @@ -69,7 +69,7 @@ export const FloatingBar = () => { $direction="row" $justify="space-between" > - {isDesktop ? : } + {isLargeScreen ? : } ); diff --git a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx index 3f18134dd..e4dfebe5c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx @@ -4,6 +4,7 @@ import Image from 'next/image'; import { useRouter } from 'next/router'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { createGlobalStyle } from 'styled-components'; import { useDebouncedCallback } from 'use-debounce'; import { Box, ButtonCloseModal, Text } from '@/components'; @@ -20,6 +21,12 @@ import EmptySearchIcon from '../assets/illustration-docs-empty.png'; import { DocSearchContent } from './DocSearchContent'; +const ModalStyle = createGlobalStyle` + .c__modal__scroller { + overflow: inherit ; + } +`; + type DocSearchModalGlobalProps = { onClose: () => void; isOpen: boolean; @@ -43,7 +50,7 @@ const DocSearchModalGlobal = ({ const [filters, setFilters] = useState( defaultFilters ?? {}, ); - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const handleInputSearch = useDebouncedCallback(setSearch, 300); const handleSelect = (doc: Doc) => { @@ -60,10 +67,11 @@ const DocSearchModalGlobal = ({ + {search.length === 0 && ( 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 0efc1072e..07d0678c8 100644 --- a/src/frontend/apps/impress/src/features/header/components/Header.tsx +++ b/src/frontend/apps/impress/src/features/header/components/Header.tsx @@ -19,7 +19,7 @@ export const Header = () => { const { t } = useTranslation(); const { data: config } = useConfig(); const { spacingsTokens } = useCunninghamTheme(); - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const icon = config?.theme_customization?.header?.icon; @@ -46,7 +46,7 @@ export const Header = () => { var(--c--contextuals--border--surface--primary); `} > - {!isDesktop && } + {!isLargeScreen && } { /> - {!isDesktop ? ( + {!isLargeScreen ? ( 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 6d6c8da53..1158ac4cd 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 @@ -24,8 +24,8 @@ const MobileLeftPanelStyle = createGlobalStyle` `; export const LeftPanel = () => { - const { isDesktop } = useResponsiveStore(); - if (isDesktop) { + const { isLargeScreen } = useResponsiveStore(); + if (isLargeScreen) { return ; } diff --git a/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelFavoriteItem.tsx b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelFavoriteItem.tsx index b2d3cc7d7..bc68a7853 100644 --- a/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelFavoriteItem.tsx +++ b/src/frontend/apps/impress/src/features/left-panel/components/LeftPanelFavoriteItem.tsx @@ -14,7 +14,7 @@ type LeftPanelFavoriteItemProps = { export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => { const { colorsTokens, spacingsTokens } = useCunninghamTheme(); - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); return ( { padding: ${spacingsTokens['2xs']}; border-radius: 4px; .pinned-actions { - opacity: ${isDesktop ? 0 : 1}; + opacity: ${isLargeScreen ? 0 : 1}; } &:hover { background-color: var( diff --git a/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx b/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx index cf89f7fbb..8e558aff4 100644 --- a/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx +++ b/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx @@ -51,7 +51,7 @@ export const ResizableLeftPanel = ({ maxPanelSizePx = 450, }: ResizableLeftPanelProps) => { const { t } = useTranslation(); - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const { isPanelOpen } = useLeftPanelStore(); const ref = useRef(null); const savedWidthPxRef = useRef(minPanelSizePx); @@ -89,7 +89,7 @@ export const ResizableLeftPanel = ({ * to either expand/collapse */ useEffect(() => { - if (!ref.current || !isDesktop) { + if (!ref.current || !isLargeScreen) { return; } if (isPanelOpen) { @@ -97,11 +97,11 @@ export const ResizableLeftPanel = ({ } else { ref.current.collapse(); } - }, [isPanelOpen, isDesktop]); + }, [isPanelOpen, isLargeScreen]); // Keep pixel width constant on window resize useEffect(() => { - if (!isDesktop) { + if (!isLargeScreen) { return; } @@ -117,7 +117,7 @@ export const ResizableLeftPanel = ({ return () => { window.removeEventListener('resize', handleResize); }; - }, [isDesktop]); + }, [isLargeScreen]); /** * Workaround: NVDA does not enter focus mode for role="separator" @@ -158,15 +158,15 @@ export const ResizableLeftPanel = ({ }} order={0} defaultSize={ - isDesktop + isLargeScreen ? Math.max( minPanelSizePercent, Math.min(panelSizePercent, maxPanelSizePercent), ) : 0 } - minSize={isDesktop ? minPanelSizePercent : 0} - maxSize={isDesktop ? maxPanelSizePercent : 0} + minSize={isLargeScreen ? minPanelSizePercent : 0} + maxSize={isLargeScreen ? maxPanelSizePercent : 0} onResize={handleResize} > {leftPanel} @@ -193,7 +193,7 @@ export const ResizableLeftPanel = ({ cursor: 'col-resize', }} onDragging={setIsDragging} - disabled={!isDesktop} + disabled={!isLargeScreen} /> )} {children} diff --git a/src/frontend/apps/impress/src/layouts/MainLayout.tsx b/src/frontend/apps/impress/src/layouts/MainLayout.tsx index 750408bf3..b3546cd31 100644 --- a/src/frontend/apps/impress/src/layouts/MainLayout.tsx +++ b/src/frontend/apps/impress/src/layouts/MainLayout.tsx @@ -52,7 +52,7 @@ export function MainLayoutContent({ backgroundColor, enableResizablePanel, }: PropsWithChildren) { - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); if (enableResizablePanel) { return ( @@ -71,7 +71,7 @@ export function MainLayoutContent({ ); } - if (!isDesktop) { + if (!isLargeScreen) { return ( <> diff --git a/src/frontend/apps/impress/src/layouts/PageLayout.tsx b/src/frontend/apps/impress/src/layouts/PageLayout.tsx index d92b28b6f..4969008a4 100644 --- a/src/frontend/apps/impress/src/layouts/PageLayout.tsx +++ b/src/frontend/apps/impress/src/layouts/PageLayout.tsx @@ -18,7 +18,7 @@ export function PageLayout({ children, withFooter = true, }: PropsWithChildren) { - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); const { t } = useTranslation(); return ( - {!isDesktop && } + {!isLargeScreen && } {children} {withFooter &&