💄(frontend) components more multi theme friendly

We adapt a bit the tokens of some components to be
more multi theme friendly.
When we will add another theme, it will be
easier to adapt to the new theme.
This commit is contained in:
Anthony LC
2024-10-11 13:29:07 +02:00
committed by Anthony LC
parent 6e64bad1e2
commit 6c3f3f6a77
20 changed files with 101 additions and 68 deletions

View File

@@ -9,6 +9,11 @@ and this project adheres to
## [Unreleased] ## [Unreleased]
## Changed
♻️(frontend) More multi theme friendly #325
## [1.5.1] - 2024-10-10 ## [1.5.1] - 2024-10-10
## Fixed ## Fixed

View File

@@ -26,7 +26,7 @@ test.describe('Header', () => {
}), }),
).toBeVisible(); ).toBeVisible();
await expect(header.getByAltText('Language Icon')).toBeVisible(); await expect(header.getByText('English')).toBeVisible();
await expect( await expect(
header.getByRole('button', { header.getByRole('button', {
@@ -87,7 +87,7 @@ test.describe('Header mobile', () => {
}), }),
).toBeHidden(); ).toBeHidden();
await expect(page.getByAltText('Language Icon')).toBeHidden(); await expect(page.getByText('English')).toBeHidden();
await header.getByLabel('Open the header menu').click(); await header.getByLabel('Open the header menu').click();
@@ -97,7 +97,7 @@ test.describe('Header mobile', () => {
}), }),
).toBeVisible(); ).toBeVisible();
await expect(page.getByAltText('Language Icon')).toBeVisible(); await expect(page.getByText('English')).toBeVisible();
}); });
}); });

View File

@@ -189,6 +189,9 @@ const config = {
}, },
}, },
}, },
'la-gauffre': {
activated: false,
},
}, },
}, },
dsfr: { dsfr: {
@@ -321,6 +324,7 @@ const config = {
'color-hover': 'var(--c--theme--colors--primary-100)', 'color-hover': 'var(--c--theme--colors--primary-100)',
}, },
'color-hover': 'var(--c--theme--colors--primary-text)', 'color-hover': 'var(--c--theme--colors--primary-text)',
color: 'var(--c--theme--colors--primary-600)',
}, },
}, },
datagrid: { datagrid: {
@@ -335,6 +339,7 @@ const config = {
pagination: { pagination: {
'background-color': 'transparent', 'background-color': 'transparent',
'background-color-active': 'var(--c--theme--colors--primary-300)', 'background-color-active': 'var(--c--theme--colors--primary-300)',
'border-color': 'var(--c--theme--colors--primary-400)',
}, },
}, },
'forms-checkbox': { 'forms-checkbox': {
@@ -384,6 +389,9 @@ const config = {
'forms-textarea': { 'forms-textarea': {
'border-radius': '0', 'border-radius': '0',
}, },
'la-gauffre': {
activated: true,
},
}, },
}, },
}, },

View File

