diff --git a/CHANGELOG.md b/CHANGELOG.md index 282ce166f4..7b0588ec7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to ### Fixed -🐛(frontend) fix broadcast store sync #1846 +- 🐛(frontend) fix broadcast store sync #1846 +- ✨(frontend) add onboarding modal with help menu button #1868 ## [v4.5.0] - 2026-01-28 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/onboarding.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/onboarding.spec.ts new file mode 100644 index 0000000000..ab315ccad1 --- /dev/null +++ b/src/frontend/apps/e2e/__tests__/app-impress/onboarding.spec.ts @@ -0,0 +1,36 @@ +import { expect, test } from '@playwright/test'; + +test.describe('Onboarding modal', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + await expect(page.getByTestId('left-panel-desktop')).toBeVisible(); + }); + + test('opens onboarding modal from help menu and can navigate/close', async ({ + page, + }) => { + await page.getByRole('button', { name: 'Open onboarding menu' }).click(); + + await page.getByRole('menuitem', { name: 'Onboarding' }).click(); + + // Modal is rendered by the UI kit + const modal = page.getByTestId('onboarding-modal'); + await expect(modal).toBeVisible(); + + await expect(page.getByTestId('onboarding-step-0')).toHaveAttribute( + 'tabindex', + '0', + ); + + // Go to next step and ensure step focusable state updates + await page.getByTestId('onboarding-next').click(); + await expect(page.getByTestId('onboarding-step-1')).toHaveAttribute( + 'tabindex', + '0', + ); + + // Close the modal using Escape (works regardless of close button label) + await page.keyboard.press('Escape'); + await expect(modal).toBeHidden(); + }); +}); diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json index 0844cd45f0..beef6ea0df 100644 --- a/src/frontend/apps/impress/package.json +++ b/src/frontend/apps/impress/package.json @@ -36,7 +36,7 @@ "@fontsource/material-icons": "5.2.7", "@gouvfr-lasuite/cunningham-react": "4.1.0", "@gouvfr-lasuite/integration": "1.0.3", - "@gouvfr-lasuite/ui-kit": "0.18.7", + "@gouvfr-lasuite/ui-kit": "0.19.5", "@hocuspocus/provider": "3.4.3", "@mantine/core": "8.3.12", "@mantine/hooks": "8.3.12", 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 6c2238f0a4..f147a2b8a6 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 @@ -14,6 +14,7 @@ import { useLeftPanelStore } from '../stores'; import { LeftPanelContent } from './LeftPanelContent'; import { LeftPanelHeader } from './LeftPanelHeader'; +import { LeftPanelHelpMenu } from './LeftPanelHelpMenu'; const MobileLeftPanelStyle = createGlobalStyle` body { @@ -57,6 +58,14 @@ export const LeftPanel = () => { + + + + + )} @@ -91,6 +100,14 @@ export const LeftPanel = () => { > + + + + + { + return ; +}; diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/drag_indicator.svg b/src/frontend/apps/impress/src/features/on-boarding/assets/drag_indicator.svg new file mode 100644 index 0000000000..24325e8838 --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/assets/drag_indicator.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/file-share.svg b/src/frontend/apps/impress/src/features/on-boarding/assets/file-share.svg new file mode 100644 index 0000000000..38b10fcbc4 --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/assets/file-share.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/format-text.svg b/src/frontend/apps/impress/src/features/on-boarding/assets/format-text.svg new file mode 100644 index 0000000000..a20b90404b --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/assets/format-text.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/stack-template.svg b/src/frontend/apps/impress/src/features/on-boarding/assets/stack-template.svg new file mode 100644 index 0000000000..834cfce76d --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/assets/stack-template.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_1.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_1.png new file mode 100644 index 0000000000..02159c479d Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_1.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_2.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_2.png new file mode 100644 index 0000000000..0c297304dd Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_2.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_EN.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_EN.png new file mode 100644 index 0000000000..ee4d789a5b Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_EN.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_FR.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_FR.png new file mode 100644 index 0000000000..64a8060639 Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_3_FR.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_EN.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_EN.png new file mode 100644 index 0000000000..f1968bd04d Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_EN.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_FR.png b/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_FR.png new file mode 100644 index 0000000000..20b250982f Binary files /dev/null and b/src/frontend/apps/impress/src/features/on-boarding/assets/step_4_FR.png differ diff --git a/src/frontend/apps/impress/src/features/on-boarding/assets/wand-and-stars.svg b/src/frontend/apps/impress/src/features/on-boarding/assets/wand-and-stars.svg new file mode 100644 index 0000000000..edfceb61f6 --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/assets/wand-and-stars.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/impress/src/features/on-boarding/components/OnBoarding.tsx b/src/frontend/apps/impress/src/features/on-boarding/components/OnBoarding.tsx new file mode 100644 index 0000000000..0eca9a79d9 --- /dev/null +++ b/src/frontend/apps/impress/src/features/on-boarding/components/OnBoarding.tsx @@ -0,0 +1,74 @@ +import { Button } from '@gouvfr-lasuite/cunningham-react'; +import { DropdownMenu, OnboardingModal } from '@gouvfr-lasuite/ui-kit'; +import { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { css } from 'styled-components'; + +import { Box, Icon } from '@/components'; + +import { useOnboardingMenuOptions } from '../hooks/useOnboardingMenuOptions'; +import { useOnboardingSteps } from '../hooks/useOnboardingSteps'; + +export const OnBoarding = () => { + const { t } = useTranslation(); + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = useCallback(() => { + setIsModalOpen(true); + }, []); + + const closeModal = useCallback(() => { + setIsModalOpen(false); + }, []); + + const toggleMenu = () => { + setIsMenuOpen((open) => !open); + }; + + const steps = useOnboardingSteps(); + const options = useOnboardingMenuOptions({ onOpenOnboarding: openModal }); + + return ( + <> + + +