Files
lasuite-docs/src/frontend/apps/impress/src/features/help/components/HelpMenu.tsx
T
Anthony LC e0fcd2a01e ⬆️(frontend) replace ui-kit by ui-components
A major release was made on the ui-kit side,
ui-kit is replaced by ui-components, which is a new
package that contains the same components as ui-kit
but with some improvements.
To build the tokens, a new dev dependency is necessary,
which is @gouvfr-lasuite/ui-tokens.
These replacements bring better separation of concerns
and a better architecture for the future.
We need to adapt our codebase to use the new package
and the new dev dependency.
2026-08-28 11:09:11 +02:00

207 lines
5.9 KiB
TypeScript

import {
Button,
ButtonProps,
DropdownMenu,
DropdownMenuItem,
useModal,
} from '@gouvfr-lasuite/ui-components';
import { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { createGlobalStyle, css } from 'styled-components';
import BubbleTextIcon from '@/assets/icons/ui-kit/bubble-text.svg';
import DocIcon from '@/assets/icons/ui-kit/doc.svg';
import LegalIcon from '@/assets/icons/ui-kit/legal.svg';
import HelpIcon from '@/assets/icons/ui-kit/question-mark.svg';
import WandAndStarsIcon from '@/assets/icons/ui-kit/wand-and-stars.svg';
import { Box } from '@/components';
import { useConfig } from '@/core';
import { OnBoarding } from './OnBoarding';
// HelpMenuStyle is mounted only when isMenuOpen is true so this global
// `.c__dropdown-menu { overflow: visible; }` rule does not affect other dropdowns.
const HelpMenuStyle = createGlobalStyle`
.c__dropdown-menu {
overflow: visible;
}
`;
export const HelpMenu = ({
colorButton,
}: {
colorButton?: ButtonProps['color'];
}) => {
const { t } = useTranslation();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const modalOnbording = useModal();
const { data: config } = useConfig();
const onboardingEnabled = config?.theme_customization?.onboarding?.enabled;
const documentationUrl = config?.theme_customization?.help?.documentation_url;
const supportMailto = config?.theme_customization?.help?.support_mailto;
const legalLinks = config?.theme_customization?.help?.legal_links;
/**
* The onboarding can be disable, so we need to check if it's enabled before displaying the help menu.
* TODO: As soon as we get more than one fixed element in the help menu,
* we should remove this condition and display the help menu even if the onboarding is disabled
*/
const showHelpMenu =
onboardingEnabled ||
!!documentationUrl ||
!!supportMailto ||
!!legalLinks?.personal_data ||
!!legalLinks?.terms_of_use ||
!!legalLinks?.accessibility_statement ||
!!legalLinks?.legal_notice;
const toggleMenu = useCallback(() => {
setIsMenuOpen((open) => !open);
}, []);
const openExternalLink = useCallback((url: string) => {
window.open(url, '_blank', 'noopener,noreferrer');
}, []);
const openMailto = useCallback((mailto: string) => {
window.location.href = mailto;
}, []);
const hasLegalLinks =
!!legalLinks?.personal_data ||
!!legalLinks?.terms_of_use ||
!!legalLinks?.accessibility_statement ||
!!legalLinks?.legal_notice;
const options = useMemo<DropdownMenuItem[]>(
() => [
{
label: t('Get Support'),
icon: <BubbleTextIcon aria-hidden="true" width="24" height="24" />,
callback: () => {
if (supportMailto) {
openMailto(supportMailto);
}
},
isHidden: !supportMailto,
},
{
label: t('Documentation'),
icon: <DocIcon aria-hidden="true" width="24" height="24" />,
callback: () => {
if (documentationUrl) {
openExternalLink(documentationUrl);
}
},
isHidden: !documentationUrl,
},
{
label: t('Onboarding'),
icon: <WandAndStarsIcon aria-hidden="true" width="24" height="24" />,
callback: modalOnbording.open,
isHidden: !onboardingEnabled,
},
{
label: t('Legal'),
icon: <LegalIcon aria-hidden="true" width="24" height="24" />,
isHidden: !hasLegalLinks,
children: [
{
label: t('Personal data and cookies'),
callback: () => {
if (legalLinks?.personal_data) {
openExternalLink(legalLinks.personal_data);
}
},
isHidden: !legalLinks?.personal_data,
},
{
label: t('Terms of use'),
callback: () => {
if (legalLinks?.terms_of_use) {
openExternalLink(legalLinks.terms_of_use);
}
},
isHidden: !legalLinks?.terms_of_use,
},
{
label: t('Accessibility statement'),
callback: () => {
if (legalLinks?.accessibility_statement) {
openExternalLink(legalLinks.accessibility_statement);
}
},
isHidden: !legalLinks?.accessibility_statement,
},
{
label: t('Legal notice'),
callback: () => {
if (legalLinks?.legal_notice) {
openExternalLink(legalLinks.legal_notice);
}
},
isHidden: !legalLinks?.legal_notice,
},
],
},
],
[
t,
supportMailto,
documentationUrl,
openMailto,
modalOnbording.open,
onboardingEnabled,
openExternalLink,
legalLinks,
hasLegalLinks,
],
);
if (!showHelpMenu) {
return null;
}
return (
<>
{isMenuOpen && <HelpMenuStyle />}
<Box
$css={css`
.c__dropdown-menu-trigger {
width: fit-content;
justify-content: flex-start;
}
`}
>
<DropdownMenu
options={options}
isOpen={isMenuOpen}
onOpenChange={setIsMenuOpen}
>
<Box $direction="row" $align="center">
<Button
aria-label={t('Open help menu')}
color={colorButton || 'neutral'}
variant="tertiary"
iconPosition="left"
icon={
<HelpIcon
aria-hidden="true"
color="inherit"
width="24"
height="24"
/>
}
onClick={toggleMenu}
/>
</Box>
</DropdownMenu>
</Box>
<OnBoarding
isOpen={modalOnbording.isOpen}
onClose={modalOnbording.close}
/>
</>
);
};