@@ -13,6 +13,7 @@ export const IconBG = ({ iconName, ...textProps }: IconBGProps) => {
$isMaterialIcon $isMaterialIcon
$size="36px" $size="36px"
$theme="primary" $theme="primary"
$variation="600"
$background={colorsTokens()['primary-bg']} $background={colorsTokens()['primary-bg']}
$css={` $css={`
border: 1px solid ${colorsTokens()['primary-200']}; border: 1px solid ${colorsTokens()['primary-200']};

View File

@@ -255,6 +255,7 @@ input:-webkit-autofill:focus {
gap: 3px; gap: 3px;
border-radius: 4px; border-radius: 4px;
background: var(--c--components--datagrid--pagination--background-color); background: var(--c--components--datagrid--pagination--background-color);
border-color: var(--c--components--datagrid--pagination--border-color);
} }
.c__pagination__list .c__button--tertiary-text.c__button--active { .c__pagination__list .c__button--tertiary-text.c__button--active {
@@ -452,6 +453,7 @@ input:-webkit-autofill:focus {
.c__button--tertiary-text { .c__button--tertiary-text {
border: none; border: none;
color: var(--c--components--button--tertiary-text--color);
} }
.c__button--tertiary-text:hover, .c__button--tertiary-text:hover,

View File

@@ -283,6 +283,7 @@
); );
--c--components--button--disabled--color: white; --c--components--button--disabled--color: white;
--c--components--button--disabled--background--color: #b3cef0; --c--components--button--disabled--background--color: #b3cef0;
--c--components--la-gauffre--activated: false;
} }
.cunningham-theme--dark { .cunningham-theme--dark {
@@ -451,6 +452,9 @@
--c--components--button--tertiary-text--color-hover: var( --c--components--button--tertiary-text--color-hover: var(
--c--theme--colors--primary-text --c--theme--colors--primary-text
); );
--c--components--button--tertiary-text--color: var(
--c--theme--colors--primary-600
);
--c--components--datagrid--header--color: var( --c--components--datagrid--header--color: var(
--c--theme--colors--primary-text --c--theme--colors--primary-text
); );
@@ -461,6 +465,9 @@
--c--components--datagrid--pagination--background-color-active: var( --c--components--datagrid--pagination--background-color-active: var(
--c--theme--colors--primary-300 --c--theme--colors--primary-300
); );
--c--components--datagrid--pagination--border-color: var(
--c--theme--colors--primary-400
);
--c--components--forms-checkbox--border-radius: 0; --c--components--forms-checkbox--border-radius: 0;
--c--components--forms-checkbox--color: var(--c--theme--colors--primary-text); --c--components--forms-checkbox--color: var(--c--theme--colors--primary-text);
--c--components--forms-checkbox--text--color: var( --c--components--forms-checkbox--text--color: var(
@@ -504,6 +511,7 @@
--c--theme--colors--primary-text --c--theme--colors--primary-text
); );
--c--components--forms-textarea--border-radius: 0; --c--components--forms-textarea--border-radius: 0;
--c--components--la-gauffre--activated: true;
} }
.clr-secondary-text { .clr-secondary-text {

View File

@@ -276,6 +276,7 @@ export const tokens = {
}, },
disabled: { color: 'white', background: { color: '#b3cef0' } }, disabled: { color: 'white', background: { color: '#b3cef0' } },
}, },
'la-gauffre': { activated: false },
}, },
}, },
dark: { dark: {
@@ -450,6 +451,7 @@ export const tokens = {
'color-hover': 'var(--c--theme--colors--primary-100)', 'color-hover': 'var(--c--theme--colors--primary-100)',
}, },
'color-hover': 'var(--c--theme--colors--primary-text)', 'color-hover': 'var(--c--theme--colors--primary-text)',
color: 'var(--c--theme--colors--primary-600)',
}, },
}, },
datagrid: { datagrid: {
@@ -464,6 +466,7 @@ export const tokens = {
pagination: { pagination: {
'background-color': 'transparent', 'background-color': 'transparent',
'background-color-active': 'var(--c--theme--colors--primary-300)', 'background-color-active': 'var(--c--theme--colors--primary-300)',
'border-color': 'var(--c--theme--colors--primary-400)',
}, },
}, },
'forms-checkbox': { 'forms-checkbox': {
@@ -503,6 +506,7 @@ export const tokens = {
'accent-color': 'var(--c--theme--colors--primary-text)', 'accent-color': 'var(--c--theme--colors--primary-text)',
}, },
'forms-textarea': { 'border-radius': '0' }, 'forms-textarea': { 'border-radius': '0' },
'la-gauffre': { activated: true },
}, },
}, },
}, },

View File

