diff --git a/src/backend/impress/configuration/theme/default.json b/src/backend/impress/configuration/theme/default.json index 99479ea7..92f11b6e 100644 --- a/src/backend/impress/configuration/theme/default.json +++ b/src/backend/impress/configuration/theme/default.json @@ -161,6 +161,7 @@ }, "onboarding": { "enabled": true, - "learn_more_url": "" + "learn_more_url": "", + "ready_template_url": "" } } diff --git a/src/frontend/apps/e2e/__tests__/app-impress/help.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/help.spec.ts index d8e9dca8..69ebe6c5 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/help.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/help.spec.ts @@ -35,7 +35,8 @@ test.describe('Help feature', () => { theme_customization: { onboarding: { enabled: true, - learn_more_url: 'https://example.com/learn-more', + learn_more_url: 'http://localhost:3000/learn-more', + ready_template_url: 'http://localhost:3000/ready-template', }, }, }); @@ -66,18 +67,19 @@ test.describe('Help feature', () => { '0', ); - await page.getByTestId('onboarding-step-3').click(); - await expect(page.getByTestId('onboarding-step-3')).toHaveAttribute( - 'tabindex', - '0', - ); + const step3 = page.getByTestId('onboarding-step-3'); + await step3.click(); + await expect(step3).toHaveAttribute('tabindex', '0'); + await expect( + step3.getByRole('link', { name: 'ready-made template' }), + ).toHaveAttribute('href', 'http://localhost:3000/ready-template'); const learnMoreLink = page.getByRole('link', { name: 'Learn more docs features', }); await expect(learnMoreLink).toHaveAttribute( 'href', - 'https://example.com/learn-more', + 'http://localhost:3000/learn-more', ); await learnMoreLink.click(); @@ -123,6 +125,16 @@ test.describe('Help feature', () => { await expect( modal.getByRole('button', { name: /Suivant/i }), ).toBeVisible(); + await modal + .getByText(/Tirez parti de la bibliothèque de contenu/) + .first() + .click(); + await expect( + modal.getByText(/Commencez à partir de/).first(), + ).toBeVisible(); + await expect( + modal.getByRole('link', { name: "modèles prêts à l'emploi" }), + ).toBeVisible(); }); test('Modal is displayed automatically on first connection', async ({ diff --git a/src/frontend/apps/impress/src/core/config/api/useConfig.tsx b/src/frontend/apps/impress/src/core/config/api/useConfig.tsx index 3597c1cc..edf0500e 100644 --- a/src/frontend/apps/impress/src/core/config/api/useConfig.tsx +++ b/src/frontend/apps/impress/src/core/config/api/useConfig.tsx @@ -19,6 +19,7 @@ interface ThemeCustomization { onboarding?: { enabled: true; learn_more_url?: string; + ready_template_url?: string; }; footer?: FooterType; home: { diff --git a/src/frontend/apps/impress/src/features/help/components/OnBoarding.tsx b/src/frontend/apps/impress/src/features/help/components/OnBoarding.tsx index dd711a26..b5850cea 100644 --- a/src/frontend/apps/impress/src/features/help/components/OnBoarding.tsx +++ b/src/frontend/apps/impress/src/features/help/components/OnBoarding.tsx @@ -2,7 +2,9 @@ import { ModalSize, OnboardingModal, type OnboardingModalProps, + OnboardingStep, } from '@gouvfr-lasuite/ui-kit'; +import React, { ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { createGlobalStyle } from 'styled-components'; @@ -10,9 +12,29 @@ import { useConfig } from '@/core/config/api/useConfig'; import { useOnboardingSteps } from '../hooks/useOnboardingSteps'; +/** + * typing was not correct on ui-kit side for the description prop of OnboardingStep, + * it can be a string or a ReactNode but was typed as string only, so we need to override the + * type here to be able to use ReactNode + */ +type OnboardingStepFixed = Omit & { + description?: ReactNode; +}; + +type OnboardingModalPropsFixed = Omit & { + steps?: OnboardingStepFixed[]; +}; + +const OnboardingModalFixed = + OnboardingModal as React.ComponentType; + const OnBoardingStyle = createGlobalStyle` .c__onboarding-modal__steps{ height: auto; + + & a{ + color:inherit; + } } .c__onboarding-modal__content { height: 350px; @@ -32,7 +54,7 @@ const OnBoardingStyle = createGlobalStyle` *:not(.material-icons):not(.material-icons-filled):not( .material-symbols-outlined ) { - font-family: Marianne, Inter, Roboto Flex Variable, sans-serif; + font-family: var(--c--globals--font--families--base); } /* Separator between content and footer actions/link */ @@ -81,7 +103,7 @@ export const OnBoarding = (props: OnBoardingProps) => { return ( <> {props.isOpen ? : null} - { const { t } = useTranslation(); + const { data: config } = useConfig(); + const readyTemplateUrl = + config?.theme_customization?.onboarding?.ready_template_url; const { contextualTokens, colorsTokens } = useCunninghamTheme(); const activeColor = contextualTokens.content.semantic.brand.tertiary ?? @@ -122,8 +126,20 @@ export const useOnboardingSteps = () => { ), title: t('Draw inspiration from the content library'), - description: t( - 'Start from ready-made templates for common use cases, then customize them to match your workflow in minutes.', + description: ( + + ), + }} + /> ), content: ( ready-made templates for common use cases, then customize them to match your workflow in minutes.": "Commencez à partir de modèles prêts à l'emploi pour les cas d'utilisation courants, puis personnalisez-les pour correspondre à votre flux de travail en quelques minutes.", "Stop": "Arrêter", "Summarize": "Résumer", "Summary": "Sommaire",