💬(frontend) add missing link in onboarding description
Some checks are pending
Helmfile lint / helmfile-lint (push) Waiting to run

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-04-20 18:09:57 +02:00
parent 203b3edcae
commit 8b25b81f3c
No known key found for this signature in database
7 changed files with 67 additions and 14 deletions

View file

@ -14,6 +14,7 @@ and this project adheres to
### Fixed
- 💬(frontend) add missing link in onboarding description #2233
- 🚸(frontend) redirect on current url tab after 401 #2197
- 🐛(frontend) abort check media status unmount #2194
- ✨(backend) order pinned documents by last updated at #2028

View file

@ -161,7 +161,8 @@
},
"onboarding": {
"enabled": true,
"learn_more_url": ""
"learn_more_url": "",
"ready_template_url": ""
},
"help": {
"documentation_url": ""

View file

@ -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', { name: "modèles prêts à l'emploi" }),
).toBeVisible();
});
test('Modal is displayed automatically on first connection', async ({

View file

@ -28,6 +28,7 @@ interface ThemeCustomization {
onboarding?: {
enabled: true;
learn_more_url?: string;
ready_template_url?: string;
};
translations?: Resource;
waffle?: WaffleType;

View file

@ -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 */
@ -81,7 +103,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')}

View file

@ -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,20 @@ 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}
/>
),
}}
/>
),
content: (
<Image

View file

@ -1466,7 +1466,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",