@@ -102,6 +102,7 @@ export const PanelEditor = ({
$weight="bold" $weight="bold"
$size="m" $size="m"
$theme="primary" $theme="primary"
$variation="600"
$padding={{ vertical: 'small', horizontal: 'small' }} $padding={{ vertical: 'small', horizontal: 'small' }}
> >
{t('Table of content')} {t('Table of content')}
@@ -118,6 +119,7 @@ export const PanelEditor = ({
$weight="bold" $weight="bold"
$size="m" $size="m"
$theme="primary" $theme="primary"
$variation="600"
$padding={{ vertical: 'small', horizontal: 'small' }} $padding={{ vertical: 'small', horizontal: 'small' }}
> >
{t('Versions')} {t('Versions')}

View File

@@ -44,6 +44,7 @@ export const DocHeader = ({ doc, versionId }: DocHeaderProps) => {
<Text <Text
$isMaterialIcon $isMaterialIcon
$theme="primary" $theme="primary"
$variation="600"
$size="2rem" $size="2rem"
$css={`&:hover {background-color: ${colorsTokens()['primary-100']}; };`} $css={`&:hover {background-color: ${colorsTokens()['primary-100']}; };`}
$hasTransition $hasTransition

View File

@@ -2,7 +2,7 @@ import { Button } from '@openfun/cunningham-react';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Box, DropButton, IconOptions, Text } from '@/components'; import { Box, DropButton, IconOptions } from '@/components';
import { useAuthStore } from '@/core'; import { useAuthStore } from '@/core';
import { usePanelEditorStore } from '@/features/docs/doc-editor/'; import { usePanelEditorStore } from '@/features/docs/doc-editor/';
import { import {
@@ -86,7 +86,7 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
icon={<span className="material-icons">history</span>} icon={<span className="material-icons">history</span>}
size="small" size="small"
> >
<Text $theme="primary">{t('Version history')}</Text> {t('Version history')}
</Button> </Button>
)} )}
<Button <Button
@@ -99,7 +99,7 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
icon={<span className="material-icons">summarize</span>} icon={<span className="material-icons">summarize</span>}
size="small" size="small"
> >
<Text $theme="primary">{t('Table of contents')}</Text> {t('Table of contents')}
</Button> </Button>
<Button <Button
onClick={() => { onClick={() => {
@@ -110,7 +110,7 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
icon={<span className="material-icons">file_download</span>} icon={<span className="material-icons">file_download</span>}
size="small" size="small"
> >
<Text $theme="primary">{t('Export')}</Text> {t('Export')}
</Button> </Button>
{doc.abilities.destroy && ( {doc.abilities.destroy && (
<Button <Button
@@ -122,7 +122,7 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
icon={<span className="material-icons">delete</span>} icon={<span className="material-icons">delete</span>}
size="small" size="small"
> >
<Text $theme="primary">{t('Delete document')}</Text> {t('Delete document')}
</Button> </Button>
)} )}
</Box> </Box>

View File

@@ -152,7 +152,12 @@ export const ModalPDF = ({ onClose, doc }: ModalPDFProps) => {
size={ModalSize.MEDIUM} size={ModalSize.MEDIUM}
title={ title={
<Box $align="center" $gap="1rem"> <Box $align="center" $gap="1rem">
<Text className="material-icons" $size="3.5rem" $theme="primary"> <Text
className="material-icons"
$size="3.5rem"
$theme="primary"
$variation="600"
>
picture_as_pdf picture_as_pdf
</Text> </Text>
<Text as="h2" $size="h3" $margin="none" $theme="primary"> <Text as="h2" $size="h3" $margin="none" $theme="primary">

View File

@@ -1,6 +0,0 @@
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12 38C12 40.2 13.8 42 16 42H32C34.2 42 36 40.2 36 38V14H12V38ZM18.34 25.18C17.56 24.4 17.56 23.14 18.34 22.36C19.12 21.58 20.38 21.58 21.16 22.36L24 25.18L26.82 22.36C27.6 21.58 28.86 21.58 29.64 22.36C30.42 23.14 30.42 24.4 29.64 25.18L26.82 28L29.64 30.82C30.42 31.6 30.42 32.86 29.64 33.64C28.86 34.42 27.6 34.42 26.82 33.64L24 30.82L21.18 33.64C20.4 34.42 19.14 34.42 18.36 33.64C17.58 32.86 17.58 31.6 18.36 30.82L21.18 28L18.34 25.18ZM36 8H31L29.58 6.58C29.22 6.22 28.7 6 28.18 6H19.82C19.3 6 18.78 6.22 18.42 6.58L17 8H12C10.9 8 10 8.9 10 10C10 11.1 10.9 12 12 12H36C37.1 12 38 11.1 38 10C38 8.9 37.1 8 36 8Z"
fill="currentColor"
/>
</svg>

Before

Width:  |  Height:  |  Size: 742 B

View File

@@ -14,7 +14,6 @@ import useCunninghamTheme from '@/cunningham/useCunninghamTheme';
import { useRemoveDoc } from '../api/useRemoveDoc'; import { useRemoveDoc } from '../api/useRemoveDoc';
import IconDoc from '../assets/icon-doc.svg'; import IconDoc from '../assets/icon-doc.svg';
import IconRemove from '../assets/icon-trash.svg';
import { Doc } from '../types'; import { Doc } from '../types';
interface ModalRemoveDocProps { interface ModalRemoveDocProps {
@@ -73,7 +72,9 @@ export const ModalRemoveDoc = ({ onClose, doc }: ModalRemoveDocProps) => {
size={ModalSize.MEDIUM} size={ModalSize.MEDIUM}
title={ title={
<Box $align="center" $gap="1rem"> <Box $align="center" $gap="1rem">
<IconRemove width={48} color={colorsTokens()['primary-text']} /> <Text $isMaterialIcon $size="48px" $theme="primary" $variation="600">
delete_forever
</Text>
<Text as="h2" $size="h3" $margin="none"> <Text as="h2" $size="h3" $margin="none">
{t('Deleting the document "{{title}}"', { title: doc.title })} {t('Deleting the document "{{title}}"', { title: doc.title })}
</Text> </Text>

View File

@@ -1,7 +1,7 @@
import { t } from 'i18next'; import { t } from 'i18next';
import { createGlobalStyle } from 'styled-components'; import { createGlobalStyle } from 'styled-components';
import { Box, Card, SideModal, Text } from '@/components'; import { Box, Card, IconBG, SideModal, Text } from '@/components';
import { InvitationList } from '@/features/docs/members/invitation-list'; import { InvitationList } from '@/features/docs/members/invitation-list';
import { AddMembers } from '@/features/docs/members/members-add'; import { AddMembers } from '@/features/docs/members/members-add';
import { MemberList } from '@/features/docs/members/members-list'; import { MemberList } from '@/features/docs/members/members-list';
@@ -62,9 +62,12 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
$padding="tiny" $padding="tiny"
$gap="1rem" $gap="1rem"
> >
<Text $isMaterialIcon $size="48px" $theme="primary"> <IconBG
share $isMaterialIcon
</Text> $size="48px"
iconName="share"
$margin="none"
/>
<Box $align="flex-start"> <Box $align="flex-start">
<Text as="h3" $size="26px" $margin="none"> <Text as="h3" $size="26px" $margin="none">
{t('Share')} {t('Share')}

View File

@@ -35,13 +35,13 @@ export const VersionItem = ({
as="li" as="li"
$background={isActive ? colorsTokens()['primary-300'] : 'transparent'} $background={isActive ? colorsTokens()['primary-300'] : 'transparent'}
$css={` $css={`
border-left: 4px solid transparent; border-left: 4px solid transparent;
border-bottom: 1px solid ${colorsTokens()['primary-100']}; border-bottom: 1px solid ${colorsTokens()['primary-100']};
&:hover{ &:hover{
border-left: 4px solid ${colorsTokens()['primary-400']}; border-left: 4px solid ${colorsTokens()['primary-400']};
background: ${colorsTokens()['primary-300']}; background: ${colorsTokens()['primary-300']};
} }
`} `}
$hasTransition $hasTransition
$minWidth="13rem" $minWidth="13rem"
> >
@@ -54,10 +54,15 @@ export const VersionItem = ({
$width="100%" $width="100%"
> >
<Box $direction="row" $gap="0.5rem" $align="center"> <Box $direction="row" $gap="0.5rem" $align="center">
<Text $isMaterialIcon $size="24px" $theme="primary"> <Text
$isMaterialIcon
$size="24px"
$theme="primary"
$variation="600"
>
description description
</Text> </Text>
<Text $weight="bold" $theme="primary" $size="m"> <Text $weight="bold" $theme="primary" $size="m" $variation="600">
{text} {text}
</Text> </Text>
</Box> </Box>
@@ -81,7 +86,7 @@ export const VersionItem = ({
icon={<span className="material-icons">save</span>} icon={<span className="material-icons">save</span>}
size="small" size="small"
> >
<Text $theme="primary">{t('Restore the version')}</Text> {t('Restore the version')}
</Button> </Button>
</Box> </Box>
</DropButton> </DropButton>

View File

@@ -116,11 +116,7 @@ export const MemberItem = ({
<Button <Button
color="tertiary-text" color="tertiary-text"
icon={ icon={
<Text <Text $isMaterialIcon $color="inherit">
$isMaterialIcon
$theme={isNotAllowed ? 'greyscale' : 'primary'}
$variation={isNotAllowed ? '500' : 'text'}
>
delete delete
</Text> </Text>
} }

View File

@@ -62,9 +62,10 @@ export const Header = () => {
<Text <Text
$margin="none" $margin="none"
as="h2" as="h2"
$theme="primary" $color="#000091"
$zIndex={1} $zIndex={1}
$size="1.30rem" $size="1.30rem"
$css="font-family: 'Marianne'"
> >
{t('Docs')} {t('Docs')}
</Text> </Text>

View File

@@ -4,20 +4,30 @@ import Script from 'next/script';
import React from 'react'; import React from 'react';
import { createGlobalStyle } from 'styled-components'; import { createGlobalStyle } from 'styled-components';
import { useCunninghamTheme } from '@/cunningham';
const GaufreStyle = createGlobalStyle` const GaufreStyle = createGlobalStyle`
.lasuite-gaufre-btn{ .lasuite-gaufre-btn{
box-shadow: inset 0 0 0 0 !important; box-shadow: inset 0 0 0 0 !important;
} }
`; `;
export const LaGaufre = () => ( export const LaGaufre = () => {
<> const { componentTokens } = useCunninghamTheme();
<Script
src="https://integration.lasuite.numerique.gouv.fr/api/v1/gaufre.js" if (!componentTokens()['la-gauffre'].activated) {
strategy="lazyOnload" return null;
id="lasuite-gaufre-script" }
/>
<GaufreStyle /> return (
<Gaufre variant="small" /> <>
</> <Script
); src="https://integration.lasuite.numerique.gouv.fr/api/v1/gaufre.js"
strategy="lazyOnload"
id="lasuite-gaufre-script"
/>
<GaufreStyle />
<Gaufre variant="small" />
</>
);
};

View File

@@ -1,5 +1,4 @@
import { Select } from '@openfun/cunningham-react'; import { Select } from '@openfun/cunningham-react';
import Image from 'next/image';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -7,8 +6,6 @@ import styled from 'styled-components';
import { Box, Text } from '@/components/'; import { Box, Text } from '@/components/';
import { LANGUAGES_ALLOWED } from '@/i18n/conf'; import { LANGUAGES_ALLOWED } from '@/i18n/conf';
import IconLanguage from './assets/icon-language.svg?url';
const SelectStyled = styled(Select)<{ $isSmall?: boolean }>` const SelectStyled = styled(Select)<{ $isSmall?: boolean }>`
flex-shrink: 0; flex-shrink: 0;
width: auto; width: auto;
@@ -49,12 +46,16 @@ export const LanguagePicker = () => {
$gap="0.7rem" $gap="0.7rem"
$align="center" $align="center"
> >
<Image priority src={IconLanguage} alt={t('Language Icon')} /> <Text $isMaterialIcon $size="1rem" $theme="primary" $variation="600">
<Text $theme="primary">{LANGUAGES_ALLOWED[lang]}</Text> translate
</Text>
<Text $theme="primary" $variation="600">
{LANGUAGES_ALLOWED[lang]}
</Text>
</Box> </Box>
), ),
})); }));
}, [languages, t]); }, [languages]);
return ( return (
<SelectStyled <SelectStyled

View File

@@ -1,14 +0,0 @@
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.334 6.66683L15.2673 14.0002H13.8307L13.03 12.0002H10.3033L9.50398 14.0002H8.06798L11.0007 6.66683H12.334ZM6.66732 1.3335V2.66683H10.6673V4.00016H9.35532C8.84106 5.54821 8.0203 6.97684 6.94198 8.20083C7.42285 8.6299 7.94444 9.01104 8.49932 9.33883L7.99865 10.5908C7.28233 10.1846 6.61238 9.70149 6.00065 9.15016C4.80971 10.228 3.39934 11.035 1.86665 11.5155L1.50932 10.2295C2.82254 9.81077 4.03266 9.11972 5.06065 8.2015C4.29978 7.34012 3.66603 6.37434 3.17865 5.3335H4.67198C5.04355 6.0194 5.4891 6.66257 6.00065 7.2515C6.83406 6.2909 7.49085 5.19037 7.94065 4.00083L1.33398 4.00016V2.66683H5.33398V1.3335H6.66732ZM11.6673 8.59016L10.836 10.6668H12.4973L11.6673 8.59016Z"
fill="#000091"
/>
</svg>

Before

Width:  |  Height:  |  Size: 877 B