💬(frontend) add missing link in onboarding description

We added a missing link in the onboarding step
description to direct users to ready-made templates f
or common use cases. This enhancement aims to improve
the user experience by providing easy access to
resources that can help users get started quickly
and customize their workflow efficiently.
This commit is contained in:
Anthony LC
2026-05-05 13:23:19 +02:00
parent b0d9ed15c0
commit 5f700ed6c4
7 changed files with 72 additions and 14 deletions
+1
View File
@@ -12,6 +12,7 @@ and this project adheres to
### Fixed
- 💬(frontend) add missing link in onboarding description #2233
- 🐛(frontend) sanitize pasted and dropped content in document title #2210
- 🐛(frontend) Emoji menu doesn't display above comment box #2229
- 🐛(frontend) Block menu doesn't stay open on 1st line #2229
@@ -161,7 +161,8 @@
},
"onboarding": {
"enabled": true,
"learn_more_url": ""
"learn_more_url": "",
"ready_template_url": ""
},
"help": {
"documentation_url": ""
@@ -153,7 +153,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',
},
},
});
@@ -184,18 +185,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();
@@ -241,6 +243,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')).toHaveText(
"modèles prêts à l'emploi",
);
});
test('Modal is displayed automatically on first connection', async ({
@@ -28,6 +28,7 @@ interface ThemeCustomization {
onboarding?: {
enabled: true;
learn_more_url?: string;
ready_template_url?: string;
};
translations?: Resource;
waffle?: WaffleType;
@@ -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<OnboardingStep, 'description'> & {
description?: ReactNode;
};
type OnboardingModalPropsFixed = Omit<OnboardingModalProps, 'steps'> & {
steps?: OnboardingStepFixed[];
};
const OnboardingModalFixed =
OnboardingModal as React.ComponentType<OnboardingModalPropsFixed>;
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 */
@@ -56,6 +78,10 @@ const OnBoardingStyle = createGlobalStyle`
display: flex;
flex-direction: column;
a{
color: inherit;
}
& .c__onboarding-modal__body{
justify-content: center;
}
@@ -81,7 +107,7 @@ export const OnBoarding = (props: OnBoardingProps) => {
return (
<>
{props.isOpen ? <OnBoardingStyle /> : null}
<OnboardingModal
<OnboardingModalFixed
size={ModalSize.LARGE}
appName={t('Discover Docs')}
mainTitle={t('Learn the core principles')}
@@ -1,7 +1,8 @@
import { type OnboardingStep } from '@gouvfr-lasuite/ui-kit';
import Image from 'next/image';
import { useTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';
import { useConfig } from '@/core';
import { useCunninghamTheme } from '@/cunningham';
import DragIndicatorIcon from '../assets/drag_indicator.svg';
@@ -16,6 +17,9 @@ export interface OnboardingStepsData {
export const useOnboardingSteps = () => {
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,21 @@ export const useOnboardingSteps = () => {
</OnboardingStepIcon>
),
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: (
<Trans
t={t}
i18nKey="Start from <Link>ready-made templates</Link> for common use cases, then customize them to match your workflow in minutes."
components={{
Link: (
<a
target="_blank"
rel="noopener noreferrer"
href={readyTemplateUrl}
aria-label={t('Ready-made templates (opens in a new tab)')}
/>
),
}}
/>
),
content: (
<Image
@@ -1482,7 +1482,7 @@
"Simple document icon": "Icône simple du document",
"Something bad happens, please retry.": "Une erreur inattendue s'est produite, veuillez réessayer.",
"Start Writing": "Commencer à écrire",
"Start from 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.",
"Start from <Link>ready-made templates</Link> for common use cases, then customize them to match your workflow in minutes.": "Commencez à partir de <Link>modèles prêts à l'emploi</Link> 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",