💥(frontend) upgrade to ui-kit v2

Upgrade Docs to Ui-Kit v2 and apply new color
scheme from LaSuite design system.
This commit will probably create breaking changes if
user has custom styles applied to their docs.
This commit is contained in:
Anthony LC
2025-11-26 11:30:49 +01:00
parent 785c9b21cf
commit 29104dfe2d
110 changed files with 9537 additions and 3249 deletions

View File

@@ -14,6 +14,7 @@ and this project adheres to
### Changed ### Changed
- ⚡️(sw) stop to cache external resources likes videos #1655 - ⚡️(sw) stop to cache external resources likes videos #1655
- 💥(frontend) upgrade to ui-kit v2
### Fixed ### Fixed

View File

@@ -1,6 +1,6 @@
import { expect, test } from '@playwright/test'; import { expect, test } from '@playwright/test';
import { createDoc } from './utils-common'; import { createDoc, goToGridDoc, verifyDocName } from './utils-common';
test.describe('Left panel desktop', () => { test.describe('Left panel desktop', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
@@ -10,8 +10,12 @@ test.describe('Left panel desktop', () => {
test('checks all the elements are visible', async ({ page }) => { test('checks all the elements are visible', async ({ page }) => {
await expect(page.getByTestId('left-panel-desktop')).toBeVisible(); await expect(page.getByTestId('left-panel-desktop')).toBeVisible();
await expect(page.getByTestId('left-panel-mobile')).toBeHidden(); await expect(page.getByTestId('left-panel-mobile')).toBeHidden();
await expect(page.getByTestId('home-button')).toBeVisible(); await expect(page.getByTestId('home-button')).toBeHidden();
await expect(page.getByTestId('new-doc-button')).toBeVisible(); await expect(page.getByTestId('new-doc-button')).toBeVisible();
await goToGridDoc(page);
await expect(page.getByTestId('home-button')).toBeVisible();
}); });
test('checks resize handle is present and functional on document page', async ({ test('checks resize handle is present and functional on document page', async ({
@@ -88,6 +92,9 @@ test.describe('Left panel mobile', () => {
await expect(languageButton).not.toBeInViewport(); await expect(languageButton).not.toBeInViewport();
await expect(logoutButton).not.toBeInViewport(); await expect(logoutButton).not.toBeInViewport();
const title = await goToGridDoc(page);
await verifyDocName(page, title);
await header.getByLabel('Open the header menu').click(); await header.getByLabel('Open the header menu').click();
await expect(page.getByTestId('left-panel-mobile')).toBeInViewport(); await expect(page.getByTestId('left-panel-mobile')).toBeInViewport();

View File

@@ -1,57 +1,25 @@
import { cunninghamConfig as tokens } from '@gouvfr-lasuite/ui-kit'; import { cunninghamConfig as tokens } from '@gouvfr-lasuite/ui-kit';
import { defaultTokens } from '@openfun/cunningham-react';
import merge from 'lodash/merge';
const customColors = { // Uikit does not provide the full list of tokens.
'primary-action': '#1212FF', // To be able to override correctly, we need to merge with the default tokens.
'primary-bg': '#FAFAFA', let mergedColors = merge(
'primary-focus': '#0A76F6', defaultTokens.globals.colors,
'secondary-icon': 'var(--c--theme--colors--primary-text)', tokens.themes.default.globals.colors,
'blue-400': '#7AB1E8', );
'blue-500': '#417DC4',
'blue-600': '#3558A2', mergedColors = {
'brown-400': '#E6BE92', ...mergedColors,
'brown-500': '#BD987A', 'logo-1': '#2845C1',
'brown-600': '#745B47',
'cyan-400': '#34BAB5',
'cyan-500': '#009099',
'cyan-600': '#006A6F',
'gold-400': '#FFCA00',
'gold-500': '#C3992A',
'gold-600': '#695240',
'green-400': '#34CB6A',
'green-500': '#00A95F',
'green-600': '#297254',
'olive-400': '#99C221',
'olive-500': '#68A532',
'olive-600': '#447049',
'orange-400': '#FF732C',
'orange-500': '#E4794A',
'orange-600': '#755348',
'pink-400': '#FFB7AE',
'pink-500': '#E18B76',
'pink-600': '#8D533E',
'purple-400': '#CE70CC',
'purple-500': '#A558A0',
'purple-600': '#6E445A',
'yellow-400': '#D8C634',
'yellow-500': '#B7A73F',
'yellow-600': '#66673D',
}; };
tokens.themes.default.theme = { tokens.themes.default.globals = {
...tokens.themes.default.theme, ...tokens.themes.default.globals,
...{ ...{
logo: { colors: mergedColors,
src: '',
alt: '',
widthHeader: '',
widthFooter: '',
},
colors: {
...tokens.themes.default.theme.colors,
...customColors,
},
font: { font: {
...tokens.themes.default.theme.font, ...tokens.themes.default.globals.font,
families: { families: {
base: 'sans-serif', base: 'sans-serif',
accent: 'sans-serif', accent: 'sans-serif',
@@ -63,39 +31,24 @@ tokens.themes.default.theme = {
tokens.themes.default.components = { tokens.themes.default.components = {
...tokens.themes.default.components, ...tokens.themes.default.components,
...{ ...{
logo: {
src: '',
alt: '',
widthHeader: '',
widthFooter: '',
},
'la-gaufre': false, 'la-gaufre': false,
'home-proconnect': false, 'home-proconnect': false,
'image-system-filter': '',
favicon: { favicon: {
ico: '/assets/favicon-light.ico',
'png-light': '/assets/favicon-light.png', 'png-light': '/assets/favicon-light.png',
'png-dark': '/assets/favicon-dark.png', 'png-dark': '/assets/favicon-dark.png',
}, },
button: {
...tokens.themes.default.components.button,
primary: {
...tokens.themes.default.components.button.primary,
...{
'background--disabled': 'var(--c--theme--colors--greyscale-100)',
},
disabled: 'var(--c--theme--colors--greyscale-400)',
},
},
}, },
}; };
const dsfrTheme = { const dsfrTheme = {
dsfr: { dsfr: {
theme: { globals: {
colors: {
'secondary-icon': '#C9191E',
},
logo: {
src: '/assets/logo-gouv.svg',
widthHeader: '110px',
widthFooter: '220px',
alt: 'Gouvernement Logo',
},
font: { font: {
families: { families: {
base: 'Marianne, Inter, Roboto Flex Variable, sans-serif', base: 'Marianne, Inter, Roboto Flex Variable, sans-serif',
@@ -104,6 +57,12 @@ const dsfrTheme = {
}, },
}, },
components: { components: {
logo: {
src: '/assets/logo-gouv.svg',
widthHeader: '110px',
widthFooter: '220px',
alt: 'Gouvernement Logo',
},
'la-gaufre': true, 'la-gaufre': true,
'home-proconnect': true, 'home-proconnect': true,
favicon: { favicon: {
@@ -117,131 +76,296 @@ const dsfrTheme = {
const genericTheme = { const genericTheme = {
generic: { generic: {
theme: { globals: {
colors: { colors: {
'primary-action': '#206EBD', 'brand-050': '#EEF1FA',
'primary-focus': '#1E64BF', 'brand-100': '#DDE2F5',
'primary-text': '#2E2C28', 'brand-150': '#CED3F1',
'primary-050': '#F8F8F7', 'brand-200': '#BEC5F0',
'primary-100': '#F0EFEC', 'brand-250': '#AFB5F1',
'primary-150': '#F4F4FD', 'brand-300': '#A0A5F6',
'primary-200': '#E8E7E4', 'brand-350': '#8F94FD',
'primary-300': '#CFCDC9', 'brand-400': '#8184FC',
'primary-400': '#979592', 'brand-450': '#7576EE',
'primary-500': '#82807D', 'brand-500': '#6969DF',
'primary-600': '#3F3D39', 'brand-550': '#5E5CD0',
'primary-700': '#2E2C28', 'brand-600': '#534FC2',
'primary-800': '#302E29', 'brand-650': '#4844AD',
'primary-900': '#282622', 'brand-700': '#3E3B98',
'primary-950': '#201F1C', 'brand-750': '#36347D',
'secondary-text': '#fff', 'brand-800': '#2D2F5F',
'secondary-50': '#F4F7FA', 'brand-850': '#262848',
'secondary-100': '#D7E3EE', 'brand-900': '#1C1E32',
'secondary-200': '#B8CCE1', 'brand-950': '#11131F',
'secondary-300': '#99B4D3', 'gray-000': '#FFFFFF',
'secondary-400': '#7595BE', 'gray-025': '#F8F8F9',
'secondary-500': '#5874A0', 'gray-050': '#F0F0F3',
'secondary-600': '#3A5383', 'gray-100': '#E2E2EA',
'secondary-700': '#1E3462', 'gray-150': '#D3D4E0',
'secondary-800': '#091B41', 'gray-200': '#C5C6D5',
'secondary-900': '#08183B', 'gray-250': '#B7B7CB',
'secondary-950': '#071636', 'gray-300': '#A9A9BF',
'greyscale-text': '#3C3B38', 'gray-350': '#9C9CB2',
'greyscale-000': '#fff', 'gray-400': '#8F8FA4',
'greyscale-050': '#F8F7F7', 'gray-450': '#828297',
'greyscale-100': '#F3F3F2', 'gray-500': '#75758A',
'greyscale-200': '#ECEBEA', 'gray-550': '#69697D',
'greyscale-250': '#E4E3E2', 'gray-600': '#5D5D70',
'greyscale-300': '#D3D2CF', 'gray-650': '#515164',
'greyscale-350': '#eee', 'gray-700': '#454558',
'greyscale-400': '#96948E', 'gray-750': '#3A3A4C',
'greyscale-500': '#817E77', 'gray-800': '#2F303D',
'greyscale-600': '#6A6862', 'gray-850': '#25252F',
'greyscale-700': '#3C3B38', 'gray-900': '#1B1B23',
'greyscale-750': '#383632', 'gray-950': '#111114',
'greyscale-800': '#2D2B27', 'gray-1000': '#000000',
'greyscale-900': '#262522', 'info-050': '#EAF2F9',
'greyscale-950': '#201F1C', 'info-100': '#D5E4F3',
'greyscale-1000': '#181714', 'info-150': '#BFD7F0',
'success-text': '#234935', 'info-200': '#A7CAEE',
'success-50': '#F3FBF5', 'info-250': '#8DBDEF',
'success-100': '#E4F7EA', 'info-300': '#6EB0F2',
'success-200': '#CAEED4', 'info-350': '#50A2F5',
'success-300': '#A0E0B5', 'info-400': '#3593F4',
'success-400': '#6CC88C', 'info-450': '#1185ED',
'success-500': '#6CC88C', 'info-500': '#0077DE',
'success-600': '#358D5C', 'info-550': '#0069CF',
'success-700': '#2D704B', 'info-600': '#005BC0',
'success-800': '#28583F', 'info-650': '#0D4EAA',
'success-900': '#234935', 'info-700': '#124394',
'success-950': '#0F281B', 'info-750': '#163878',
'info-text': '#212445', 'info-800': '#192F5A',
'info-50': '#F2F6FB', 'info-850': '#192541',
'info-100': '#E2E9F5', 'info-900': '#141B2D',
'info-200': '#CCD8EE', 'info-950': '#0C111C',
'info-300': '#A9C0E3', 'success-050': '#E8F1EA',
'info-400': '#809DD4', 'success-100': '#CFE4D4',
'info-500': '#617BC7', 'success-150': '#BAD9C1',
'info-600': '#4A5CBF', 'success-200': '#A2CFAD',
'info-700': '#3E49B2', 'success-250': '#86C597',
'info-800': '#353C8F', 'success-300': '#6CBA83',
'info-900': '#303771', 'success-350': '#4FB070',
'info-950': '#212445', 'success-400': '#40A363',
'warning-text': '#D97C3A', 'success-450': '#309556',
'warning-50': '#FDF7F1', 'success-500': '#1E884A',
'warning-100': '#FBEDDC', 'success-550': '#027B3E',
'warning-200': '#F5D9B9', 'success-600': '#016D31',
'warning-300': '#EDBE8C', 'success-650': '#006024',
'warning-400': '#E2985C', 'success-700': '#005317',
'warning-500': '#D97C3A', 'success-750': '#0D4511',
'warning-600': '#C96330', 'success-800': '#11380E',
'warning-700': '#A34B32', 'success-850': '#132A11',
'warning-800': '#813B2C', 'success-900': '#101E0F',
'warning-900': '#693327', 'success-950': '#091209',
'warning-950': '#381713', 'warning-050': '#F8F0E9',
'danger-action': '#C0182A', 'warning-100': '#F1E0D3',
'danger-text': '#FFF', 'warning-150': '#ECD0BC',
'danger-050': '#FDF5F4', 'warning-200': '#E8C0A4',
'danger-100': '#FBEBE8', 'warning-250': '#E8AE8A',
'danger-200': '#F9E0DC', 'warning-300': '#EB9970',
'danger-300': '#F3C3BD', 'warning-350': '#E98456',
'danger-400': '#E26552', 'warning-400': '#E57036',
'danger-500': '#C91F00', 'warning-450': '#DA5E18',
'danger-600': '#A71901', 'warning-500': '#CB5000',
'danger-700': '#562C2B', 'warning-550': '#BC4200',
'danger-800': '#392425', 'warning-600': '#AD3300',
'danger-900': '#311F20', 'warning-650': '#9E2300',
'danger-950': '#2A191A', 'warning-700': '#882011',
'blue-400': '#8BAECC', 'warning-750': '#731E16',
'blue-500': '#567AA2', 'warning-800': '#58201A',
'blue-600': '#455784', 'warning-850': '#401D18',
'brown-400': '#E4C090', 'warning-900': '#2E1714',
'brown-500': '#BA9977', 'warning-950': '#1D0F0D',
'brown-600': '#735C45', 'error-050': '#F9EFEC',
'cyan-400': '#5CBEC9', 'error-100': '#F4DFD9',
'cyan-500': '#43A1B3', 'error-150': '#F0CEC6',
'cyan-600': '#39809B', 'error-200': '#EEBCB2',
'gold-400': '#ECBF50', 'error-250': '#EEA99D',
'gold-500': '#DFA038', 'error-300': '#EF9486',
'gold-600': '#C17B31', 'error-350': '#F37C6E',
'green-400': '#5DBD9A', 'error-400': '#F65F53',
'green-500': '#3AA183', 'error-450': '#F0463D',
'green-600': '#2A816D', 'error-500': '#E82322',
'olive-400': '#AFD662', 'error-550': '#D7010E',
'olive-500': '#90BB4B', 'error-600': '#C00100',
'olive-600': '#6E9441', 'error-650': '#AA0000',
'orange-400': '#E2985C', 'error-700': '#910C06',
'orange-500': '#D97C3A', 'error-750': '#731E16',
'orange-600': '#C96330', 'error-800': '#58201A',
'pink-400': '#BE8FC8', 'error-850': '#401D18',
'pink-500': '#A563B1', 'error-900': '#2E1714',
'pink-600': '#8B44A5', 'error-950': '#1D0F0D',
'purple-400': '#BE8FC8', 'red-050': '#FAEFEE',
'purple-500': '#A563B1', 'red-100': '#F4DEDD',
'purple-600': '#8B44A5', 'red-150': '#F1CDCB',
'yellow-400': '#EDC947', 'red-200': '#EFBBBA',
'yellow-500': '#DBB13A', 'red-250': '#EEA8A8',
'yellow-600': '#B88A34', 'red-300': '#F09394',
'red-350': '#F37B7E',
'red-400': '#EF6569',
'red-450': '#E94A55',
'red-500': '#DA3B49',
'red-550': '#CA2A3C',
'red-600': '#BB1330',
'red-650': '#A90021',
'red-700': '#910A13',
'red-750': '#731E16',
'red-800': '#58201A',
'red-850': '#411D18',
'red-900': '#2E1714',
'red-950': '#1D0F0D',
'orange-050': '#F8F0E9',
'orange-100': '#F1E0D3',
'orange-150': '#ECD0BD',
'orange-200': '#EABFA6',
'orange-250': '#EBAC90',
'orange-300': '#EC9772',
'orange-350': '#E5845A',
'orange-400': '#D6774D',
'orange-450': '#C86A40',
'orange-500': '#B95D33',
'orange-550': '#AB5025',
'orange-600': '#9D4315',
'orange-650': '#8F3600',
'orange-700': '#812900',
'orange-750': '#6C2511',
'orange-800': '#572017',
'orange-850': '#401D18',
'orange-900': '#2E1714',
'orange-950': '#1D0F0D',
'brown-050': '#F6F0E8',
'brown-100': '#F1E0D3',
'brown-150': '#EBD0BA',
'brown-200': '#E2C0A6',
'brown-250': '#D4B398',
'brown-300': '#C6A58B',
'brown-350': '#B8987E',
'brown-400': '#AA8B71',
'brown-450': '#9D7E65',
'brown-500': '#8F7158',
'brown-550': '#82654C',
'brown-600': '#765841',
'brown-650': '#694C35',
'brown-700': '#5D412A',
'brown-750': '#51361E',
'brown-800': '#452A13',
'brown-850': '#392008',
'brown-900': '#29180A',
'brown-950': '#1B0F08',
'yellow-050': '#F3F0E7',
'yellow-100': '#E9E2CF',
'yellow-150': '#E1D4B7',
'yellow-200': '#D9C599',
'yellow-250': '#D2B677',
'yellow-300': '#CAA756',
'yellow-350': '#C2972E',
'yellow-400': '#B98900',
'yellow-450': '#AB7B00',
'yellow-500': '#9D6E00',
'yellow-550': '#916100',
'yellow-600': '#855400',
'yellow-650': '#784700',
'yellow-700': '#6C3A00',
'yellow-750': '#5F2E00',
'yellow-800': '#512302',
'yellow-850': '#3E1D10',
'yellow-900': '#2D1711',
'yellow-950': '#1D0F0D',
'green-050': '#E6F1E9',
'green-100': '#CFE4D5',
'green-150': '#B8D8C1',
'green-200': '#A0CFAE',
'green-250': '#84C59A',
'green-300': '#65BA86',
'green-350': '#45B173',
'green-400': '#23A562',
'green-450': '#029755',
'green-500': '#008948',
'green-550': '#017B3B',
'green-600': '#006E2E',
'green-650': '#006022',
'green-700': '#005314',
'green-750': '#0D4510',
'green-800': '#11380E',
'green-850': '#132A11',
'green-900': '#101E0F',
'green-950': '#091209',
'blue1-050': '#EBF1F9',
'blue1-100': '#D6E4F4',
'blue1-150': '#C1D7F0',
'blue1-200': '#AACAEF',
'blue1-250': '#8FBCEF',
'blue1-300': '#7CAFEB',
'blue1-350': '#68A1E4',
'blue1-400': '#5B94D6',
'blue1-450': '#4E86C7',
'blue1-500': '#4279B9',
'blue1-550': '#356CAC',
'blue1-600': '#28609E',
'blue1-650': '#1B5390',
'blue1-700': '#0B4783',
'blue1-750': '#0F3C6E',
'blue1-800': '#133059',
'blue1-850': '#152641',
'blue1-900': '#121C2D',
'blue1-950': '#0B111C',
'blue2-050': '#E7F3F4',
'blue2-100': '#CEE7E9',
'blue2-150': '#B2DCE0',
'blue2-200': '#91D1D7',
'blue2-250': '#68C7D0',
'blue2-300': '#43BBC5',
'blue2-350': '#00AFBA',
'blue2-400': '#01A0AA',
'blue2-450': '#00929D',
'blue2-500': '#00848F',
'blue2-550': '#007682',
'blue2-600': '#016874',
'blue2-650': '#005B67',
'blue2-700': '#004E5A',
'blue2-750': '#00424E',
'blue2-800': '#003642',
'blue2-850': '#002A38',
'blue2-900': '#061E28',
'blue2-950': '#071219',
'purple-050': '#F7F0F6',
'purple-100': '#EEE0EE',
'purple-150': '#E7D1E7',
'purple-200': '#DBBFE4',
'purple-250': '#D3AEE2',
'purple-300': '#CB99E1',
'purple-350': '#C188D9',
'purple-400': '#B47BCB',
'purple-450': '#A66EBD',
'purple-500': '#9961AF',
'purple-550': '#8B55A1',
'purple-600': '#7E4894',
'purple-650': '#723C87',
'purple-700': '#633376',
'purple-750': '#552A65',
'purple-800': '#452551',
'purple-850': '#35213D',
'purple-900': '#261A2C',
'purple-950': '#17111C',
'pink-050': '#F8EFF4',
'pink-100': '#F0DFEA',
'pink-150': '#EACEDF',
'pink-200': '#E9BBD1',
'pink-250': '#E9A7C2',
'pink-300': '#E095B4',
'pink-350': '#D685A8',
'pink-400': '#C7799B',
'pink-450': '#B86C8D',
'pink-500': '#AA5F80',
'pink-550': '#9C5374',
'pink-600': '#8E4767',
'pink-650': '#813B5B',
'pink-700': '#732E4F',
'pink-750': '#632643',
'pink-800': '#521F38',
'pink-850': '#3E1C2B',
'pink-900': '#2D171F',
'pink-950': '#1C0E12',
}, },
font: { font: {
families: { families: {
@@ -250,18 +374,6 @@ const genericTheme = {
}, },
}, },
}, },
components: {
button: {
primary: {
background: {
'color-hover': 'var(--c--theme--colors--primary-focus)',
'color-active': 'var(--c--theme--colors--primary-focus)',
'color-focus': 'var(--c--theme--colors--primary-focus)',
},
},
},
'image-system-filter': 'saturate(0.2)',
},
}, },
}; };

View File

@@ -35,11 +35,11 @@
"@fontsource-variable/material-symbols-outlined": "5.2.28", "@fontsource-variable/material-symbols-outlined": "5.2.28",
"@fontsource/material-icons": "5.2.7", "@fontsource/material-icons": "5.2.7",
"@gouvfr-lasuite/integration": "1.0.3", "@gouvfr-lasuite/integration": "1.0.3",
"@gouvfr-lasuite/ui-kit": "0.16.2", "@gouvfr-lasuite/ui-kit": "0.18.0",
"@hocuspocus/provider": "3.4.0", "@hocuspocus/provider": "3.4.0",
"@mantine/core": "8.3.6", "@mantine/core": "8.3.6",
"@mantine/hooks": "8.3.6", "@mantine/hooks": "8.3.6",
"@openfun/cunningham-react": "3.2.3", "@openfun/cunningham-react": "4.0.0",
"@react-pdf/renderer": "4.3.1", "@react-pdf/renderer": "4.3.1",
"@sentry/nextjs": "10.27.0", "@sentry/nextjs": "10.27.0",
"@tanstack/react-query": "5.90.6", "@tanstack/react-query": "5.90.6",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,6 +14,7 @@ export interface BoxProps {
as?: HTMLElementType; as?: HTMLElementType;
$align?: CSSProperties['alignItems']; $align?: CSSProperties['alignItems'];
$background?: CSSProperties['background']; $background?: CSSProperties['background'];
$border?: CSSProperties['border'];
$color?: CSSProperties['color']; $color?: CSSProperties['color'];
$css?: string | RuleSet<object>; $css?: string | RuleSet<object>;
$cursor?: CSSProperties['cursor']; $cursor?: CSSProperties['cursor'];
@@ -36,41 +37,34 @@ export interface BoxProps {
$position?: CSSProperties['position']; $position?: CSSProperties['position'];
$radius?: CSSProperties['borderRadius']; $radius?: CSSProperties['borderRadius'];
$shrink?: CSSProperties['flexShrink']; $shrink?: CSSProperties['flexShrink'];
$transition?: CSSProperties['transition'];
$width?: CSSProperties['width'];
$zIndex?: CSSProperties['zIndex'];
$wrap?: CSSProperties['flexWrap'];
// Theming props
$layer?: 'background' | 'content' | 'border';
$theme?: $theme?:
| 'primary' | 'brand'
| 'primary-text' | 'error'
| 'secondary' | 'gray'
| 'secondary-text'
| 'info' | 'info'
| 'success' | 'success'
| 'warning' | 'warning'
| 'danger' | 'neutral'
| 'greyscale'; | 'contextual'
$transition?: CSSProperties['transition']; | 'disabled'
$variation?: | (string & {});
| 'text' $scope?: 'surface' | 'semantic' | 'palette' | (string & {});
| '000' $variation?: 'primary' | 'secondary' | 'tertiary' | (string & {});
| '100' $withThemeBG?: boolean;
| '200' $withThemeBorder?: boolean;
| '300' $withThemeInherited?: boolean;
| '400'
| '500'
| '600'
| '700'
| '800'
| '900'
| '1000';
$width?: CSSProperties['width'];
$wrap?: CSSProperties['flexWrap'];
$zIndex?: CSSProperties['zIndex'];
} }
export type BoxType = ComponentPropsWithRef<typeof Box>; export type BoxType = ComponentPropsWithRef<typeof Box>;
export const Box = styled('div')<BoxProps>` export const Box = styled('div')<BoxProps>`
${({ $align }) => $align && `align-items: ${$align};`} ${({ $align }) => $align && `align-items: ${$align};`}
${({ $background }) => $background && `background: ${$background};`}
${({ $color }) => $color && `color: ${$color};`}
${({ $cursor }) => $cursor && `cursor: ${$cursor};`} ${({ $cursor }) => $cursor && `cursor: ${$cursor};`}
${({ $direction }) => `flex-direction: ${$direction || 'column'};`} ${({ $direction }) => `flex-direction: ${$direction || 'column'};`}
${({ $display, as }) => ${({ $display, as }) =>
@@ -80,9 +74,9 @@ export const Box = styled('div')<BoxProps>`
${({ $height }) => $height && `height: ${$height};`} ${({ $height }) => $height && `height: ${$height};`}
${({ $hasTransition }) => ${({ $hasTransition }) =>
$hasTransition && $hasTransition === 'slow' $hasTransition && $hasTransition === 'slow'
? `transition: all 0.5s ease-in-out;` ? `transition: all 0.5s var(--c--globals--transitions--ease-out);`
: $hasTransition : $hasTransition
? `transition: all 0.3s ease-in-out;` ? `transition: all var(--c--globals--transitions--duration) var(--c--globals--transitions--ease-out);`
: ''} : ''}
${({ $justify }) => $justify && `justify-content: ${$justify};`} ${({ $justify }) => $justify && `justify-content: ${$justify};`}
${({ $margin }) => $margin && stylesMargin($margin)} ${({ $margin }) => $margin && stylesMargin($margin)}
@@ -96,11 +90,85 @@ export const Box = styled('div')<BoxProps>`
${({ $position }) => $position && `position: ${$position};`} ${({ $position }) => $position && `position: ${$position};`}
${({ $radius }) => $radius && `border-radius: ${$radius};`} ${({ $radius }) => $radius && `border-radius: ${$radius};`}
${({ $shrink }) => $shrink && `flex-shrink: ${$shrink};`} ${({ $shrink }) => $shrink && `flex-shrink: ${$shrink};`}
${({ $theme, $variation }) => { ${({
if (!$theme || !$variation) { $layer = 'border',
$theme = 'brand',
$variation = 'primary',
$scope = 'semantic',
$border,
$withThemeBorder,
$withThemeInherited,
}) => {
if ($border) {
return `border: ${$border};`;
}
if (!$layer || !$scope || !$theme || !$withThemeBorder) {
return ''; return '';
} }
return `color: var(--c--theme--colors--${$theme}-${$variation});`;
if ($withThemeInherited) {
return `border: inherit;`;
}
return `border: 1px solid var(--c--contextuals--${$layer}--${$scope}${$theme ? `--${$theme}` : ''}${$variation ? `--${$variation}` : ''});`;
}}
${({
$layer = 'background',
$theme = 'brand',
$variation = 'primary',
$scope = 'semantic',
$background,
$withThemeBG,
$withThemeInherited,
}) => {
if ($background) {
return `background: ${$background};`;
}
if (!$layer || !$scope || !$theme || !$withThemeBG) {
return '';
}
if ($withThemeInherited) {
return `background: inherit;`;
}
return `background: var(--c--contextuals--${$layer}--${$scope}${$theme ? `--${$theme}` : ''}${$variation ? `--${$variation}` : ''});`;
}}
${({
$layer = 'content',
$theme = 'neutral',
$variation = 'primary',
$scope = 'semantic',
$color,
$withThemeBG,
$withThemeInherited,
}) => {
if ($color) {
return `color: ${$color};`;
}
if (!$layer || !$scope) {
return '';
}
// There is a special case when primary with background
if (
$withThemeBG &&
$layer === 'content' &&
$scope === 'semantic' &&
$variation === 'primary' &&
$theme
) {
$variation = `on-${$theme}`;
}
if ($withThemeInherited) {
return `color: inherit;`;
}
return `color: var(--c--contextuals--${$layer}--${$scope}${$theme ? `--${$theme}` : ''}${$variation ? `--${$variation}` : ''});`;
}} }}
${({ $transition }) => $transition && `transition: ${$transition};`} ${({ $transition }) => $transition && `transition: ${$transition};`}
${({ $width }) => $width && `width: ${$width};`} ${({ $width }) => $width && `width: ${$width};`}
@@ -121,7 +189,7 @@ export const Box = styled('div')<BoxProps>`
return ( return (
effect && effect &&
` `
transition: all 0.3s ease-in-out; transition: all var(--c--globals--transitions--duration) var(--c--globals--transitions--ease-out);
${effect} ${effect}
` `
); );

View File

@@ -24,8 +24,8 @@ export type BoxButtonType = BoxType & {
*/ */
const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>( const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>(
({ $css, ...props }, ref) => { ({ $css, ...props }, ref) => {
const theme = props.$theme || 'greyscale'; const theme = props.$theme || 'gray';
const variation = props.$variation || '400'; const variation = props.$variation || 'primary';
return ( return (
<Box <Box
@@ -40,15 +40,14 @@ const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>(
border: none; border: none;
outline: none; outline: none;
font-family: inherit; font-family: inherit;
color: ${props.disabled color: ${props.disabled &&
? `var(--c--theme--colors--${theme}-400) !important` `var(--c--contextuals--content--semantic--disabled--primary)`};
: `inherit`};
&:focus-visible { &:focus-visible {
transition: none; transition: none;
outline: 2px solid var(--c--theme--colors--${theme}-${variation}); outline: 2px solid
var(--c--contextuals--content--semantic--${theme}--${variation});
border-radius: 1px; border-radius: 1px;
outline-offset: 4px; outline-offset: var(--c--globals--spacings--st);
} }
${$css || ''} ${$css || ''}
`} `}

View File

@@ -1,27 +1,23 @@
import { PropsWithChildren } from 'react'; import { PropsWithChildren } from 'react';
import { css } from 'styled-components';
import { useCunninghamTheme } from '@/cunningham';
import { Box, BoxType } from '.'; import { Box, BoxType } from '.';
export const Card = ({ export const Card = ({
children, children,
className, className,
$css,
...props ...props
}: PropsWithChildren<BoxType>) => { }: PropsWithChildren<BoxType>) => {
const { colorsTokens } = useCunninghamTheme();
return ( return (
<Box <Box
role="region"
$withThemeBG
$withThemeBorder
className={`--docs--card ${className || ''}`} className={`--docs--card ${className || ''}`}
$background="white" $radius="var(--c--globals--spacings--st)"
$radius="4px" $padding={{ horizontal: 'xs', vertical: '3xs' }}
$css={css` $scope={props.$theme ? props.$scope || 'semantic' : 'surface'}
border: 1px solid ${colorsTokens['greyscale-200']}; $theme={props.$theme || 'primary'}
${$css} $variation={props.$theme ? props.$variation || 'tertiary' : ''}
`}
{...props} {...props}
> >
{children} {children}

View File

@@ -14,10 +14,11 @@ import { BoxProps } from './Box';
const StyledPopover = styled(Popover)` const StyledPopover = styled(Popover)`
background-color: white; background-color: white;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 0 6px 0 rgba(0, 0, 145, 0.1);
border: 1px solid #dddddd; border: 1px solid var(--c--contextuals--border--surface--primary);
transition: opacity 0.2s ease-in-out; transition: opacity var(--c--globals--transitions--duration)
var(--c--globals--transitions--ease-out);
`; `;
interface StyledButtonProps { interface StyledButtonProps {
@@ -28,18 +29,22 @@ const StyledButton = styled(Button)<StyledButtonProps>`
border: none; border: none;
background: none; background: none;
outline: none; outline: none;
font-weight: 500; font-weight: var(--c--components--button--font-weight);
font-size: 0.938rem; font-size: var(--c--components--button--medium-font-size);
padding: 0; padding: var(--c--globals--spacings--0);
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
color: var(--c--contextuals--content--semantic--brand--tertiary);
&:hover { &:hover {
background-color: var( background-color: var(
--c--components--button--primary-text--background--color-hover --c--contextuals--background--semantic--contextual--primary
); );
} }
&:focus-visible { &:focus-visible {
box-shadow: 0 0 0 2px var(--c--theme--colors--primary-400); box-shadow: 0 0 0 2px var(--c--globals--colors--brand-400);
border-radius: 4px; background-color: var(
--c--contextuals--background--semantic--brand--tertiary-hover
);
border-radius: var(--c--globals--spacings--st);
} }
${({ $css }) => $css}; ${({ $css }) => $css};
`; `;

View File

@@ -13,7 +13,7 @@ export const Icon = ({
iconName, iconName,
disabled, disabled,
variant = 'outlined', variant = 'outlined',
$variation = 'text', $theme = 'neutral',
...textProps ...textProps
}: IconProps) => { }: IconProps) => {
const hasLabel = 'aria-label' in textProps || 'aria-labelledby' in textProps; const hasLabel = 'aria-label' in textProps || 'aria-labelledby' in textProps;
@@ -28,7 +28,7 @@ export const Icon = ({
'material-icons': variant === 'outlined', 'material-icons': variant === 'outlined',
'material-symbols-outlined': variant === 'symbols-outlined', 'material-symbols-outlined': variant === 'symbols-outlined',
})} })}
$variation={disabled ? '300' : $variation} $theme={disabled ? 'disabled' : $theme}
aria-disabled={disabled} aria-disabled={disabled}
{...textProps} {...textProps}
> >

View File

@@ -39,7 +39,8 @@ export const InfiniteScroll = ({
{!isLoading && hasMore && ( {!isLoading && hasMore && (
<Button <Button
onClick={() => void next()} onClick={() => void next()}
color="primary-text" color="brand"
variant="bordered"
icon={<Icon iconName="arrow_downward" />} icon={<Icon iconName="arrow_downward" />}
> >
{buttonLabel ?? t('Load more')} {buttonLabel ?? t('Load more')}

View File

@@ -24,12 +24,12 @@ export const LoadMoreText = ({
className="--docs--load-more" className="--docs--load-more"
> >
<Icon <Icon
$theme="primary" $theme="brand"
$variation="800" $variation="secondary"
iconName="arrow_downward" iconName="arrow_downward"
$size="md" $size="md"
/> />
<Text $theme="primary" $variation="800"> <Text $theme="brand" $variation="secondary">
{t('Load more')} {t('Load more')}
</Text> </Text>
</Box> </Box>

View File

@@ -5,7 +5,7 @@ import { tokens } from '@/cunningham';
import { Box, BoxProps } from './Box'; import { Box, BoxProps } from './Box';
const { sizes } = tokens.themes.default.theme.font; const { sizes } = tokens.themes.default.globals.font;
type TextSizes = keyof typeof sizes; type TextSizes = keyof typeof sizes;
export interface TextProps extends BoxProps { export interface TextProps extends BoxProps {
@@ -27,24 +27,14 @@ export const TextStyled = styled(Box)<TextProps>`
${({ $size }) => ${({ $size }) =>
$size && $size &&
`font-size: ${$size in sizes ? sizes[$size as TextSizes] : $size};`} `font-size: ${$size in sizes ? sizes[$size as TextSizes] : $size};`}
${({ $color }) => $color && `color: ${$color};`}
${({ $ellipsis }) => ${({ $ellipsis }) =>
$ellipsis && $ellipsis &&
`white-space: nowrap; overflow: hidden; text-overflow: ellipsis;`} `white-space: nowrap; overflow: hidden; text-overflow: ellipsis;`}
`; `;
const Text = forwardRef<HTMLElement, ComponentPropsWithRef<typeof TextStyled>>( const Text = forwardRef<HTMLElement, ComponentPropsWithRef<typeof TextStyled>>(
({ className, ...props }, ref) => { (props, ref) => {
return ( return <TextStyled ref={ref} as="span" {...props} />;
<TextStyled
ref={ref}
as="span"
$theme="greyscale"
$variation="text"
className={className}
{...props}
/>
);
}, },
); );

View File

@@ -7,7 +7,7 @@ import { Box, Text, TextType } from '@/components';
const AlertStyled = styled(Alert)` const AlertStyled = styled(Alert)`
& .c__button--tertiary:hover { & .c__button--tertiary:hover {
background-color: var(--c--theme--colors--greyscale-200); background-color: var(--c--globals--colors--gray-200);
} }
`; `;
@@ -54,8 +54,7 @@ export const TextOnlyErrors = ({
causes.map((cause, i) => ( causes.map((cause, i) => (
<Text <Text
key={`causes-${i}`} key={`causes-${i}`}
$theme="danger" $theme="error"
$variation="600"
$textAlign="center" $textAlign="center"
{...textProps} {...textProps}
> >
@@ -64,12 +63,7 @@ export const TextOnlyErrors = ({
))} ))}
{!causes && ( {!causes && (
<Text <Text $theme="error" $textAlign="center" {...textProps}>
$theme="danger"
$variation="600"
$textAlign="center"
{...textProps}
>
{defaultMessage || t('Something bad happens, please retry.')} {defaultMessage || t('Something bad happens, please retry.')}
</Text> </Text>
)} )}

View File

@@ -124,18 +124,19 @@ export const DropdownMenu = ({
> >
<Box>{children}</Box> <Box>{children}</Box>
<Icon <Icon
$variation="600"
$css={ $css={
arrowCss ?? arrowCss ??
css` css`
color: var(--c--theme--colors--primary-600); color: var(--c--globals--colors--brand-600);
` `
} }
iconName={isOpen ? 'arrow_drop_up' : 'arrow_drop_down'} iconName={isOpen ? 'arrow_drop_up' : 'arrow_drop_down'}
/> />
</Box> </Box>
) : ( ) : (
<Box ref={blockButtonRef}>{children}</Box> <Box ref={blockButtonRef} $color="inherit">
{children}
</Box>
) )
} }
> >
@@ -147,7 +148,6 @@ export const DropdownMenu = ({
> >
{topMessage && ( {topMessage && (
<Text <Text
$variation="700"
$wrap="wrap" $wrap="wrap"
$size="xs" $size="xs"
$weight="bold" $weight="bold"
@@ -186,8 +186,8 @@ export const DropdownMenu = ({
key={option.label} key={option.label}
$align="center" $align="center"
$justify="space-between" $justify="space-between"
$background={colorsTokens['greyscale-000']} $background={colorsTokens['gray-000']}
$color={colorsTokens['primary-600']} $color={colorsTokens['brand-600']}
$padding={{ vertical: 'xs', horizontal: 'base' }} $padding={{ vertical: 'xs', horizontal: 'base' }}
$width="100%" $width="100%"
$gap={spacingsTokens['base']} $gap={spacingsTokens['base']}
@@ -200,30 +200,39 @@ export const DropdownMenu = ({
`} `}
${index === options.length - 1 && ${index === options.length - 1 &&
css` css`
border-bottom-left-radius: 4px; border-bottom-left-radius: var(--c--globals--spacings--st);
border-bottom-right-radius: 4px; border-bottom-right-radius: var(--c--globals--spacings--st);
`} `}
font-size: var(--c--theme--font--sizes--sm); font-size: var(--c--globals--font--sizes--sm);
color: var(--c--theme--colors--greyscale-1000); color: var(--c--globals--colors--gray-1000);
font-weight: 500; font-weight: var(--c--globals--font--weights--medium);
cursor: ${isDisabled ? 'not-allowed' : 'pointer'}; cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
user-select: none; user-select: none;
&:hover { &:hover {
background-color: var(--c--theme--colors--greyscale-050); background-color: var(
--c--contextuals--background--semantic--contextual--primary
);
} }
&:focus-visible { &:focus-visible {
outline: 2px solid var(--c--theme--colors--primary-400); outline: 2px solid var(--c--globals--colors--brand-400);
outline-offset: -2px; outline-offset: -2px;
background-color: var(--c--theme--colors--greyscale-050); background-color: var(
--c--contextuals--background--semantic--contextual--primary
);
} }
${isFocused && /**
* TODO: This part seems to have a problem with DocToolBox
*/
/* ${isFocused &&
css` css`
outline-offset: -2px; outline-offset: -2px;
background-color: var(--c--theme--colors--greyscale-050); background-color: var(
`} --c--contextuals--background--semantic--contextual--primary
);
`} */
`} `}
> >
<Box <Box
@@ -234,8 +243,8 @@ export const DropdownMenu = ({
{option.icon && typeof option.icon === 'string' && ( {option.icon && typeof option.icon === 'string' && (
<Icon <Icon
$size="20px" $size="20px"
$theme="greyscale" $theme="gray"
$variation={isDisabled ? '400' : '1000'} $variation={isDisabled ? 'tertiary' : 'primary'}
iconName={option.icon} iconName={option.icon}
aria-hidden="true" aria-hidden="true"
/> />
@@ -243,7 +252,7 @@ export const DropdownMenu = ({
{option.icon && {option.icon &&
typeof option.icon !== 'string' && typeof option.icon !== 'string' &&
option.icon} option.icon}
<Text $variation={isDisabled ? '400' : '1000'}> <Text $variation={isDisabled ? 'tertiary' : 'primary'}>
{option.label} {option.label}
</Text> </Text>
</Box> </Box>
@@ -252,7 +261,7 @@ export const DropdownMenu = ({
<Icon <Icon
iconName="check" iconName="check"
$size="20px" $size="20px"
$theme="greyscale" $theme="gray"
aria-hidden="true" aria-hidden="true"
/> />
)} )}

View File

@@ -33,32 +33,27 @@ export const FilterDropdown = ({
<Box <Box
$css={css` $css={css`
border: 1px solid border: 1px solid
${selectedOption var(--c--contextuals--border--semantic--neutral--tertiary);
? 'var(--c--theme--colors--primary-500)' border-radius: var(--c--globals--spacings--st);
: 'var(--c--theme--colors--greyscale-250)'}; background-color: var(
border-radius: 4px; --c--contextuals--background--semantic--neutral--tertiary
background-color: ${selectedOption );
? 'var(--c--theme--colors--primary-100)' gap: var(--c--globals--spacings--2xs);
: 'var(--c--theme--colors--greyscale-000)'}; padding: var(--c--globals--spacings--2xs)
gap: var(--c--theme--spacings--2xs); var(--c--globals--spacings--xs);
padding: var(--c--theme--spacings--2xs) var(--c--theme--spacings--xs);
`} `}
color="secondary" color="secondary"
$direction="row" $direction="row"
$align="center" $align="center"
> >
<Text <Text $weight={400} $variation="tertiary" $theme="neutral">
$weight={400}
$variation={selectedOption ? '800' : '600'}
$theme={selectedOption ? 'primary' : 'greyscale'}
>
{selectedOption?.label ?? options[0].label} {selectedOption?.label ?? options[0].label}
</Text> </Text>
<Icon <Icon
$size="16px" $size="s"
iconName="keyboard_arrow_down" iconName="keyboard_arrow_down"
$variation={selectedOption ? '800' : '600'} $variation="tertiary"
$theme={selectedOption ? 'primary' : 'greyscale'} $theme="neutral"
/> />
</Box> </Box>
</DropdownMenu> </DropdownMenu>

View File

@@ -38,7 +38,6 @@ export const AlertModal = ({
$margin="0" $margin="0"
id="alert-modal-title" id="alert-modal-title"
$align="flex-start" $align="flex-start"
$variation="1000"
> >
{title} {title}
</Text> </Text>
@@ -47,7 +46,7 @@ export const AlertModal = ({
<> <>
<Button <Button
aria-label={`${t('Cancel')} - ${title}`} aria-label={`${t('Cancel')} - ${title}`}
color="secondary" variant="secondary"
fullWidth fullWidth
onClick={() => onClose()} onClick={() => onClose()}
> >
@@ -55,7 +54,7 @@ export const AlertModal = ({
</Button> </Button>
<Button <Button
aria-label={confirmLabel ?? t('Confirm')} aria-label={confirmLabel ?? t('Confirm')}
color="danger" color="error"
onClick={onConfirm} onClick={onConfirm}
> >
{confirmLabel ?? t('Confirm')} {confirmLabel ?? t('Confirm')}
@@ -65,7 +64,7 @@ export const AlertModal = ({
> >
<Box className="--docs--alert-modal"> <Box className="--docs--alert-modal">
<Box> <Box>
<Text $variation="600" as="p"> <Text $variation="secondary" as="p">
{description} {description}
</Text> </Text>
</Box> </Box>

View File

@@ -1,18 +1,21 @@
import { Button, type ButtonProps } from '@openfun/cunningham-react'; import { Button, type ButtonProps } from '@openfun/cunningham-react';
import React from 'react'; import React from 'react';
import { Box } from '@/components'; import { Icon } from '@/components';
export const ButtonCloseModal = (props: ButtonProps) => { export const ButtonCloseModal = (props: ButtonProps) => {
return ( return (
<Button <Button
type="button" type="button"
size="small" size="small"
color="primary-text" color="brand"
variant="tertiary"
icon={ icon={
<Box as="span" aria-hidden="true" className="material-icons-filled"> <Icon
close $withThemeInherited
</Box> iconName="close"
className="material-icons-filled"
/>
} }
{...props} {...props}
/> />

View File

@@ -59,11 +59,7 @@ export const QuickSearchGroup = <T,>({
); );
})} })}
{group.emptyString && group.elements.length === 0 && ( {group.emptyString && group.elements.length === 0 && (
<Text <Text $margin={{ left: '2xs', bottom: '3xs' }} $size="sm">
$variation="500"
$margin={{ left: '2xs', bottom: '3xs' }}
$size="sm"
>
{group.emptyString} {group.emptyString}
</Text> </Text>
)} )}

View File

@@ -53,7 +53,7 @@ export const QuickSearchInput = ({
$padding={{ horizontal: 'base', vertical: 'sm' }} $padding={{ horizontal: 'base', vertical: 'sm' }}
> >
{!loading && ( {!loading && (
<Icon iconName="search" $variation="600" aria-hidden="true" /> <Icon iconName="search" $variation="secondary" aria-hidden="true" />
)} )}
{loading && ( {loading && (
<div> <div>

View File

@@ -19,25 +19,25 @@ export const QuickSearchStyle = createGlobalStyle`
border: none; border: none;
width: 100%; width: 100%;
font-size: 17px; font-size: 17px;
padding: 8px; padding: var(--c--globals--spacings--xs);
background: white; background: white;
outline: none; outline: none;
color: var(--c--theme--colors--greyscale-1000); color: var(--c--globals--colors--gray-1000);
border-radius: 0; border-radius: var(--c--globals--spacings--0);
&::placeholder { &::placeholder {
color: var(--c--theme--colors--greyscale-500); color: var(--c--globals--colors--gray-500);
} }
} }
[cmdk-item] { [cmdk-item] {
content-visibility: auto; content-visibility: auto;
cursor: pointer; cursor: pointer;
border-radius: var(--c--theme--spacings--xs); border-radius: var(--c--globals--spacings--xs);
font-size: 14px; font-size: var(--c--globals--font--sizes--sm);
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: var(--c--globals--spacings--xs);
user-select: none; user-select: none;
will-change: background, color; will-change: background, color;
transition: all 150ms ease; transition: all 150ms ease;
@@ -49,19 +49,19 @@ export const QuickSearchStyle = createGlobalStyle`
&:hover, &:hover,
&[data-selected='true'] { &[data-selected='true'] {
background: var(--c--theme--colors--greyscale-100); background: var(--c--contextuals--background--semantic--contextual--primary);
.show-right-on-focus { .show-right-on-focus {
opacity: 1; opacity: 1;
} }
} }
&[data-disabled='true'] { &[data-disabled='true'] {
color: var(--c--theme--colors--greyscale-500); color: var(--c--globals--colors--gray-500);
cursor: not-allowed; cursor: not-allowed;
} }
& + [cmdk-item] { & + [cmdk-item] {
margin-top: 4px; margin-top: var(--c--globals--spacings--st);
} }
} }
@@ -79,11 +79,11 @@ export const QuickSearchStyle = createGlobalStyle`
kbd { kbd {
font-size: 12px; font-size: 12px;
min-width: 20px; min-width: 20px;
padding: 4px; padding: var(--c--globals--spacings--st);
height: 20px; height: 20px;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
color: white; color: white;
background: var(--c--theme--colors--greyscale-500); background: var(--c--globals--colors--gray-500);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -94,23 +94,23 @@ export const QuickSearchStyle = createGlobalStyle`
[cmdk-separator] { [cmdk-separator] {
height: 1px; height: 1px;
width: 100%; width: 100%;
background: var(--c--theme--colors--greyscale-500); background: var(--c--globals--colors--gray-500);
margin: 4px 0; margin: var(--c--globals--spacings--st) 0;
} }
*:not([hidden]) + [cmdk-group] { *:not([hidden]) + [cmdk-group] {
margin-top: 8px; margin-top: var(--c--globals--spacings--xs);
} }
[cmdk-group-heading] { [cmdk-group-heading] {
user-select: none; user-select: none;
font-size: var(--c--theme--font--sizes--sm); font-size: var(--c--globals--font--sizes--sm);
color: var(--c--theme--colors--greyscale-700); color: var(--c--globals--colors--gray-700);
font-weight: bold; font-weight: bold;
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: var(--c--theme--spacings--xs); margin-bottom: var(--c--globals--spacings--xs);
} }
[cmdk-empty] { [cmdk-empty] {
@@ -128,9 +128,9 @@ export const QuickSearchStyle = createGlobalStyle`
} }
.c__modal__title { .c__modal__title {
font-size: var(--c--theme--font--sizes--xs); font-size: var(--c--globals--font--sizes--xs);
padding: var(--c--theme--spacings--base); padding: var(--c--globals--spacings--base);
margin-bottom: 0; margin-bottom: var(--c--globals--spacings--0);
} }
} }
`; `;

View File

@@ -1,26 +1,16 @@
import { useCunninghamTheme } from '@/cunningham';
import { Spacings } from '@/utils'; import { Spacings } from '@/utils';
import { Box } from '../Box'; import { Box } from '../Box';
export enum SeparatorVariant {
LIGHT = 'light',
DARK = 'dark',
}
type Props = { type Props = {
variant?: SeparatorVariant;
$withPadding?: boolean; $withPadding?: boolean;
customPadding?: Spacings; customPadding?: Spacings;
}; };
export const HorizontalSeparator = ({ export const HorizontalSeparator = ({
variant = SeparatorVariant.LIGHT,
$withPadding = true, $withPadding = true,
customPadding, customPadding,
}: Props) => { }: Props) => {
const { colorsTokens } = useCunninghamTheme();
const padding = $withPadding const padding = $withPadding
? (customPadding ?? 'base') ? (customPadding ?? 'base')
: ('none' as Spacings); : ('none' as Spacings);
@@ -30,11 +20,7 @@ export const HorizontalSeparator = ({
$height="1px" $height="1px"
$width="100%" $width="100%"
$margin={{ vertical: padding }} $margin={{ vertical: padding }}
$background={ $background="var(--c--contextuals--border--surface--primary)"
variant === SeparatorVariant.DARK
? '#e5e5e533'
: colorsTokens['greyscale-100']
}
className="--docs--horizontal-separator" className="--docs--horizontal-separator"
/> />
); );

View File

@@ -13,7 +13,8 @@ export const SeparatedSection = ({
showSeparator = true, showSeparator = true,
children, children,
}: PropsWithChildren<Props>) => { }: PropsWithChildren<Props>) => {
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
return ( return (
<Box <Box
$css={css` $css={css`
@@ -21,7 +22,8 @@ export const SeparatedSection = ({
padding: ${spacingsTokens['sm']} 0; padding: ${spacingsTokens['sm']} 0;
${showSeparator && ${showSeparator &&
css` css`
border-bottom: 1px solid ${colorsTokens['greyscale-200']}; border-bottom: 1px solid
var(--c--contextuals--border--surface--primary);
`} `}
`} `}
> >

View File

@@ -2,13 +2,13 @@ import { useCunninghamTheme } from '../useCunninghamTheme';
describe('<useCunninghamTheme />', () => { describe('<useCunninghamTheme />', () => {
it('has the logo correctly set', () => { it('has the logo correctly set', () => {
expect(useCunninghamTheme.getState().themeTokens.logo?.src).toBe(''); expect(useCunninghamTheme.getState().componentTokens.logo?.src).toBe('');
// Change theme // Change theme
useCunninghamTheme.getState().setTheme('dsfr'); useCunninghamTheme.getState().setTheme('dsfr');
const { themeTokens } = useCunninghamTheme.getState(); const { componentTokens } = useCunninghamTheme.getState();
const logo = themeTokens.logo; const logo = componentTokens.logo;
expect(logo?.src).toBe('/assets/logo-gouv.svg'); expect(logo?.src).toBe('/assets/logo-gouv.svg');
expect(logo?.widthHeader).toBe('110px'); expect(logo?.widthHeader).toBe('110px');
expect(logo?.widthFooter).toBe('220px'); expect(logo?.widthFooter).toBe('220px');

View File

@@ -26,7 +26,7 @@
* Select * Select
**/ **/
--c--components--forms-select--value-color--disabled: var( --c--components--forms-select--value-color--disabled: var(
--c--theme--colors--greyscale-400 --c--globals--colors--gray-400
); );
/** /**
@@ -44,6 +44,14 @@
contain: content; contain: content;
} }
.c__button:disabled {
cursor: unset;
}
.c__button:focus-visible {
outline: none;
}
.c__button--medium { .c__button--medium {
min-height: var(--c--components--button--medium-height); min-height: var(--c--components--button--medium-height);
height: auto; height: auto;
@@ -60,14 +68,11 @@
* Tooltip * Tooltip
*/ */
.c__tooltip { .c__tooltip {
padding: 4px 6px; padding: var(--c--globals--font--sizes--sm) var(--c--globals--spacings--xxs);
} }
/** .c__tooltip .react-aria-OverlayArrow svg {
* Image System display: none;
*/
.c__image-system-filter {
filter: var(--c--components--image-system-filter);
} }
/** /**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,21 +5,23 @@ import { tokens } from './cunningham-tokens';
type Tokens = typeof tokens.themes.default & type Tokens = typeof tokens.themes.default &
Partial<(typeof tokens.themes)[keyof typeof tokens.themes]>; Partial<(typeof tokens.themes)[keyof typeof tokens.themes]>;
type ColorsTokens = Tokens['theme']['colors']; type ColorsTokens = Tokens['globals']['colors'];
type FontSizesTokens = Tokens['theme']['font']['sizes']; type FontSizesTokens = Tokens['globals']['font']['sizes'];
type SpacingsTokens = Tokens['theme']['spacings']; type SpacingsTokens = Tokens['globals']['spacings'];
type ComponentTokens = Tokens['components']; type ComponentTokens = Tokens['components'];
type ContextualTokens = Tokens['contextuals'];
export type Theme = keyof typeof tokens.themes; export type Theme = keyof typeof tokens.themes;
interface ThemeStore { interface ThemeStore {
colorsTokens: Partial<ColorsTokens>; colorsTokens: Partial<ColorsTokens>;
componentTokens: ComponentTokens; componentTokens: ComponentTokens;
contextualTokens: ContextualTokens;
currentTokens: Partial<Tokens>; currentTokens: Partial<Tokens>;
fontSizesTokens: Partial<FontSizesTokens>; fontSizesTokens: Partial<FontSizesTokens>;
setTheme: (theme: Theme) => void; setTheme: (theme: Theme) => void;
spacingsTokens: Partial<SpacingsTokens>; spacingsTokens: Partial<SpacingsTokens>;
theme: Theme; theme: Theme;
themeTokens: Partial<Tokens['theme']>; themeTokens: Partial<Tokens['globals']>;
} }
const getMergedTokens = (theme: Theme) => { const getMergedTokens = (theme: Theme) => {
@@ -30,14 +32,15 @@ const DEFAULT_THEME: Theme = 'generic';
const defaultTokens = getMergedTokens(DEFAULT_THEME); const defaultTokens = getMergedTokens(DEFAULT_THEME);
const initialState: ThemeStore = { const initialState: ThemeStore = {
colorsTokens: defaultTokens.theme.colors, colorsTokens: defaultTokens.globals.colors,
componentTokens: defaultTokens.components, componentTokens: defaultTokens.components,
contextualTokens: defaultTokens.contextuals,
currentTokens: tokens.themes[DEFAULT_THEME] as Partial<Tokens>, currentTokens: tokens.themes[DEFAULT_THEME] as Partial<Tokens>,
fontSizesTokens: defaultTokens.theme.font.sizes, fontSizesTokens: defaultTokens.globals.font.sizes,
setTheme: () => {}, setTheme: () => {},
spacingsTokens: defaultTokens.theme.spacings, spacingsTokens: defaultTokens.globals.spacings,
theme: DEFAULT_THEME, theme: DEFAULT_THEME,
themeTokens: defaultTokens.theme, themeTokens: defaultTokens.globals,
}; };
export const useCunninghamTheme = create<ThemeStore>((set) => ({ export const useCunninghamTheme = create<ThemeStore>((set) => ({
@@ -46,13 +49,14 @@ export const useCunninghamTheme = create<ThemeStore>((set) => ({
const newTokens = getMergedTokens(theme); const newTokens = getMergedTokens(theme);
set({ set({
colorsTokens: newTokens.theme.colors, colorsTokens: newTokens.globals.colors,
componentTokens: newTokens.components, componentTokens: newTokens.components,
contextualTokens: newTokens.contextuals,
currentTokens: tokens.themes[theme] as Partial<Tokens>, currentTokens: tokens.themes[theme] as Partial<Tokens>,
fontSizesTokens: newTokens.theme.font.sizes, fontSizesTokens: newTokens.globals.font.sizes,
spacingsTokens: newTokens.theme.spacings, spacingsTokens: newTokens.globals.spacings,
theme, theme,
themeTokens: newTokens.theme, themeTokens: newTokens.globals,
}); });
}, },
})); }));

View File

@@ -18,7 +18,8 @@ export const ButtonLogin = () => {
return ( return (
<Button <Button
onClick={() => gotoLogin()} onClick={() => gotoLogin()}
color="primary-text" color="brand"
variant="tertiary"
aria-label={t('Login')} aria-label={t('Login')}
className="--docs--button-login" className="--docs--button-login"
> >
@@ -31,14 +32,15 @@ export const ButtonLogin = () => {
<Box <Box
$css={css` $css={css`
.--docs--button-logout:focus-visible { .--docs--button-logout:focus-visible {
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']} !important; box-shadow: 0 0 0 2px ${colorsTokens['brand-400']} !important;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
`} `}
> >
<Button <Button
onClick={gotoLogout} onClick={gotoLogout}
color="primary-text" color="brand"
variant="tertiary"
aria-label={t('Logout')} aria-label={t('Logout')}
className="--docs--button-logout" className="--docs--button-logout"
> >
@@ -56,9 +58,13 @@ export const ProConnectButton = () => {
onClick={() => gotoLogin()} onClick={() => gotoLogin()}
aria-label={t('Proconnect Login')} aria-label={t('Proconnect Login')}
$css={css` $css={css`
background-color: var(--c--theme--colors--primary-text); background-color: var(
--c--contextuals--background--semantic--brand--primary
);
&:hover { &:hover {
background-color: var(--c--theme--colors--primary-action); background-color: var(
--c--contextuals--background--semantic--brand--primary-hover
);
} }
`} `}
$radius="4px" $radius="4px"

View File

@@ -4,15 +4,12 @@ import { tokens } from '@/cunningham';
import { AvatarSvg } from './AvatarSvg'; import { AvatarSvg } from './AvatarSvg';
const colors = tokens.themes.default.theme.colors; const colors = tokens.themes.default.globals.colors;
const avatarsColors = [ const avatarsColors = [
colors['blue-500'], colors['blue-1-500'],
colors['brown-500'], colors['brown-500'],
colors['cyan-500'],
colors['gold-500'],
colors['green-500'], colors['green-500'],
colors['olive-500'],
colors['orange-500'], colors['orange-500'],
colors['pink-500'], colors['pink-500'],
colors['purple-500'], colors['purple-500'],

View File

@@ -91,7 +91,7 @@ export function MarkdownButton() {
<Text <Text
aria-hidden={true} aria-hidden={true}
$css={css` $css={css`
font-family: var(--c--theme--font--families--base); font-family: var(--c--globals--font--families--base);
`} `}
$weight="bold" $weight="bold"
> >

View File

@@ -24,14 +24,14 @@ export const ModalConfirmDownloadUnsafe = ({
<> <>
<Button <Button
aria-label={t('Cancel the download')} aria-label={t('Cancel the download')}
color="secondary" variant="secondary"
onClick={() => onClose()} onClick={() => onClose()}
> >
{t('Cancel')} {t('Cancel')}
</Button> </Button>
<Button <Button
aria-label={t('Download')} aria-label={t('Download')}
color="danger" color="error"
data-testid="modal-download-unsafe-button" data-testid="modal-download-unsafe-button"
onClick={() => { onClick={() => {
if (onConfirm) { if (onConfirm) {
@@ -52,7 +52,6 @@ export const ModalConfirmDownloadUnsafe = ({
$gap="0.7rem" $gap="0.7rem"
$size="h6" $size="h6"
$align="flex-start" $align="flex-start"
$variation="1000"
$direction="row" $direction="row"
$margin="0" $margin="0"
> >
@@ -67,8 +66,10 @@ export const ModalConfirmDownloadUnsafe = ({
> >
<Box> <Box>
<Box $direction="column" $gap="0.35rem" $margin={{ top: 'sm' }}> <Box $direction="column" $gap="0.35rem" $margin={{ top: 'sm' }}>
<Text $variation="700">{t('This file is flagged as unsafe.')}</Text> <Text $variation="secondary">
<Text $variation="600"> {t('This file is flagged as unsafe.')}
</Text>
<Text $variation="secondary">
{t('Please download it only if it comes from a trusted source.')} {t('Please download it only if it comes from a trusted source.')}
</Text> </Text>
</Box> </Box>

View File

@@ -46,20 +46,18 @@ export const CommentToolbarButton = () => {
<Icon <Icon
iconName="comment" iconName="comment"
className="--docs--icon-bg" className="--docs--icon-bg"
$theme="greyscale" $theme="gray"
$variation="600"
$padding="0.15rem" $padding="0.15rem"
$size="16px" $size="md"
$color={colorsTokens['greyscale-600']}
/> />
{t('Comment')} {t('Comment')}
</Box> </Box>
</Components.Generic.Toolbar.Button> </Components.Generic.Toolbar.Button>
<Box <Box
$background={colorsTokens['greyscale-100']} $background={colorsTokens['gray-100']}
$width="1px" $width="1px"
$height="70%" $height="70%"
$margin={{ left: '2px' }} $margin={{ left: 'var(--c--globals--spacings--4xs)' }}
$css={css` $css={css`
align-self: center; align-self: center;
`} `}

View File

@@ -11,7 +11,7 @@ export const cssComments = (
.bn-thread-mark:not([data-orphan='true']), .bn-thread-mark:not([data-orphan='true']),
.bn-thread-mark-selected:not([data-orphan='true']) { .bn-thread-mark-selected:not([data-orphan='true']) {
background: ${canSeeComment ? '#EDB40066' : 'transparent'}; background: ${canSeeComment ? '#EDB40066' : 'transparent'};
color: var(--c--theme--colors--greyscale-700); color: var(--c--globals--colors--greyscale-700);
} }
} }
@@ -31,7 +31,7 @@ export const cssComments = (
max-height: 500px; max-height: 500px;
.bn-default-styles { .bn-default-styles {
font-family: var(--c--theme--font--families--base); font-family: var(--c--globals--font--families--base);
} }
.bn-block { .bn-block {
@@ -52,21 +52,22 @@ export const cssComments = (
padding: 8px; padding: 8px;
& .bn-editor { & .bn-editor {
padding-left: 32px; padding-left: var(--c--globals--spacings--lg);
.bn-inline-content { .bn-inline-content {
color: var(--c--theme--colors--greyscale-700); color: var(--c--globals--colors--greyscale-700);
} }
} }
// Emoji // Emoji
& .bn-badge-group { & .bn-badge-group {
padding-left: 32px; padding-left: var(--c--globals--spacings--lg);
.bn-badge label { .bn-badge label {
padding: 0 4px; padding: var(--c--globals--spacings--0)
var(--c--globals--spacings--st);
background: none; background: none;
border: 1px solid var(--c--theme--colors--greyscale-300); border: 1px solid var(--c--globals--colors--greyscale-300);
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
height: 24px; height: var(--c--globals--spacings--md);
} }
} }
@@ -102,17 +103,17 @@ export const cssComments = (
background-color: transparent; background-color: transparent;
&:hover { &:hover {
background-color: var(--c--theme--colors--greyscale-100); background-color: var(--c--globals--colors--greyscale-100);
} }
} }
button[role='menuitem'] svg { button[role='menuitem'] svg {
color: var(--c--theme--colors--greyscale-600); color: var(--c--globals--colors--greyscale-600);
} }
} }
& svg { & svg {
color: var(--c--theme--colors--info-600); color: var(--c--globals--colors--info-600);
} }
} }
@@ -125,19 +126,19 @@ export const cssComments = (
gap: 0.4rem !important; gap: 0.4rem !important;
& > button { & > button {
height: 24px; height: var(--c--globals--spacings--md);
padding-inline: 4px; padding-inline: var(--c--globals--spacings--st);
&[data-test='save'] { &[data-test='save'] {
border: 1px solid var(--c--theme--colors--info-600); border: 1px solid var(--c--globals--colors--info-600);
background: var(--c--theme--colors--info-600); background: var(--c--globals--colors--info-600);
color: white; color: white;
} }
&[data-test='cancel'] { &[data-test='cancel'] {
background: white; background: white;
border: 1px solid var(--c--theme--colors--greyscale-300); border: 1px solid var(--c--globals--colors--greyscale-300);
color: var(--c--theme--colors--info-600); color: var(--c--globals--colors--info-600);
} }
} }
} }
@@ -179,19 +180,19 @@ export const cssComments = (
button { button {
font-size: 0; font-size: 0;
background: var(--c--theme--colors--info-600); background: var(--c--globals--colors--info-600);
width: 24px; width: var(--c--globals--spacings--md);
height: 24px; height: var(--c--globals--spacings--md);
padding: 0; padding: var(--c--globals--spacings--0);
&:disabled { &:disabled {
background: var(--c--theme--colors--greyscale-300); background: var(--c--globals--colors--greyscale-300);
} }
& .mantine-Button-label::before { & .mantine-Button-label::before {
content: '🡡'; content: '🡡';
font-size: 13px; font-size: 13px;
color: var(--c--theme--colors--greyscale-100); color: var(--c--globals--colors--greyscale-100);
} }
} }
} }

View File

@@ -21,8 +21,8 @@ import emojidata from './initEmojiCallout';
const CalloutBlockStyle = createGlobalStyle` const CalloutBlockStyle = createGlobalStyle`
.bn-block-content[data-content-type="callout"][data-background-color] { .bn-block-content[data-content-type="callout"][data-background-color] {
padding: var(--c--theme--spacings--3xs) var(--c--theme--spacings--3xs); padding: var(--c--globals--spacings--3xs) var(--c--globals--spacings--3xs);
border-radius: var(--c--theme--spacings--3xs); border-radius: var(--c--globals--spacings--3xs);
} }
`; `;

View File

@@ -91,9 +91,10 @@ const LinkSelected = ({ url, title }: LinkSelectedProps) => {
margin-right: 0.2rem; margin-right: 0.2rem;
} }
&:hover { &:hover {
background-color: ${colorsTokens['greyscale-100']}; background-color: ${colorsTokens['gray-100']};
} }
transition: background-color 0.2s ease-in-out; transition: background-color var(--c--globals--transitions--duration)
var(--c--globals--transitions--ease-out);
.--docs--doc-deleted & { .--docs--doc-deleted & {
pointer-events: none; pointer-events: none;
@@ -103,7 +104,7 @@ const LinkSelected = ({ url, title }: LinkSelectedProps) => {
{emoji ? ( {emoji ? (
<Text $size="16px">{emoji}</Text> <Text $size="16px">{emoji}</Text>
) : ( ) : (
<SelectedPageIcon width={11.5} color={colorsTokens['primary-400']} /> <SelectedPageIcon width={11.5} color={colorsTokens['brand-400']} />
)} )}
<Text <Text
$weight="500" $weight="500"

View File

@@ -35,11 +35,11 @@ import { DocSearchSubPageContent, DocSearchTarget } from '@/docs/doc-search';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
const inputStyle = css` const inputStyle = css`
background-color: var(--c--theme--colors--greyscale-100); background-color: var(--c--globals--colors--gray-100);
border: none; border: none;
outline: none; outline: none;
color: var(--c--theme--colors--greyscale-700); color: var(--c--globals--colors--gray-700);
font-size: 16px; font-size: var(--c--globals--font--sizes--md);
width: 100%; width: 100%;
font-family: 'Inter'; font-family: 'Inter';
`; `;
@@ -159,8 +159,8 @@ export const SearchPage = ({
<Box <Box
as="span" as="span"
className="inline-content" className="inline-content"
$background={colorsTokens['greyscale-100']} $background={colorsTokens['gray-100']}
$color="var(--c--theme--colors--greyscale-700)" $color="var(--c--globals--colors--gray-700)"
$direction="row" $direction="row"
$radius="3px" $radius="3px"
$padding="1px" $padding="1px"
@@ -198,9 +198,9 @@ export const SearchPage = ({
<QuickSearch showInput={false}> <QuickSearch showInput={false}>
<Card <Card
$css={css` $css={css`
box-shadow: 0 0 3px 0px var(--c--theme--colors--greyscale-200); box-shadow: 0 0 3px 0px var(--c--globals--colors--gray-200);
& > div { & > div {
margin-top: 0; margin-top: var(--c--globals--spacings--0);
& [cmdk-group-heading] { & [cmdk-group-heading] {
padding: 0.4rem; padding: 0.4rem;
margin: 0; margin: 0;
@@ -287,8 +287,8 @@ export const SearchPage = ({
</Box> </Box>
<Text <Text
$size="14px" $size="sm"
$color="var(--c--theme--colors--greyscale-1000)" $color="var(--c--globals--colors--gray-1000)"
spellCheck="false" spellCheck="false"
> >
{titleWithoutEmoji} {titleWithoutEmoji}
@@ -296,11 +296,7 @@ export const SearchPage = ({
</Box> </Box>
} }
right={ right={
<Icon <Icon iconName="keyboard_return" spellCheck="false" />
iconName="keyboard_return"
$variation="600"
spellCheck="false"
/>
} }
/> />
); );
@@ -317,7 +313,7 @@ export const SearchPage = ({
<Box <Box
$css={css` $css={css`
border-top: 1px solid border-top: 1px solid
var(--c--theme--colors--greyscale-200); var(--c--globals--colors--gray-200);
`} `}
$width="100%" $width="100%"
> >
@@ -332,15 +328,15 @@ export const SearchPage = ({
$css={css` $css={css`
&:hover { &:hover {
background-color: var( background-color: var(
--c--theme--colors--greyscale-100 --c--globals--colors--gray-100
); );
} }
`} `}
> >
<AddPageIcon /> <AddPageIcon />
<Text <Text
$size="14px" $size="sm"
$color="var(--c--theme--colors--greyscale-1000)" $color="var(--c--globals--colors--gray-1000)"
contentEditable={false} contentEditable={false}
> >
{t('New sub-doc')} {t('New sub-doc')}

View File

@@ -8,7 +8,7 @@ export const cssEditor = css`
} }
& .bn-editor { & .bn-editor {
color: var(--c--theme--colors--greyscale-700); color: var(--c--globals--colors--greyscale-700);
} }
/** /**
@@ -104,14 +104,14 @@ export const cssEditor = css`
* Callout, Paragraph and Heading blocks * Callout, Paragraph and Heading blocks
*/ */
.bn-block { .bn-block {
border-radius: var(--c--theme--spacings--3xs); border-radius: var(--c--globals--spacings--3xs);
} }
.bn-block-outer { .bn-block-outer {
border-radius: var(--c--theme--spacings--3xs); border-radius: var(--c--globals--spacings--3xs);
} }
.bn-block > .bn-block-content[data-background-color] { .bn-block > .bn-block-content[data-background-color] {
padding: var(--c--theme--spacings--3xs) var(--c--theme--spacings--3xs); padding: var(--c--globals--spacings--3xs) var(--c--globals--spacings--3xs);
border-radius: var(--c--theme--spacings--3xs); border-radius: var(--c--globals--spacings--3xs);
} }
.bn-block-content[data-content-type='checkListItem'][data-checked='true'] .bn-block-content[data-content-type='checkListItem'][data-checked='true']
.bn-inline-content { .bn-inline-content {
@@ -127,7 +127,7 @@ export const cssEditor = css`
font-size: 1.25rem; font-size: 1.25rem;
} }
a { a {
color: var(--c--theme--colors--greyscale-600); color: var(--c--globals--colors--greyscale-600);
cursor: pointer; cursor: pointer;
} }
.bn-block-group .bn-block-group
@@ -144,7 +144,7 @@ export const cssEditor = css`
* Quotes * Quotes
*/ */
blockquote { blockquote {
border-left: 4px solid var(--c--theme--colors--greyscale-300); border-left: 4px solid var(--c--globals--colors--gray-300);
font-style: italic; font-style: italic;
} }

View File

@@ -174,7 +174,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
<> <>
<Button <Button
aria-label={t('Cancel the download')} aria-label={t('Cancel the download')}
color="secondary" variant="secondary"
fullWidth fullWidth
onClick={() => onClose()} onClick={() => onClose()}
> >
@@ -183,7 +183,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
<Button <Button
data-testid="doc-export-download-button" data-testid="doc-export-download-button"
aria-label={t('Download')} aria-label={t('Download')}
color="primary" variant="primary"
fullWidth fullWidth
onClick={() => void onSubmit()} onClick={() => void onSubmit()}
disabled={isExporting} disabled={isExporting}
@@ -205,7 +205,6 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
$margin="0" $margin="0"
id="modal-export-title" id="modal-export-title"
$size="h6" $size="h6"
$variation="1000"
$align="flex-start" $align="flex-start"
data-testid="modal-export-title" data-testid="modal-export-title"
> >
@@ -225,7 +224,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
$gap="1rem" $gap="1rem"
className="--docs--modal-export-content" className="--docs--modal-export-content"
> >
<Text $variation="600" $size="sm" as="p"> <Text $variation="secondary" $size="sm" as="p">
{t('Download your document in a .docx, .odt or .pdf format.')} {t('Download your document in a .docx, .odt or .pdf format.')}
</Text> </Text>
<Select <Select

View File

@@ -2,36 +2,37 @@ import { Button, Modal, ModalSize } from '@openfun/cunningham-react';
import { t } from 'i18next'; import { t } from 'i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { Box, BoxButton, Icon, Text } from '@/components'; import { Box, BoxButton, Card, Icon, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
export const AlertNetwork = () => { export const AlertNetwork = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
return ( return (
<> <>
<Box> <Box>
<Box <Card
$direction="row" $direction="row"
$justify="space-between" $justify="space-between"
$width="100%" $width="100%"
$background={colorsTokens['warning-100']}
$radius={spacingsTokens['3xs']} $radius={spacingsTokens['3xs']}
$padding="xs" $padding="xs"
$flex={1} $flex={1}
$align="center" $align="center"
$gap={spacingsTokens['2xs']} $gap={spacingsTokens['2xs']}
$css={css` $theme="warning"
border: 1px solid var(--c--theme--colors--warning-300);
`}
> >
<Box $direction="row" $gap={spacingsTokens['2xs']} $align="center"> <Box
<Icon iconName="mobiledata_off" $theme="warning" $variation="600" /> $direction="row"
<Text $theme="warning" $variation="600" $weight={500}> $gap={spacingsTokens['2xs']}
$align="center"
$withThemeInherited
>
<Icon iconName="mobiledata_off" $withThemeInherited />
<Text $withThemeInherited $weight={500}>
{t('Others are editing. Your network prevent changes.')} {t('Others are editing. Your network prevent changes.')}
</Text> </Text>
</Box> </Box>
@@ -40,20 +41,20 @@ export const AlertNetwork = () => {
$gap={spacingsTokens['3xs']} $gap={spacingsTokens['3xs']}
$align="center" $align="center"
onClick={() => setIsModalOpen(true)} onClick={() => setIsModalOpen(true)}
$withThemeInherited
> >
<Icon <Icon
iconName="info" iconName="info"
$theme="warning" $withThemeInherited
$variation="600" $size="md"
$size="16px"
$weight="500" $weight="500"
$margin={{ top: 'auto' }} $margin={{ top: 'auto' }}
/> />
<Text $theme="warning" $variation="600" $weight="500" $size="xs"> <Text $withThemeInherited $weight="500" $size="xs">
{t('Learn more')} {t('Learn more')}
</Text> </Text>
</BoxButton> </BoxButton>
</Box> </Card>
</Box> </Box>
{isModalOpen && ( {isModalOpen && (
<AlertNetworkModal onClose={() => setIsModalOpen(false)} /> <AlertNetworkModal onClose={() => setIsModalOpen(false)} />
@@ -74,20 +75,14 @@ export const AlertNetworkModal = ({ onClose }: AlertNetworkModalProps) => {
onClose={() => onClose()} onClose={() => onClose()}
rightActions={ rightActions={
<> <>
<Button aria-label={t('OK')} onClick={onClose} color="danger"> <Button aria-label={t('OK')} onClick={onClose} color="error">
{t('I understand')} {t('I understand')}
</Button> </Button>
</> </>
} }
size={ModalSize.MEDIUM} size={ModalSize.MEDIUM}
title={ title={
<Text <Text $size="h6" as="h6" $margin={{ all: '0' }} $align="flex-start">
$size="h6"
as="h6"
$margin={{ all: '0' }}
$align="flex-start"
$variation="1000"
>
{t("Why you can't edit the document?")} {t("Why you can't edit the document?")}
</Text> </Text>
} }
@@ -97,14 +92,14 @@ export const AlertNetworkModal = ({ onClose }: AlertNetworkModalProps) => {
className="--docs--modal-alert-network" className="--docs--modal-alert-network"
$margin={{ top: 'md' }} $margin={{ top: 'md' }}
> >
<Text $size="sm" $variation="600"> <Text $size="sm" $variation="secondary">
{t( {t(
'Others are editing this document. Unfortunately your network blocks WebSockets, the technology enabling real-time co-editing.', 'Others are editing this document. Unfortunately your network blocks WebSockets, the technology enabling real-time co-editing.',
)} )}
</Text> </Text>
<Text <Text
$size="sm" $size="sm"
$variation="600" $variation="secondary"
$margin={{ top: 'xs' }} $margin={{ top: 'xs' }}
$weight="bold" $weight="bold"
$display="inline" $display="inline"
@@ -112,7 +107,7 @@ export const AlertNetworkModal = ({ onClose }: AlertNetworkModalProps) => {
{t("This means you can't edit until others leave.")}{' '} {t("This means you can't edit until others leave.")}{' '}
<Text <Text
$size="sm" $size="sm"
$variation="600" $variation="secondary"
$margin={{ top: 'xs' }} $margin={{ top: 'xs' }}
$weight="normal" $weight="normal"
$display="inline" $display="inline"

View File

@@ -1,39 +1,33 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { Box, Icon, Text } from '@/components'; import { Card, Icon, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
export const AlertPublic = ({ isPublicDoc }: { isPublicDoc: boolean }) => { export const AlertPublic = ({ isPublicDoc }: { isPublicDoc: boolean }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
return ( return (
<Box <Card
aria-label={t('Public document')} aria-label={t('Public document')}
$color={colorsTokens['primary-800']}
$background={colorsTokens['primary-050']}
$radius={spacingsTokens['3xs']} $radius={spacingsTokens['3xs']}
$direction="row" $direction="row"
$padding="xs" $padding="xs"
$flex={1} $flex={1}
$align="center" $align="center"
$gap={spacingsTokens['2xs']} $gap={spacingsTokens['2xs']}
$css={css` $theme="brand"
border: 1px solid var(--c--theme--colors--primary-300, #e3e3fd);
`}
> >
<Icon <Icon
$theme="primary" $withThemeInherited
$variation="800"
data-testid="public-icon" data-testid="public-icon"
iconName={isPublicDoc ? 'public' : 'vpn_lock'} iconName={isPublicDoc ? 'public' : 'vpn_lock'}
/> />
<Text $theme="primary" $variation="800" $weight="500"> <Text $withThemeInherited $weight="500">
{isPublicDoc {isPublicDoc
? t('Public document') ? t('Public document')
: t('Document accessible to any connected person')} : t('Document accessible to any connected person')}
</Text> </Text>
</Box> </Card>
); );
}; };

View File

@@ -1,9 +1,12 @@
import { useTreeContext } from '@gouvfr-lasuite/ui-kit'; import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
import { VariantType, useToastProvider } from '@openfun/cunningham-react'; import {
Button,
VariantType,
useToastProvider,
} from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { Box, BoxButton, Icon, Text } from '@/components'; import { Box, Card, Icon } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { import {
Doc, Doc,
@@ -17,7 +20,7 @@ export const AlertRestore = ({ doc }: { doc: Doc }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { toast } = useToastProvider(); const { toast } = useToastProvider();
const treeContext = useTreeContext<Doc>(); const treeContext = useTreeContext<Doc>();
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { mutate: restoreDoc, error } = useRestoreDoc({ const { mutate: restoreDoc, error } = useRestoreDoc({
listInvalidQueries: [KEY_LIST_DOC, KEY_LIST_DOC_TRASHBIN, KEY_DOC], listInvalidQueries: [KEY_LIST_DOC, KEY_LIST_DOC_TRASHBIN, KEY_DOC],
options: { options: {
@@ -44,57 +47,52 @@ export const AlertRestore = ({ doc }: { doc: Doc }) => {
}); });
return ( return (
<Box <Card
className="--docs--alert-restore" className="--docs--alert-restore"
aria-label={t('Alert deleted document')} aria-label={t('Alert deleted document')}
$color={colorsTokens['danger-800']}
$background={colorsTokens['danger-100']}
$radius={spacingsTokens['3xs']} $radius={spacingsTokens['3xs']}
$direction="row" $direction="row"
$padding="xs" $padding="xs"
$flex={1} $flex={1}
$align="center" $align="center"
$gap={spacingsTokens['3xs']} $gap={spacingsTokens['3xs']}
$css={css`
border: 1px solid var(--c--theme--colors--danger-300, #e3e3fd);
`}
$justify="space-between" $justify="space-between"
$theme="error"
> >
<Box $direction="row" $align="center" $gap={spacingsTokens['2xs']}> <Box
$withThemeInherited
$direction="row"
$align="center"
$gap={spacingsTokens['2xs']}
>
<Icon <Icon
$theme="danger" $withThemeInherited
$variation="700"
data-testid="public-icon" data-testid="public-icon"
iconName="delete" iconName="delete"
variant="symbols-outlined" variant="symbols-outlined"
/> />
<Text $theme="danger" $variation="700" $weight="500"> {t('Document deleted')}
{t('Document deleted')}
</Text>
</Box> </Box>
<BoxButton <Button
onClick={() => onClick={() =>
restoreDoc({ restoreDoc({
docId: doc.id, docId: doc.id,
}) })
} }
$direction="row" color="error"
$gap="0.2rem" variant="tertiary"
$theme="danger" size="nano"
$variation="600" icon={
$align="center" <Icon
iconName="undo"
$withThemeInherited
$size="18px"
variant="symbols-outlined"
/>
}
> >
<Icon Restore
iconName="undo" </Button>
$theme="danger" </Card>
$variation="600"
$size="18px"
variant="symbols-outlined"
/>
<Text $theme="danger" $variation="600" $size="s" $css="line-height:1;">
{t('Restore')}
</Text>
</BoxButton>
</Box>
); );
}; };

View File

@@ -46,20 +46,19 @@ export const BoutonShare = ({
<Box <Box
$css={css` $css={css`
.c__button--medium { .c__button--medium {
height: 32px; height: var(--c--globals--spacings--lg);
padding: 10px var(--c--theme--spacings--xs); padding: 10px var(--c--globals--spacings--xs);
gap: 7px; gap: 7px;
} }
`} `}
> >
<Button <Button
color="tertiary"
aria-label={t('Share button')} aria-label={t('Share button')}
variant="secondary"
icon={ icon={
<Icon <Icon
iconName="group" iconName="group"
$theme="primary" $color="inherit"
$variation="800"
variant="filled" variant="filled"
disabled={isDisabled} disabled={isDisabled}
/> />
@@ -76,7 +75,8 @@ export const BoutonShare = ({
return ( return (
<Button <Button
color="primary-text" color="brand"
variant="tertiary"
onClick={open} onClick={open}
size="medium" size="medium"
disabled={isDisabled} disabled={isDisabled}

View File

@@ -47,15 +47,15 @@ export const DocHeaderInfo = ({ doc }: DocHeaderInfoProps) => {
return ( return (
<> <>
<Text <Text
$variation="600" $variation="tertiary"
$size="s" $size="s"
$weight="bold" $weight="bold"
$theme={isEditable ? 'greyscale' : 'warning'} $theme={isEditable ? 'gray' : 'warning'}
> >
{transRole(isEditable ? doc.user_role || doc.link_role : Role.READER)} {transRole(isEditable ? doc.user_role || doc.link_role : Role.READER)}
&nbsp;·&nbsp; &nbsp;·&nbsp;
</Text> </Text>
<Text $variation="600" $size="s"> <Text $variation="tertiary" $size="s">
{dateToDisplay} {dateToDisplay}
</Text> </Text>
</> </>
@@ -64,11 +64,11 @@ export const DocHeaderInfo = ({ doc }: DocHeaderInfoProps) => {
return ( return (
<> <>
<Text $variation="400" $size="s"> <Text $variation="tertiary" $size="s">
{hasChildren ? relativeOnly : dateToDisplay} {hasChildren ? relativeOnly : dateToDisplay}
</Text> </Text>
{hasChildren && ( {hasChildren && (
<Text $variation="400" $size="s"> <Text $variation="tertiary" $size="s">
&nbsp;&nbsp; &nbsp;&nbsp;
{t('Contains {{count}} sub-documents', { {t('Contains {{count}} sub-documents', {
count: childrenCount, count: childrenCount,

View File

@@ -43,7 +43,6 @@ export const DocTitleText = () => {
as="h2" as="h2"
$margin={{ all: 'none', left: 'none' }} $margin={{ all: 'none', left: 'none' }}
$size={isMobile ? 'h4' : 'h2'} $size={isMobile ? 'h4' : 'h2'}
$variation="1000"
> >
{currentDoc?.title || untitledDocument} {currentDoc?.title || untitledDocument}
</Text> </Text>
@@ -71,10 +70,11 @@ const DocTitleEmojiPicker = ({ doc }: DocTitleProps) => {
padding-top: 3px; padding-top: 3px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: ${colorsTokens['greyscale-100']}; background-color: ${colorsTokens['gray-100']};
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
transition: background-color 0.2s ease-in-out; transition: background-color var(--c--globals--transitions--duration)
var(--c--globals--transitions--ease-out);
`} `}
> >
<DocIcon <DocIcon
@@ -95,7 +95,7 @@ const DocTitleEmojiPicker = ({ doc }: DocTitleProps) => {
height="25px" height="25px"
aria-hidden="true" aria-hidden="true"
aria-label={t('Simple document icon')} aria-label={t('Simple document icon')}
color={colorsTokens['primary-500']} color={colorsTokens['brand-500']}
/> />
} }
/> />
@@ -107,7 +107,6 @@ const DocTitleEmojiPicker = ({ doc }: DocTitleProps) => {
const DocTitleInput = ({ doc }: DocTitleProps) => { const DocTitleInput = ({ doc }: DocTitleProps) => {
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { t } = useTranslation(); const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
const { isTopRoot } = useDocUtils(doc); const { isTopRoot } = useDocUtils(doc);
const { untitledDocument } = useTrans(); const { untitledDocument } = useTrans();
const { emoji, titleWithoutEmoji } = getEmojiAndTitle(doc.title ?? ''); const { emoji, titleWithoutEmoji } = getEmojiAndTitle(doc.title ?? '');
@@ -177,18 +176,19 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
onBlurCapture={(event) => onBlurCapture={(event) =>
handleTitleSubmit(event.target.textContent || '') handleTitleSubmit(event.target.textContent || '')
} }
$color={colorsTokens['greyscale-1000']}
$padding={{ right: 'big' }} $padding={{ right: 'big' }}
$css={css` $css={css`
&[contenteditable='true']:empty:not(:focus):before { &[contenteditable='true']:empty:not(:focus):before {
content: '${untitledDocument}'; content: '${untitledDocument}';
color: grey; color: var(
--c--contextuals--content--semantic--neutral--tertiary
);
pointer-events: none; pointer-events: none;
font-style: italic; font-style: italic;
} }
font-size: ${isDesktop font-size: ${isDesktop
? css`var(--c--theme--font--sizes--h2)` ? css`var(--c--globals--font--sizes--h2)`
: css`var(--c--theme--font--sizes--sm)`}; : css`var(--c--globals--font--sizes--sm)`};
font-weight: 700; font-weight: 700;
outline: none; outline: none;
`} `}

View File

@@ -215,14 +215,9 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
{!isSmallMobile && ModalExport && ( {!isSmallMobile && ModalExport && (
<Button <Button
data-testid="doc-open-modal-download-button" data-testid="doc-open-modal-download-button"
color="tertiary-text" variant="tertiary"
icon={ icon={
<Icon <Icon iconName="download" $color="inherit" aria-hidden={true} />
iconName="download"
$theme="primary"
$variation="800"
aria-hidden={true}
/>
} }
onClick={() => { onClick={() => {
setIsModalExportOpen(true); setIsModalExportOpen(true);
@@ -236,17 +231,14 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
label={t('Open the document options')} label={t('Open the document options')}
buttonCss={css` buttonCss={css`
padding: ${spacingsTokens['xs']}; padding: ${spacingsTokens['xs']};
&:hover {
background-color: ${colorsTokens['greyscale-100']};
}
${isSmallMobile ${isSmallMobile
? css` ? css`
border: 1px solid ${colorsTokens['greyscale-300']}; border: 1px solid ${colorsTokens['gray-300']};
` `
: ''} : ''}
`} `}
> >
<IconOptions aria-hidden="true" isHorizontal $theme="primary" /> <IconOptions aria-hidden="true" isHorizontal $color="inherit" />
</DropdownMenu> </DropdownMenu>
</Box> </Box>

View File

@@ -21,7 +21,7 @@ export const DocIcon = ({
emoji, emoji,
defaultIcon, defaultIcon,
$size = 'sm', $size = 'sm',
$variation = '1000', $variation = 'secondary',
$weight = '400', $weight = '400',
docId, docId,
title, title,

View File

@@ -65,7 +65,6 @@ export const DocPage403 = ({ id }: DocProps) => {
$padding={{ bottom: '2rem' }} $padding={{ bottom: '2rem' }}
> >
<Image <Image
className="c__image-system-filter"
src={img403} src={img403}
alt={t('Image 403')} alt={t('Image 403')}
width={300} width={300}
@@ -77,7 +76,7 @@ export const DocPage403 = ({ id }: DocProps) => {
/> />
<Box $align="center" $gap="0.8rem"> <Box $align="center" $gap="0.8rem">
<Text as="p" $textAlign="center" $maxWidth="350px" $theme="primary"> <Text as="p" $textAlign="center" $maxWidth="350px" $theme="brand">
{hasRequested {hasRequested
? t('Your access request for this document is pending.') ? t('Your access request for this document is pending.')
: t('Insufficient access rights to view the document.')} : t('Insufficient access rights to view the document.')}
@@ -88,7 +87,6 @@ export const DocPage403 = ({ id }: DocProps) => {
as="p" as="p"
$maxWidth="320px" $maxWidth="320px"
$textAlign="center" $textAlign="center"
$variation="600"
$size="sm" $size="sm"
$margin={{ top: '0' }} $margin={{ top: '0' }}
> >
@@ -101,8 +99,9 @@ export const DocPage403 = ({ id }: DocProps) => {
<Box $direction="row" $gap="0.7rem"> <Box $direction="row" $gap="0.7rem">
<StyledLink href="/"> <StyledLink href="/">
<StyledButton <StyledButton
icon={<Icon iconName="house" $theme="primary" />} icon={<Icon iconName="house" $withThemeInherited />}
color="tertiary" color="brand"
variant="secondary"
> >
{t('Home')} {t('Home')}
</StyledButton> </StyledButton>

View File

@@ -98,7 +98,7 @@ export const ModalRemoveDoc = ({
<Button <Button
ref={cancelButtonRef} ref={cancelButtonRef}
aria-label={t('Cancel the deletion')} aria-label={t('Cancel the deletion')}
color="secondary" variant="secondary"
fullWidth fullWidth
onClick={handleClose} onClick={handleClose}
onKeyDown={handleCloseKeyDown} onKeyDown={handleCloseKeyDown}
@@ -107,7 +107,7 @@ export const ModalRemoveDoc = ({
</Button> </Button>
<Button <Button
aria-label={t('Delete document')} aria-label={t('Delete document')}
color="danger" color="error"
fullWidth fullWidth
onClick={handleDelete} onClick={handleDelete}
onKeyDown={handleDeleteKeyDown} onKeyDown={handleDeleteKeyDown}
@@ -130,7 +130,6 @@ export const ModalRemoveDoc = ({
id="modal-remove-doc-title" id="modal-remove-doc-title"
$margin="0" $margin="0"
$align="flex-start" $align="flex-start"
$variation="1000"
> >
{t('Delete a doc')} {t('Delete a doc')}
</Text> </Text>
@@ -144,7 +143,12 @@ export const ModalRemoveDoc = ({
> >
<Box className="--docs--modal-remove-doc"> <Box className="--docs--modal-remove-doc">
{!isError && ( {!isError && (
<Text $size="sm" $variation="600" $display="inline-block" as="p"> <Text
$size="sm"
$variation="secondary"
$display="inline-block"
as="p"
>
{hasChildren ? ( {hasChildren ? (
<Trans t={t}> <Trans t={t}>
This document and <strong>any sub-documents</strong> will be This document and <strong>any sub-documents</strong> will be

View File

@@ -33,7 +33,7 @@ export const SimpleDocItem = ({
showAccesses = false, showAccesses = false,
}: SimpleDocItemProps) => { }: SimpleDocItemProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { untitledDocument } = useTrans(); const { untitledDocument } = useTrans();
const { isChild } = useDocUtils(doc); const { isChild } = useDocUtils(doc);
@@ -63,13 +63,13 @@ export const SimpleDocItem = ({
<PinnedDocumentIcon <PinnedDocumentIcon
aria-hidden="true" aria-hidden="true"
data-testid="doc-pinned-icon" data-testid="doc-pinned-icon"
color={colorsTokens['primary-500']} color="var(--c--contextuals--content--semantic--info--tertiary)"
/> />
) : isChild ? ( ) : isChild ? (
<ChildDocument <ChildDocument
aria-hidden="true" aria-hidden="true"
data-testid="doc-child-icon" data-testid="doc-child-icon"
color={colorsTokens['primary-500']} color="var(--c--contextuals--content--semantic--info--tertiary)"
/> />
) : ( ) : (
<SimpleFileIcon <SimpleFileIcon
@@ -77,14 +77,13 @@ export const SimpleDocItem = ({
height="32px" height="32px"
aria-hidden="true" aria-hidden="true"
data-testid="doc-simple-icon" data-testid="doc-simple-icon"
color={colorsTokens['primary-500']} color="var(--c--contextuals--content--semantic--info--tertiary)"
/> />
)} )}
</Box> </Box>
<Box $justify="center" $overflow="auto"> <Box $justify="center" $overflow="auto">
<Text <Text
$size="sm" $size="sm"
$variation="1000"
$weight="500" $weight="500"
$css={ItemTextCss} $css={ItemTextCss}
data-testid="doc-title" data-testid="doc-title"
@@ -99,7 +98,7 @@ export const SimpleDocItem = ({
$margin={{ top: '-2px' }} $margin={{ top: '-2px' }}
aria-hidden="true" aria-hidden="true"
> >
<Text $variation="600" $size="xs"> <Text $size="xs" $variation="tertiary">
{DateTime.fromISO(doc.updated_at).toRelative()} {DateTime.fromISO(doc.updated_at).toRelative()}
</Text> </Text>
</Box> </Box>

View File

@@ -58,7 +58,7 @@ export const DocSearchFilters = ({
/> />
</Box> </Box>
{hasFilters && ( {hasFilters && (
<Button color="primary-text" size="small" onClick={onReset}> <Button color="brand" variant="tertiary" size="small" onClick={onReset}>
{t('Reset')} {t('Reset')}
</Button> </Button>
)} )}

View File

@@ -24,7 +24,11 @@ export const DocSearchItem = ({ doc }: DocSearchItemProps) => {
</Box> </Box>
} }
right={ right={
<Icon iconName="keyboard_return" $theme="primary" $variation="800" /> <Icon
iconName="keyboard_return"
$theme="brand"
$variation="secondary"
/>
} }
/> />
</Box> </Box>

View File

@@ -85,7 +85,8 @@ const DocSearchModalGlobal = ({
aria-label={t('Close the search modal')} aria-label={t('Close the search modal')}
onClick={modalProps.onClose} onClick={modalProps.onClose}
size="small" size="small"
color="primary-text" color="brand"
variant="tertiary"
/> />
</Box> </Box>
<QuickSearch <QuickSearch
@@ -112,7 +113,6 @@ const DocSearchModalGlobal = ({
$justify="center" $justify="center"
> >
<Image <Image
className="c__image-system-filter"
width={320} width={320}
src={EmptySearchIcon} src={EmptySearchIcon}
alt={t('No active search')} alt={t('No active search')}

View File

@@ -9,7 +9,7 @@
<path <path
id="&#244;&#128;&#153;&#160;" id="&#244;&#128;&#153;&#160;"
d="M5.99986 12.2256C5.99986 11.7946 6.25238 11.5791 6.75741 11.5791H10.4145C10.802 11.5791 11.2156 11.4811 11.6553 11.2852C12.0994 11.0893 12.5413 10.8302 12.981 10.508C13.4208 10.1902 13.8235 9.84192 14.1892 9.46314C14.5593 9.08437 14.864 8.70778 15.1035 8.33336L15.4496 7.80438C15.5802 7.59105 15.7718 7.48438 16.0243 7.48438C16.1897 7.48438 16.3334 7.5388 16.4553 7.64765C16.5816 7.76084 16.6447 7.91758 16.6447 8.11785C16.6447 8.30506 16.5837 8.48791 16.4618 8.66641L16.2398 9.01254C15.996 9.37389 15.7086 9.7309 15.3778 10.0835C15.0469 10.4362 14.6964 10.7606 14.3263 11.0566C13.9606 11.357 13.6058 11.6073 13.2619 11.8076C12.9179 12.0122 12.6153 12.1472 12.3541 12.2125V12.2386C12.6153 12.2996 12.9179 12.4324 13.2619 12.637C13.6058 12.8416 13.9606 13.0941 14.3263 13.3945C14.6921 13.695 15.0404 14.0193 15.3712 14.3676C15.7065 14.7203 15.996 15.0794 16.2398 15.4451L16.4618 15.7847C16.5837 15.9632 16.6447 16.1461 16.6447 16.3333C16.6447 16.5292 16.5837 16.6838 16.4618 16.797C16.3443 16.9102 16.1963 16.9668 16.0178 16.9668C15.7696 16.9668 15.5802 16.8601 15.4496 16.6468L15.1035 16.1243C14.864 15.7499 14.5593 15.3711 14.1892 14.988C13.8235 14.6092 13.4208 14.2588 12.981 13.9366C12.5413 13.6188 12.0994 13.3619 11.6553 13.166C11.2156 12.9701 10.802 12.8721 10.4145 12.8721H6.75741C6.25238 12.8721 5.99986 12.6566 5.99986 12.2256ZM14.3068 7.64112C14.1065 7.48438 14.0303 7.32329 14.0782 7.15785C14.1261 6.99677 14.2697 6.88139 14.5092 6.81173L17.0822 6.03459C17.2782 5.97364 17.4392 5.99323 17.5655 6.09337C17.6918 6.1935 17.7505 6.34371 17.7418 6.54398L17.6308 9.23457C17.6221 9.48274 17.5437 9.64818 17.3957 9.7309C17.252 9.81362 17.0822 9.78097 16.8863 9.63294L14.3068 7.64112ZM14.3198 16.7251L16.9516 14.8117C17.1519 14.6637 17.3239 14.6354 17.4675 14.7268C17.6112 14.8182 17.6831 14.9858 17.6831 15.2296L17.7157 17.9268C17.7157 18.127 17.6504 18.2729 17.5198 18.3643C17.3935 18.4601 17.2324 18.4753 17.0365 18.41L14.4896 17.5545C14.2545 17.4805 14.1152 17.3608 14.0717 17.1953C14.0281 17.0299 14.1108 16.8732 14.3198 16.7251Z" d="M5.99986 12.2256C5.99986 11.7946 6.25238 11.5791 6.75741 11.5791H10.4145C10.802 11.5791 11.2156 11.4811 11.6553 11.2852C12.0994 11.0893 12.5413 10.8302 12.981 10.508C13.4208 10.1902 13.8235 9.84192 14.1892 9.46314C14.5593 9.08437 14.864 8.70778 15.1035 8.33336L15.4496 7.80438C15.5802 7.59105 15.7718 7.48438 16.0243 7.48438C16.1897 7.48438 16.3334 7.5388 16.4553 7.64765C16.5816 7.76084 16.6447 7.91758 16.6447 8.11785C16.6447 8.30506 16.5837 8.48791 16.4618 8.66641L16.2398 9.01254C15.996 9.37389 15.7086 9.7309 15.3778 10.0835C15.0469 10.4362 14.6964 10.7606 14.3263 11.0566C13.9606 11.357 13.6058 11.6073 13.2619 11.8076C12.9179 12.0122 12.6153 12.1472 12.3541 12.2125V12.2386C12.6153 12.2996 12.9179 12.4324 13.2619 12.637C13.6058 12.8416 13.9606 13.0941 14.3263 13.3945C14.6921 13.695 15.0404 14.0193 15.3712 14.3676C15.7065 14.7203 15.996 15.0794 16.2398 15.4451L16.4618 15.7847C16.5837 15.9632 16.6447 16.1461 16.6447 16.3333C16.6447 16.5292 16.5837 16.6838 16.4618 16.797C16.3443 16.9102 16.1963 16.9668 16.0178 16.9668C15.7696 16.9668 15.5802 16.8601 15.4496 16.6468L15.1035 16.1243C14.864 15.7499 14.5593 15.3711 14.1892 14.988C13.8235 14.6092 13.4208 14.2588 12.981 13.9366C12.5413 13.6188 12.0994 13.3619 11.6553 13.166C11.2156 12.9701 10.802 12.8721 10.4145 12.8721H6.75741C6.25238 12.8721 5.99986 12.6566 5.99986 12.2256ZM14.3068 7.64112C14.1065 7.48438 14.0303 7.32329 14.0782 7.15785C14.1261 6.99677 14.2697 6.88139 14.5092 6.81173L17.0822 6.03459C17.2782 5.97364 17.4392 5.99323 17.5655 6.09337C17.6918 6.1935 17.7505 6.34371 17.7418 6.54398L17.6308 9.23457C17.6221 9.48274 17.5437 9.64818 17.3957 9.7309C17.252 9.81362 17.0822 9.78097 16.8863 9.63294L14.3068 7.64112ZM14.3198 16.7251L16.9516 14.8117C17.1519 14.6637 17.3239 14.6354 17.4675 14.7268C17.6112 14.8182 17.6831 14.9858 17.6831 15.2296L17.7157 17.9268C17.7157 18.127 17.6504 18.2729 17.5198 18.3643C17.3935 18.4601 17.2324 18.4753 17.0365 18.41L14.4896 17.5545C14.2545 17.4805 14.1152 17.3608 14.0717 17.1953C14.0281 17.0299 14.1108 16.8732 14.3198 16.7251Z"
fill="#000091" fill="currentColor"
/> />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -9,7 +9,7 @@
<path <path
id="v" id="v"
d="M4.6665 12.667V11.3337H9.39984C10.0998 11.3337 10.7082 11.1114 11.2248 10.667C11.7415 10.2225 11.9998 9.66699 11.9998 9.00033C11.9998 8.33366 11.7415 7.7781 11.2248 7.33366C10.7082 6.88921 10.0998 6.66699 9.39984 6.66699H5.19984L6.93317 8.40033L5.99984 9.33366L2.6665 6.00033L5.99984 2.66699L6.93317 3.60033L5.19984 5.33366H9.39984C10.4776 5.33366 11.4026 5.68366 12.1748 6.38366C12.9471 7.08366 13.3332 7.95588 13.3332 9.00033C13.3332 10.0448 12.9471 10.917 12.1748 11.617C11.4026 12.317 10.4776 12.667 9.39984 12.667H4.6665Z" d="M4.6665 12.667V11.3337H9.39984C10.0998 11.3337 10.7082 11.1114 11.2248 10.667C11.7415 10.2225 11.9998 9.66699 11.9998 9.00033C11.9998 8.33366 11.7415 7.7781 11.2248 7.33366C10.7082 6.88921 10.0998 6.66699 9.39984 6.66699H5.19984L6.93317 8.40033L5.99984 9.33366L2.6665 6.00033L5.99984 2.66699L6.93317 3.60033L5.19984 5.33366H9.39984C10.4776 5.33366 11.4026 5.68366 12.1748 6.38366C12.9471 7.08366 13.3332 7.95588 13.3332 9.00033C13.3332 10.0448 12.9471 10.917 12.1748 11.617C11.4026 12.317 10.4776 12.667 9.39984 12.667H4.6665Z"
fill="#000091" fill="currentColor"
/> />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 725 B

After

Width:  |  Height:  |  Size: 730 B

View File

@@ -1,8 +1,7 @@
import { Button } from '@openfun/cunningham-react'; import { Button } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { Box, Text } from '@/components'; import { Box, Card, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { Doc, KEY_DOC, KEY_LIST_DOC } from '@/docs/doc-management'; import { Doc, KEY_DOC, KEY_LIST_DOC } from '@/docs/doc-management';
@@ -17,29 +16,29 @@ interface DocDesynchronizedProps {
export const DocDesynchronized = ({ doc }: DocDesynchronizedProps) => { export const DocDesynchronized = ({ doc }: DocDesynchronizedProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { mutate: updateDocLink } = useUpdateDocLink({ const { mutate: updateDocLink } = useUpdateDocLink({
listInvalidQueries: [KEY_LIST_DOC, KEY_DOC], listInvalidQueries: [KEY_LIST_DOC, KEY_DOC],
}); });
return ( return (
<Box <Card
$background={colorsTokens['primary-100']}
$padding="3xs" $padding="3xs"
$direction="row" $direction="row"
$align="center" $align="center"
$justify="space-between" $justify="space-between"
$gap={spacingsTokens['4xs']} $gap={spacingsTokens['4xs']}
$color={colorsTokens['primary-800']} $theme="brand"
$css={css`
border: 1px solid ${colorsTokens['primary-300']};
border-radius: ${spacingsTokens['2xs']};
`}
> >
<Box $direction="row" $align="center" $gap={spacingsTokens['3xs']}> <Box
$withThemeInherited
$direction="row"
$align="center"
$gap={spacingsTokens['3xs']}
>
<Desync /> <Desync />
<Text $size="xs" $theme="primary" $variation="800" $weight="400"> <Text $size="xs" $withThemeInherited $weight="400">
{t('The link sharing rules differ from the parent document')} {t('The link sharing rules differ from the parent document')}
</Text> </Text>
</Box> </Box>
@@ -53,12 +52,13 @@ export const DocDesynchronized = ({ doc }: DocDesynchronizedProps) => {
}) })
} }
size="small" size="small"
color="primary-text" color="brand"
variant="tertiary"
icon={<Undo />} icon={<Undo />}
> >
{t('Restore')} {t('Restore')}
</Button> </Button>
)} )}
</Box> </Card>
); );
}; };

View File

@@ -41,21 +41,16 @@ export const DocInheritedShareContent = ({
}} }}
> >
<Box $direction="row" $align="center" $gap={spacingsTokens['4xs']}> <Box $direction="row" $align="center" $gap={spacingsTokens['4xs']}>
<Text $variation="1000" $weight="bold" $size="sm"> <Text $weight="bold" $size="sm">
{t('People with access via the parent document')} {t('People with access via the parent document')}
</Text> </Text>
<Box> <Box>
<StyledLink href={`/docs/${rawAccesses[0].document.id}`}> <StyledLink href={`/docs/${rawAccesses[0].document.id}`}>
<Button <Button
size="small" size="small"
icon={ icon={<Icon iconName="open_in_new" />}
<Icon color="neutral"
$theme="greyscale" variant="tertiary"
$variation="600"
iconName="open_in_new"
/>
}
color="tertiary-text"
/> />
</StyledLink> </StyledLink>
</Box> </Box>

View File

@@ -106,7 +106,12 @@ export const DocRoleDropdown = ({
if (!canUpdate) { if (!canUpdate) {
return ( return (
<Text aria-label={t('Document role text')} $variation="600"> <Text
$variation="tertiary"
aria-label={t('Document role text')}
$weight={500}
$size="s"
>
{transRole(currentRole)} {transRole(currentRole)}
</Text> </Text>
); );
@@ -121,7 +126,8 @@ export const DocRoleDropdown = ({
})} })}
showArrow={true} showArrow={true}
arrowCss={css` arrowCss={css`
color: var(--c--theme--colors--primary-800) !important; color: var(--c--contextuals--content--semantic--brand--tertiary);
font-size: 16px;
`} `}
testId="doc-role-dropdown" testId="doc-role-dropdown"
options={[ options={[
@@ -132,8 +138,14 @@ export const DocRoleDropdown = ({
callback: onRemove, callback: onRemove,
}, },
]} ]}
buttonCss={css`
&:hover {
background: none;
}
font-size: 12px;
`}
> >
<Text $theme="primary" $variation="800"> <Text $theme="brand" $variation="tertiary">
{transRole(currentRole)} {transRole(currentRole)}
</Text> </Text>
</DropdownMenu> </DropdownMenu>

View File

@@ -83,7 +83,8 @@ const DocShareAccessRequestItem = ({ doc, accessRequest }: Props) => {
})} })}
/> />
<Button <Button
color="tertiary" color="brand"
variant="tertiary"
onClick={() => onClick={() =>
acceptDocAccessRequests({ acceptDocAccessRequests({
docId: doc.id, docId: doc.id,
@@ -106,7 +107,7 @@ const DocShareAccessRequestItem = ({ doc, accessRequest }: Props) => {
} }
aria-label={t('Close the access request modal')} aria-label={t('Close the access request modal')}
> >
<Icon iconName="close" $variation="600" $size="16px" /> <Icon iconName="close" $size="16px" />
</BoxButton> </BoxButton>
)} )}
</Box> </Box>
@@ -197,7 +198,7 @@ export const ButtonAccessRequest = ({
if (docAccessError?.status === 404) { if (docAccessError?.status === 404) {
return ( return (
<Text $maxWidth="320px" $textAlign="center" $variation="600" $size="sm"> <Text $maxWidth="320px" $textAlign="center" $size="sm">
{t( {t(
'As this is a sub-document, please request access to the parent document to enable these features.', 'As this is a sub-document, please request access to the parent document to enable these features.',
)} )}

View File

@@ -5,10 +5,9 @@ import {
} from '@openfun/cunningham-react'; } from '@openfun/cunningham-react';
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { APIError } from '@/api'; import { APIError } from '@/api';
import { Box } from '@/components'; import { Box, Card } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { Doc, Role } from '@/docs/doc-management'; import { Doc, Role } from '@/docs/doc-management';
import { User } from '@/features/auth'; import { User } from '@/features/auth';
@@ -41,7 +40,7 @@ export const DocShareAddMemberList = ({
const { toast } = useToastProvider(); const { toast } = useToastProvider();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const [invitationRole, setInvitationRole] = useState<Role>(Role.EDITOR); const [invitationRole, setInvitationRole] = useState<Role>(Role.EDITOR);
const canShare = doc.abilities.accesses_manage; const canShare = doc.abilities.accesses_manage;
const { mutateAsync: createInvitation } = useCreateDocInvitation(); const { mutateAsync: createInvitation } = useCreateDocInvitation();
@@ -116,17 +115,16 @@ export const DocShareAddMemberList = ({
: t('Invite {{count}} members', { count: selectedUsers.length }); : t('Invite {{count}} members', { count: selectedUsers.length });
return ( return (
<Box <Card
className="--docs--doc-share-add-member-list"
data-testid="doc-share-add-member-list" data-testid="doc-share-add-member-list"
$direction="row" $direction="row"
$padding={spacingsTokens.sm}
$align="center" $align="center"
$background={colorsTokens['greyscale-050']} $padding={spacingsTokens.sm}
$radius={spacingsTokens['3xs']} $scope="surface"
$css={css` $theme="tertiary"
border: 1px solid ${colorsTokens['greyscale-200']}; $variation=""
`} $border="1px solid var(--c--contextuals--border--semantic--contextual--primary)"
className="--docs--doc-share-add-member-list"
> >
<Box <Box
$direction="row" $direction="row"
@@ -148,6 +146,7 @@ export const DocShareAddMemberList = ({
canUpdate={canShare} canUpdate={canShare}
currentRole={invitationRole} currentRole={invitationRole}
onSelectRole={setInvitationRole} onSelectRole={setInvitationRole}
ariaLabel={t('Invite new members')}
/> />
<Button <Button
onClick={() => void onInvite()} onClick={() => void onInvite()}
@@ -158,6 +157,6 @@ export const DocShareAddMemberList = ({
{t('Invite')} {t('Invite')}
</Button> </Button>
</Box> </Box>
</Box> </Card>
); );
}; };

View File

@@ -1,8 +1,6 @@
import { Button } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { Box, Icon, Text } from '@/components'; import { Box, BoxButton, Icon, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { User } from '@/features/auth'; import { User } from '@/features/auth';
@@ -12,11 +10,11 @@ type Props = {
}; };
export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => { export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { spacingsTokens, colorsTokens, fontSizesTokens } = const { spacingsTokens } = useCunninghamTheme();
useCunninghamTheme();
return ( return (
<Box <Box
className="--docs--doc-share-add-member-list-item"
data-testid={`doc-share-add-member-${user.email}`} data-testid={`doc-share-add-member-${user.email}`}
$radius={spacingsTokens['3xs']} $radius={spacingsTokens['3xs']}
$direction="row" $direction="row"
@@ -24,30 +22,27 @@ export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => {
$justify="center" $justify="center"
$align="center" $align="center"
$gap={spacingsTokens['3xs']} $gap={spacingsTokens['3xs']}
$background={colorsTokens['greyscale-250']}
$padding={{ $padding={{
left: spacingsTokens['xs'], left: spacingsTokens['xs'],
right: spacingsTokens['4xs'], right: spacingsTokens['4xs'],
vertical: spacingsTokens['4xs'], vertical: spacingsTokens['4xs'],
}} }}
$css={css` $withThemeBG
color: ${colorsTokens['greyscale-1000']}; $theme="neutral"
font-size: ${fontSizesTokens['xs']}; $variation="secondary"
`}
className="--docs--doc-share-add-member-list-item"
> >
<Text $variation="1000" $size="xs"> <Text $withThemeInherited $size="xs">
{user.full_name || user.email} {user.full_name || user.email}
</Text> </Text>
<Button <BoxButton
color="tertiary-text"
size="nano"
onClick={() => onRemoveUser?.(user)} onClick={() => onRemoveUser?.(user)}
icon={<Icon $variation="600" $size="sm" iconName="close" />}
aria-label={t('Remove {{name}} from the invite list', { aria-label={t('Remove {{name}} from the invite list', {
name: user.full_name || user.email, name: user.full_name || user.email,
})} })}
/> $withThemeInherited
>
<Icon $withThemeInherited $size="sm" iconName="close" />
</BoxButton>
</Box> </Box>
); );
}; };

View File

@@ -262,7 +262,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
<Text <Text
$maxWidth="320px" $maxWidth="320px"
$textAlign="center" $textAlign="center"
$variation="600" $variation="secondary"
$size="sm" $size="sm"
as="p" as="p"
> >
@@ -272,7 +272,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
</Text> </Text>
<ButtonAccessRequest <ButtonAccessRequest
docId={doc.id} docId={doc.id}
color="tertiary" variant="secondary"
size="small" size="small"
/> />
</Box> </Box>

View File

@@ -2,7 +2,7 @@ import { Button } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components'; import { css } from 'styled-components';
import { Box, HorizontalSeparator } from '@/components'; import { Box, HorizontalSeparator, Icon } from '@/components';
import { Doc, useCopyDocLink } from '@/docs/doc-management'; import { Doc, useCopyDocLink } from '@/docs/doc-management';
import { DocVisibility } from './DocVisibility'; import { DocVisibility } from './DocVisibility';
@@ -38,18 +38,12 @@ export const DocShareModalFooter = ({
<Button <Button
fullWidth={false} fullWidth={false}
onClick={copyDocLink} onClick={copyDocLink}
color="tertiary" variant="secondary"
icon={ icon={<Icon iconName="add_link" $withThemeInherited />}
<span className="material-icons" aria-hidden={true}>
add_link
</span>
}
> >
{t('Copy link')} {t('Copy link')}
</Button> </Button>
<Button onClick={onClose} color="primary"> <Button onClick={onClose}>{t('OK')}</Button>
{t('OK')}
</Button>
</Box> </Box>
</Box> </Box>
); );

View File

@@ -34,7 +34,7 @@ interface DocVisibilityProps {
export const DocVisibility = ({ doc }: DocVisibilityProps) => { export const DocVisibility = ({ doc }: DocVisibilityProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const canManage = doc.abilities.accesses_manage; const canManage = doc.abilities.accesses_manage;
const docLinkReach = getDocLinkReach(doc); const docLinkReach = getDocLinkReach(doc);
const docLinkRole = getDocLinkRole(doc); const docLinkRole = getDocLinkRole(doc);
@@ -123,7 +123,7 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
$gap={spacingsTokens['base']} $gap={spacingsTokens['base']}
className="--docs--doc-visibility" className="--docs--doc-visibility"
> >
<Text $weight="700" $size="sm" $variation="700"> <Text $weight="700" $size="sm">
{t('Link settings')} {t('Link settings')}
</Text> </Text>
{isDesynchronized && <DocDesynchronized doc={doc} />} {isDesynchronized && <DocDesynchronized doc={doc} />}
@@ -145,7 +145,9 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
testId="doc-visibility" testId="doc-visibility"
label={t('Document visibility')} label={t('Document visibility')}
arrowCss={css` arrowCss={css`
color: ${colorsTokens['primary-800']} !important; color: var(
--c--contextuals--content--semantic--brand--tertiary
) !important;
`} `}
buttonCss={css` buttonCss={css`
&:hover { &:hover {
@@ -163,24 +165,24 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
} }
options={linkReachOptions} options={linkReachOptions}
> >
<Box $direction="row" $align="center" $gap={spacingsTokens['3xs']}> <Box
$theme={canManage ? 'brand' : 'gray'}
$variation={canManage ? 'tertiary' : 'primary'}
$direction="row"
$align="center"
$gap={spacingsTokens['3xs']}
>
<Icon <Icon
$theme={canManage ? 'primary' : 'greyscale'}
$variation={canManage ? '800' : '600'}
iconName={linkReachChoices[docLinkReach].icon} iconName={linkReachChoices[docLinkReach].icon}
$withThemeInherited
/> />
<Text <Text $weight="500" $size="md" $withThemeInherited>
$theme={canManage ? 'primary' : 'greyscale'}
$variation={canManage ? '800' : '600'}
$weight="500"
$size="md"
>
{linkReachChoices[docLinkReach].label} {linkReachChoices[docLinkReach].label}
</Text> </Text>
</Box> </Box>
</DropdownMenu> </DropdownMenu>
{isDesktop && ( {isDesktop && (
<Text $size="xs" $variation="600" $weight="400"> <Text $size="xs" $variation="secondary" $weight="400">
{description} {description}
</Text> </Text>
)} )}
@@ -193,6 +195,13 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
&:hover { &:hover {
background-color: unset; background-color: unset;
} }
font-size: 12px;
`}
arrowCss={css`
color: var(
--c--contextuals--content--semantic--brand--tertiary
) !important;
font-size: 16px;
`} `}
disabled={!canManage} disabled={!canManage}
showArrow={true} showArrow={true}
@@ -206,7 +215,7 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
} }
label={t('Document access mode')} label={t('Document access mode')}
> >
<Text $weight="initial" $variation="600" $theme="primary"> <Text $weight="initial" $theme="brand" $variation="tertiary">
{linkModeTranslations[docLinkRole]} {linkModeTranslations[docLinkRole]}
</Text> </Text>
</DropdownMenu> </DropdownMenu>
@@ -214,7 +223,7 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
)} )}
</Box> </Box>
{!isDesktop && ( {!isDesktop && (
<Text $size="xs" $variation="600"> <Text $size="xs" $variation="secondary">
{description} {description}
</Text> </Text>
)} )}

View File

@@ -35,16 +35,14 @@ export const SearchUserRow = ({
> >
<UserAvatar <UserAvatar
fullName={user.full_name || user.email} fullName={user.full_name || user.email}
background={ background={isInvitation ? colorsTokens['gray-400'] : undefined}
isInvitation ? colorsTokens['greyscale-400'] : undefined
}
/> />
<Box $direction="column"> <Box $direction="column">
<Text $size="sm" $weight="500" $variation="1000"> <Text $size="sm" $weight="500">
{hasFullName ? user.full_name : user.email} {hasFullName ? user.full_name : user.email}
</Text> </Text>
{hasFullName && ( {hasFullName && (
<Text $size="xs" $margin={{ top: '-2px' }} $variation="600"> <Text $size="xs" $margin={{ top: '-2px' }} $variation="secondary">
{user.email} {user.email}
</Text> </Text>
)} )}

View File

@@ -57,15 +57,15 @@ export const Heading = ({
block: 'start', block: 'start',
}); });
}} }}
$radius="4px" $radius="var(--c--globals--spacings--st)"
$background={isActive ? `${colorsTokens['greyscale-100']}` : 'none'} $background={isActive ? `${colorsTokens['gray-100']}` : 'none'}
$css={css` $css={css`
text-align: left; text-align: left;
&:focus-visible { &:focus-visible {
/* Scoped focus style: same footprint as hover, with theme shadow */ /* Scoped focus style: same footprint as hover, with theme shadow */
outline: none; outline: none;
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']}; box-shadow: 0 0 0 2px ${colorsTokens['brand-400']};
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
`} `}
className="--docs--table-content-heading" className="--docs--table-content-heading"
@@ -76,7 +76,6 @@ export const Heading = ({
<Text <Text
$width="100%" $width="100%"
$padding={{ vertical: 'xtiny', left: leftPaddingMap[level] }} $padding={{ vertical: 'xtiny', left: leftPaddingMap[level] }}
$variation={isActive ? '1000' : '700'}
$weight={isHighlight ? 'bold' : 'normal'} $weight={isHighlight ? 'bold' : 'normal'}
$css="overflow-wrap: break-word;" $css="overflow-wrap: break-word;"
$hasTransition $hasTransition

View File

@@ -111,11 +111,11 @@ export const TableContent = () => {
$position="sticky" $position="sticky"
aria-label={t('Summary')} aria-label={t('Summary')}
$css={css` $css={css`
top: 0; top: var(--c--globals--spacings--0);
border: 1px solid ${colorsTokens['greyscale-300']}; border: 1px solid ${colorsTokens['brand-100']};
overflow: hidden; overflow: hidden;
border-radius: ${spacingsTokens['3xs']}; border-radius: ${spacingsTokens['3xs']};
background: ${colorsTokens['greyscale-000']}; background: ${colorsTokens['gray-000']};
${isHover && ${isHover &&
css` css`
display: flex; display: flex;
@@ -138,22 +138,19 @@ export const TableContent = () => {
aria-expanded={isHover} aria-expanded={isHover}
aria-controls="toc-list" aria-controls="toc-list"
$css={css` $css={css`
&:hover {
background: ${colorsTokens['primary-100']};
}
&:focus-visible { &:focus-visible {
outline: none; outline: none;
box-shadow: 0 0 0 4px ${colorsTokens['primary-400']}; box-shadow: 0 0 0 4px ${colorsTokens['brand-400']};
background: ${colorsTokens['primary-100']}; background: ${colorsTokens['brand-100']};
width: 90%; width: 90%;
height: 90%; height: 90%;
} }
`} `}
> >
<Icon <Icon
$theme="brand"
$variation="tertiary"
iconName="list" iconName="list"
$theme="primary"
$variation="800"
variant="symbols-outlined" variant="symbols-outlined"
/> />
</BoxButton> </BoxButton>
@@ -173,7 +170,7 @@ export const TableContent = () => {
$justify="space-between" $justify="space-between"
$align="center" $align="center"
> >
<Text $weight="500" $size="sm" $variation="800" $theme="primary"> <Text $weight="500" $size="sm">
{t('Summary')} {t('Summary')}
</Text> </Text>
<BoxButton <BoxButton
@@ -188,12 +185,12 @@ export const TableContent = () => {
transform: rotate(180deg); transform: rotate(180deg);
&:focus-visible { &:focus-visible {
outline: none; outline: none;
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']}; box-shadow: 0 0 0 2px ${colorsTokens['brand-400']};
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
`} `}
> >
<Icon iconName="menu_open" $theme="primary" $variation="800" /> <Icon iconName="menu_open" $theme="brand" $variation="tertiary" />
</BoxButton> </BoxButton>
</Box> </Box>
<Box <Box

View File

@@ -1,4 +1,5 @@
import { import {
TreeViewDataType,
TreeViewItem, TreeViewItem,
TreeViewNodeProps, TreeViewNodeProps,
useTreeContext, useTreeContext,
@@ -39,7 +40,7 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
const treeContext = useTreeContext<Doc>(); const treeContext = useTreeContext<Doc>();
const { untitledDocument } = useTrans(); const { untitledDocument } = useTrans();
const { node } = props; const { node } = props;
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -68,7 +69,10 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
node.open(); node.open();
router.push(`/docs/${createdDoc.id}`); router.push(`/docs/${createdDoc.id}`);
treeContext?.treeData.setChildren(node.data.value.id, allChildren); treeContext?.treeData.setChildren(
node.data.value.id,
allChildren as TreeViewDataType<Doc>[],
);
treeContext?.treeData.setSelectedNode(createdDoc); treeContext?.treeData.setSelectedNode(createdDoc);
togglePanel(); togglePanel();
}) })
@@ -114,33 +118,24 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
aria-expanded={hasChildren ? isExpanded : undefined} aria-expanded={hasChildren ? isExpanded : undefined}
aria-disabled={isDisabled} aria-disabled={isDisabled}
$css={css` $css={css`
background-color: ${menuOpen background-color: var(--c--globals--colors--gray-000);
? 'var(--c--theme--colors--greyscale-100)'
: 'var(--c--theme--colors--greyscale-000)'};
.light-doc-item-actions { .light-doc-item-actions {
display: ${menuOpen || !isDesktop ? 'flex' : 'none'}; display: ${menuOpen || !isDesktop ? 'flex' : 'none'};
position: absolute; position: absolute;
right: 0; right: var(--c--globals--spacings--0);
background: ${isDesktop
? 'var(--c--theme--colors--greyscale-100)'
: 'var(--c--theme--colors--greyscale-000)'};
}
.c__tree-view--node.isSelected {
.light-doc-item-actions {
background: var(--c--theme--colors--greyscale-100);
}
} }
.c__tree-view--node.isFocused { .c__tree-view--node.isFocused {
outline: none !important; outline: none !important;
box-shadow: 0 0 0 2px var(--c--theme--colors--primary-500) !important; box-shadow: 0 0 0 2px var(--c--globals--colors--brand-500) !important;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
&:hover { &:hover {
background-color: var(--c--theme--colors--greyscale-100); background-color: var(
border-radius: 4px; --c--contextuals--background--semantic--gray--tertiary
);
border-radius: var(--c--globals--spacings--st);
.light-doc-item-actions { .light-doc-item-actions {
display: flex; display: flex;
background: var(--c--theme--colors--greyscale-100);
} }
} }
.row.preview & { .row.preview & {
@@ -152,7 +147,9 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
<DocIcon <DocIcon
emoji={emoji} emoji={emoji}
withEmojiPicker={doc.abilities.partial_update} withEmojiPicker={doc.abilities.partial_update}
defaultIcon={<SubPageIcon color={colorsTokens['primary-400']} />} defaultIcon={
<SubPageIcon color="var(--c--contextuals--content--semantic--info--tertiary)" />
}
$size="sm" $size="sm"
docId={doc.id} docId={doc.id}
title={doc.title} title={doc.title}
@@ -187,15 +184,14 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
overflow: hidden; overflow: hidden;
`} `}
> >
<Text $css={ItemTextCss} $size="sm" $variation="1000"> <Text $css={ItemTextCss} $size="sm">
{displayTitle} {displayTitle}
</Text> </Text>
{doc.nb_accesses_direct >= 1 && ( {doc.nb_accesses_direct >= 1 && (
<Icon <Icon
variant="filled" variant="filled"
iconName="group" iconName="group"
$size="16px" $size="md"
$variation="400"
aria-hidden="true" aria-hidden="true"
/> />
)} )}

View File

@@ -215,24 +215,26 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
onKeyDown={handleRootKeyDown} onKeyDown={handleRootKeyDown}
$css={css` $css={css`
padding: ${spacingsTokens['2xs']}; padding: ${spacingsTokens['2xs']};
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
width: 100%; width: 100%;
background-color: ${rootIsSelected || rootActionsOpen background-color: ${rootIsSelected || rootActionsOpen
? 'var(--c--theme--colors--greyscale-100)' ? 'var(--c--contextuals--background--semantic--contextual--primary)'
: 'transparent'}; : 'transparent'};
&:hover { &:hover {
background-color: var(--c--theme--colors--greyscale-100); background-color: var(
--c--contextuals--background--semantic--contextual--primary
);
} }
&:focus-visible { &:focus-visible {
outline: none !important; outline: none !important;
box-shadow: 0 0 0 2px var(--c--theme--colors--primary-500) !important; box-shadow: 0 0 0 2px var(--c--globals--colors--brand-500) !important;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
.doc-tree-root-item-actions { .doc-tree-root-item-actions {
display: 'flex'; display: flex;
opacity: ${rootActionsOpen ? '1' : '0'}; opacity: ${rootActionsOpen ? '1' : '0'};
&:has(.isOpen) { &:has(.isOpen) {

View File

@@ -119,7 +119,7 @@ export const DocTreeItemActions = ({
: []), : []),
{ {
label: t('Duplicate'), label: t('Duplicate'),
icon: <Icon $variation="600" iconName="content_copy" />, icon: <Icon iconName="content_copy" />,
isDisabled: !doc.abilities.duplicate, isDisabled: !doc.abilities.duplicate,
callback: () => { callback: () => {
duplicateDoc({ duplicateDoc({
@@ -180,8 +180,8 @@ export const DocTreeItemActions = ({
}} }}
iconName="more_horiz" iconName="more_horiz"
variant="filled" variant="filled"
$theme="primary" $theme="brand"
$variation="600" $variation="secondary"
aria-label={t('More options')} aria-label={t('More options')}
/> />
</DropdownMenu> </DropdownMenu>
@@ -195,16 +195,12 @@ export const DocTreeItemActions = ({
parentId: doc.id, parentId: doc.id,
}); });
}} }}
color="primary" $theme="brand"
$variation="secondary"
aria-label={t('Add a sub page')} aria-label={t('Add a sub page')}
data-testid="doc-tree-item-actions-add-child" data-testid="doc-tree-item-actions-add-child"
> >
<Icon <Icon variant="filled" $color="inherit" iconName="add_box" />
variant="filled"
$variation="800"
$theme="primary"
iconName="add_box"
/>
</BoxButton> </BoxButton>
)} )}
</Box> </Box>

View File

@@ -74,7 +74,7 @@ export const ModalConfirmationVersion = ({
<> <>
<Button <Button
aria-label={`${t('Cancel')} - ${t('Warning')}`} aria-label={`${t('Cancel')} - ${t('Warning')}`}
color="secondary" variant="secondary"
fullWidth fullWidth
onClick={() => onClose()} onClick={() => onClose()}
> >
@@ -82,7 +82,7 @@ export const ModalConfirmationVersion = ({
</Button> </Button>
<Button <Button
aria-label={t('Restore')} aria-label={t('Restore')}
color="danger" color="error"
fullWidth fullWidth
onClick={() => { onClick={() => {
if (!version?.content) { if (!version?.content) {
@@ -109,7 +109,6 @@ export const ModalConfirmationVersion = ({
id="modal-confirmation-version-title" id="modal-confirmation-version-title"
$size="h6" $size="h6"
$align="flex-start" $align="flex-start"
$variation="1000"
> >
{t('Warning')} {t('Warning')}
</Text> </Text>
@@ -117,10 +116,10 @@ export const ModalConfirmationVersion = ({
> >
<Box className="--docs--modal-confirmation-version"> <Box className="--docs--modal-confirmation-version">
<Box> <Box>
<Text $variation="600" as="p"> <Text $variation="secondary" as="p">
{t('Your current document will revert to this version.')} {t('Your current document will revert to this version.')}
</Text> </Text>
<Text $variation="600" as="p"> <Text $variation="secondary" as="p">
{t('If a member is editing, his works can be lost.')} {t('If a member is editing, his works can be lost.')}
</Text> </Text>
</Box> </Box>

View File

@@ -102,7 +102,7 @@ export const ModalSelectVersion = ({
$height="calc(100vh - 2em - 12px)" $height="calc(100vh - 2em - 12px)"
$css={css` $css={css`
overflow-y: hidden; overflow-y: hidden;
border-left: 1px solid var(--c--theme--colors--greyscale-200); border-left: 1px solid var(--c--globals--colors--gray-200);
`} `}
> >
<Box <Box
@@ -118,12 +118,11 @@ export const ModalSelectVersion = ({
$direction="row" $direction="row"
$align="center" $align="center"
$css={css` $css={css`
border-bottom: 1px solid border-bottom: 1px solid var(--c--globals--colors--gray-200);
var(--c--theme--colors--greyscale-200);
`} `}
$padding="sm" $padding="sm"
> >
<Text $size="h6" $variation="1000" $weight="bold"> <Text $size="h6" $weight="bold">
{t('History')} {t('History')}
</Text> </Text>
<ButtonCloseModal <ButtonCloseModal
@@ -143,14 +142,13 @@ export const ModalSelectVersion = ({
<Box <Box
$padding="xs" $padding="xs"
$css={css` $css={css`
border-top: 1px solid var(--c--theme--colors--greyscale-200); border-top: 1px solid var(--c--globals--colors--gray-200);
`} `}
> >
<Button <Button
fullWidth fullWidth
disabled={!selectedVersionId} disabled={!selectedVersionId}
onClick={restoreModal.open} onClick={restoreModal.open}
color="primary"
> >
{t('Restore')} {t('Restore')}
</Button> </Button>

View File

@@ -32,13 +32,13 @@ export const VersionItem = ({
<Box <Box
$width="100%" $width="100%"
as="li" as="li"
$background={isActive ? colorsTokens['greyscale-100'] : 'transparent'} $background={isActive ? colorsTokens['gray-100'] : 'transparent'}
$radius={spacingsTokens['3xs']} $radius={spacingsTokens['3xs']}
$css={` $css={`
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: ${colorsTokens['greyscale-100']}; background: ${colorsTokens['gray-100']};
} }
`} `}
$hasTransition $hasTransition
@@ -53,7 +53,7 @@ export const VersionItem = ({
$width="100%" $width="100%"
> >
<Box $direction="row" $gap="0.5rem" $align="center"> <Box $direction="row" $gap="0.5rem" $align="center">
<Text $weight="bold" $size="sm" $variation="1000"> <Text $weight="bold" $size="sm">
{text} {text}
</Text> </Text>
</Box> </Box>

View File

@@ -6,7 +6,7 @@ import { useQueryClient } from '@tanstack/react-query';
import { useMemo, useRef } from 'react'; import { useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AlertModal, Box, Text } from '@/components'; import { AlertModal, Card, Text } from '@/components';
import { Doc, KEY_LIST_DOC } from '@/docs/doc-management'; import { Doc, KEY_LIST_DOC } from '@/docs/doc-management';
import { import {
getDocAccesses, getDocAccesses,
@@ -147,19 +147,8 @@ export const DraggableDocGridContentList = ({
return selectedDoc?.title || t('Unnamed document'); return selectedDoc?.title || t('Unnamed document');
}, [canDrag, canDrop, selectedDoc, t]); }, [canDrag, canDrop, selectedDoc, t]);
const overlayBgColor = useMemo(() => { const cannotMoveDoc =
if (!canDrag) { !canDrag || (canDrop !== undefined && !canDrop) || isError;
return 'var(--c--theme--colors--danger-600)';
}
if (canDrop !== undefined && !canDrop) {
return 'var(--c--theme--colors--danger-600)';
}
if (isError) {
return 'var(--c--theme--colors--danger-600)';
}
return '#5858D3';
}, [canDrag, canDrop, isError]);
if (docs.length === 0) { if (docs.length === 0) {
return null; return null;
@@ -183,20 +172,20 @@ export const DraggableDocGridContentList = ({
/> />
))} ))}
<DragOverlay dropAnimation={null}> <DragOverlay dropAnimation={null}>
<Box <Card
$width="fit-content" $width="fit-content"
$padding={{ horizontal: 'xs', vertical: '3xs' }}
$radius="12px" $radius="12px"
$background={overlayBgColor}
data-testid="drag-doc-overlay" data-testid="drag-doc-overlay"
$height="auto"
role="alert" role="alert"
aria-label={t('Drag and drop status')} aria-label={t('Drag and drop status')}
$theme={cannotMoveDoc ? 'error' : 'brand'}
$variation="tertiary"
$scope="semantic"
> >
<Text $size="xs" $variation="000" $weight="500"> <Text $size="xs" $weight="500" $withThemeInherited>
{overlayText} {overlayText}
</Text> </Text>
</Box> </Card>
</DragOverlay> </DragOverlay>
</DndContext> </DndContext>
{modalConfirmation.isOpen && ( {modalConfirmation.isOpen && (

View File

@@ -98,18 +98,13 @@ export const DocsGrid = ({
bottom: 'md', bottom: 'md',
}} }}
> >
<Text <Text as="h2" $size="h4" $margin={{ top: '0px', bottom: '10px' }}>
as="h2"
$size="h4"
$variation="1000"
$margin={{ top: '0px', bottom: '10px' }}
>
{title} {title}
</Text> </Text>
{!hasDocs && !loading && ( {!hasDocs && !loading && (
<Box $padding={{ vertical: 'sm' }} $align="center" $justify="center"> <Box $padding={{ vertical: 'sm' }} $align="center" $justify="center">
<Text $size="sm" $variation="600" $weight="700"> <Text $size="sm" $weight="700">
{t('No documents found')} {t('No documents found')}
</Text> </Text>
</Box> </Box>
@@ -126,7 +121,7 @@ export const DocsGrid = ({
role="row" role="row"
> >
<Box $flex={flexLeft} $padding="3xs" role="columnheader"> <Box $flex={flexLeft} $padding="3xs" role="columnheader">
<Text $size="xs" $variation="600" $weight="500"> <Text $size="xs" $variation="secondary" $weight="500">
{t('Name')} {t('Name')}
</Text> </Text>
</Box> </Box>
@@ -136,7 +131,7 @@ export const DocsGrid = ({
$padding={{ vertical: '3xs' }} $padding={{ vertical: '3xs' }}
role="columnheader" role="columnheader"
> >
<Text $size="xs" $weight="500" $variation="600"> <Text $size="xs" $weight="500" $variation="secondary">
{DocDefaultFilter.TRASHBIN === target {DocDefaultFilter.TRASHBIN === target
? t('Days remaining') ? t('Days remaining')
: t('Updated at')} : t('Updated at')}
@@ -162,7 +157,8 @@ export const DocsGrid = ({
{!isFetching && hasNextPage && ( {!isFetching && hasNextPage && (
<Button <Button
onClick={() => void fetchNextPage()} onClick={() => void fetchNextPage()}
color="primary-text" color="brand"
variant="tertiary"
> >
{t('More docs')} {t('More docs')}
</Button> </Button>

View File

@@ -89,12 +89,17 @@ export const DocsGridActions = ({
options={options} options={options}
label={menuLabel} label={menuLabel}
aria-label={t('More options')} aria-label={t('More options')}
buttonCss={css`
&:hover {
background-color: unset;
}
`}
> >
<Icon <Icon
data-testid={`docs-grid-actions-button-${doc.id}`} data-testid={`docs-grid-actions-button-${doc.id}`}
iconName="more_horiz" iconName="more_horiz"
$theme="primary" $theme="brand"
$variation="600" $variation="secondary"
$css={css` $css={css`
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View File

@@ -63,7 +63,7 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
&:hover { &:hover {
background-color: ${dragMode background-color: ${dragMode
? 'none' ? 'none'
: 'var(--c--theme--colors--greyscale-100)'}; : 'var(--c--contextuals--background--semantic--contextual--primary)'};
} }
`} `}
className="--docs--doc-grid-item" className="--docs--doc-grid-item"
@@ -111,8 +111,9 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
{dragMode && ( {dragMode && (
<> <>
<Icon <Icon
$theme="greyscale" $layer="background"
$variation="600" $theme="neutral"
$variation="primary"
$size="14px" $size="14px"
iconName={isPublic ? 'public' : 'vpn_lock'} iconName={isPublic ? 'public' : 'vpn_lock'}
/> />
@@ -126,7 +127,7 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
{!dragMode && ( {!dragMode && (
<Tooltip <Tooltip
content={ content={
<Text $textAlign="center" $variation="000"> <Text $textAlign="center">
{isPublic {isPublic
? t('Accessible to anyone') ? t('Accessible to anyone')
: t('Accessible to authenticated users')} : t('Accessible to authenticated users')}
@@ -136,9 +137,10 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
> >
<div> <div>
<Icon <Icon
$theme="greyscale" $layer="background"
$variation="600" $theme="neutral"
$size="14px" $variation="primary"
$size="sm"
iconName={isPublic ? 'public' : 'vpn_lock'} iconName={isPublic ? 'public' : 'vpn_lock'}
/> />
<span className="sr-only"> <span className="sr-only">
@@ -222,7 +224,12 @@ export const DocsGridItemDate = ({
return ( return (
<StyledLink href={`/docs/${doc.id}`}> <StyledLink href={`/docs/${doc.id}`}>
<Text $variation="600" $size="xs"> <Text
$size="xs"
$layer="background"
$theme="neutral"
$variation="primary"
>
{dateToDisplay} {dateToDisplay}
</Text> </Text>
</StyledLink> </StyledLink>

View File

@@ -25,7 +25,7 @@ export const DocsGridItemSharedButton = ({
return ( return (
<Tooltip <Tooltip
content={ content={
<Text $textAlign="center" $variation="000"> <Text $textAlign="center">
{t('Shared with {{count}} users', { count: sharedCount })} {t('Shared with {{count}} users', { count: sharedCount })}
</Text> </Text>
} }
@@ -37,17 +37,25 @@ export const DocsGridItemSharedButton = ({
aria-label={t('Open the sharing settings for the document')} aria-label={t('Open the sharing settings for the document')}
data-testid={`docs-grid-item-shared-button-${doc.id}`} data-testid={`docs-grid-item-shared-button-${doc.id}`}
style={{ style={{
minWidth: '50px', padding: `0 var(--c--globals--spacings--xxxs) 0 var(--c--globals--spacings--xxxs)`,
justifyContent: 'center',
}} }}
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
handleClick(); handleClick();
}} }}
color="tertiary" color="brand"
variant="secondary"
size="nano" size="nano"
icon={<Icon $theme="primary" iconName="group" disabled={disabled} />} icon={
<Icon
$theme="brand"
$variation="secondary"
iconName="group"
disabled={disabled}
variant="filled"
/>
}
disabled={disabled} disabled={disabled}
> >
{sharedCount} {sharedCount}

View File

@@ -44,8 +44,6 @@ export const DocsGridTrashbinActions = ({
icon: ( icon: (
<Icon <Icon
$size="20px" $size="20px"
$theme="greyscale"
$variation="1000"
iconName="undo" iconName="undo"
aria-hidden="true" aria-hidden="true"
variant="symbols-outlined" variant="symbols-outlined"
@@ -70,12 +68,17 @@ export const DocsGridTrashbinActions = ({
options={options} options={options}
label={menuLabel} label={menuLabel}
aria-label={t('More options')} aria-label={t('More options')}
buttonCss={css`
&:hover {
background-color: unset;
}
`}
> >
<Icon <Icon
data-testid={`docs-grid-actions-button-${doc.id}`} data-testid={`docs-grid-actions-button-${doc.id}`}
iconName="more_horiz" iconName="more_horiz"
$theme="primary" $theme="brand"
$variation="600" $variation="secondary"
$css={css` $css={css`
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View File

@@ -37,13 +37,13 @@ export const Droppable = ({
data-testid={`droppable-doc-${id}`} data-testid={`droppable-doc-${id}`}
role="none" role="none"
$css={css` $css={css`
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
background-color: ${enableHover background-color: ${enableHover
? 'var(--c--theme--colors--primary-100)' ? 'var(--c--globals--colors--brand-100)'
: 'transparent'}; : 'transparent'};
border: 1.5px solid border: 1.5px solid
${enableHover ${enableHover
? 'var(--c--theme--colors--primary-500)' ? 'var(--c--globals--colors--brand-500)'
: 'transparent'}; : 'transparent'};
`} `}
className="--docs--grid-droppable" className="--docs--grid-droppable"

View File

@@ -15,7 +15,7 @@ const BlueStripe = styled.div`
position: absolute; position: absolute;
height: 2px; height: 2px;
width: 100%; width: 100%;
background: var(--c--theme--colors--primary-600); background: var(--c--globals--colors--brand-700);
top: 0; top: 0;
`; `;
@@ -83,7 +83,6 @@ export const Footer = () => {
> >
{logo?.src && ( {logo?.src && (
<Image <Image
className="c__image-system-filter"
priority priority
src={logo.src} src={logo.src}
alt={logo?.alt || t('Logo')} alt={logo?.alt || t('Logo')}
@@ -116,11 +115,14 @@ export const Footer = () => {
key={label} key={label}
href={href} href={href}
target="__blank" target="__blank"
$css={` $css={css`
gap:0.2rem; gap: 0.2rem;
transition: box-shadow 0.3s; transition: box-shadow 0.3s;
&:hover { &:hover {
box-shadow: 0px 2px 0 0 var(--c--theme--colors--greyscale-text); box-shadow: 0px 2px 0 0
var(
--c--contextuals--content--semantic--neutral--secondary
);
} }
`} `}
> >
@@ -136,7 +138,7 @@ export const Footer = () => {
$padding={{ top: 'tiny' }} $padding={{ top: 'tiny' }}
$css={` $css={`
flex-wrap: wrap; flex-wrap: wrap;
border-top: 1px solid var(--c--theme--colors--greyscale-200); border-top: 1px solid var(--c--globals--colors--gray-200);
column-gap: 1rem; column-gap: 1rem;
row-gap: .5rem; row-gap: .5rem;
`} `}
@@ -151,18 +153,20 @@ export const Footer = () => {
padding-right: 1rem; padding-right: 1rem;
&:not(:last-child) { &:not(:last-child) {
box-shadow: inset -1px 0px 0px 0px box-shadow: inset -1px 0px 0px 0px
var(--c--theme--colors--greyscale-200); var(--c--globals--colors--gray-200);
} }
`} `}
> >
<Text <Text
$variation="600" $size="s"
$size="m" $variation="secondary"
$transition="box-shadow 0.3s" $transition="box-shadow 0.3s"
$css={css` $css={css`
&:hover { &:hover {
box-shadow: 0px 2px 0 0 box-shadow: 0px 2px 0 0
var(--c--theme--colors--greyscale-text); var(
--c--contextuals--content--semantic--neutral--secondary
);
} }
`} `}
> >
@@ -174,9 +178,9 @@ export const Footer = () => {
{bottomInformation && ( {bottomInformation && (
<Text <Text
as="p" as="p"
$size="m" $size="s"
$margin={{ top: 'big' }} $margin={{ top: 'big' }}
$variation="600" $variation="secondary"
$display="inline" $display="inline"
className="--docs--footer-licence" className="--docs--footer-licence"
> >
@@ -188,11 +192,11 @@ export const Footer = () => {
$css={css` $css={css`
display: inline-flex; display: inline-flex;
box-shadow: 0px 1px 0 0 box-shadow: 0px 1px 0 0
var(--c--theme--colors--greyscale-text); var(--c--contextuals--content--semantic--neutral--secondary);
gap: 0.2rem; gap: 0.2rem;
`} `}
> >
<Text $variation="600">{bottomInformation.link.label}</Text> <Text>{bottomInformation.link.label}</Text>
<IconLink width={14} /> <IconLink width={14} />
</StyledLink> </StyledLink>
)} )}

View File

@@ -13,13 +13,9 @@ export const ButtonTogglePanel = () => {
size="medium" size="medium"
onClick={() => togglePanel()} onClick={() => togglePanel()}
aria-label={t('Open the header menu')} aria-label={t('Open the header menu')}
color="tertiary-text" variant="tertiary"
icon={ icon={
<Icon <Icon $withThemeInherited iconName={isPanelOpen ? 'close' : 'menu'} />
$variation="800"
$theme="primary"
iconName={isPanelOpen ? 'close' : 'menu'}
/>
} }
className="--docs--button-toggle-panel" className="--docs--button-toggle-panel"
/> />

View File

@@ -18,7 +18,7 @@ import { Title } from './Title';
export const Header = () => { export const Header = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { data: config } = useConfig(); const { data: config } = useConfig();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const logo = config?.theme_customization?.header?.logo; const logo = config?.theme_customization?.header?.logo;
@@ -38,8 +38,8 @@ export const Header = () => {
justify-content: space-between; justify-content: space-between;
height: ${HEADER_HEIGHT}px; height: ${HEADER_HEIGHT}px;
padding: 0 ${spacingsTokens['base']}; padding: 0 ${spacingsTokens['base']};
background-color: ${colorsTokens['greyscale-000']}; background-color: var(--c--contextuals--background--surface--primary);
border-bottom: 1px solid ${colorsTokens['greyscale-200']}; border-bottom: 1px solid var(--c--contextuals--border--surface--primary);
`} `}
className="--docs--header" className="--docs--header"
> >
@@ -51,8 +51,8 @@ export const Header = () => {
$css={css` $css={css`
outline: none; outline: none;
&:focus-visible { &:focus-visible {
box-shadow: 0 0 0 2px var(--c--theme--colors--primary-400) !important; box-shadow: 0 0 0 2px var(--c--globals--colors--brand-400) !important;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
`} `}
> >

View File

@@ -9,6 +9,12 @@ 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;
border-radius: var(--c--components--button--border-radius) !important;
transition: all var(--c--globals--transitions--duration) var(--c--globals--transitions--ease-out) !important;
&:hover, &:focus-visible {
background: var(--c--contextuals--background--semantic--contextual--primary) !important;
}
color: var(--c--contextuals--content--semantic--brand--tertiary) !important;
} }
`; `;

View File

@@ -1,7 +1,6 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Box, Text } from '@/components/'; import { Text } from '@/components/';
import { useCunninghamTheme } from '@/cunningham';
type TitleSemanticsProps = { type TitleSemanticsProps = {
headingLevel?: 'h1' | 'h2' | 'h3'; headingLevel?: 'h1' | 'h2' | 'h3';
@@ -9,24 +8,19 @@ type TitleSemanticsProps = {
export const Title = ({ headingLevel = 'h2' }: TitleSemanticsProps) => { export const Title = ({ headingLevel = 'h2' }: TitleSemanticsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
return ( return (
<Box <Text
className="--docs--title"
$direction="row" $direction="row"
$align="center" $align="center"
$gap={spacingsTokens['2xs']} $margin="none"
className="--docs--title" as={headingLevel}
$zIndex={1}
$size="1.375rem"
$color="var(--c--contextuals--content--logo1)"
> >
<Text {t('Docs')}
$margin="none" </Text>
as={headingLevel}
$color={colorsTokens['primary-text']}
$zIndex={1}
$size="1.375rem"
>
{t('Docs')}
</Text>
</Box>
); );
}; };

View File

@@ -3,8 +3,8 @@ import Image from 'next/image';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components'; import { css } from 'styled-components';
import IconDocs from '@/assets/icons/icon-docs.svg';
import { Box, Icon, Text } from '@/components'; import { Box, Icon, Text } from '@/components';
import { useConfig } from '@/core';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { ProConnectButton, gotoLogin } from '@/features/auth'; import { ProConnectButton, gotoLogin } from '@/features/auth';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
@@ -15,10 +15,13 @@ import { getHeaderHeight } from './HomeHeader';
export default function HomeBanner() { export default function HomeBanner() {
const { t } = useTranslation(); const { t } = useTranslation();
const { componentTokens, spacingsTokens, colorsTokens } = const { componentTokens, spacingsTokens } = useCunninghamTheme();
useCunninghamTheme();
const { isMobile, isSmallMobile } = useResponsiveStore(); const { isMobile, isSmallMobile } = useResponsiveStore();
const withProConnect = componentTokens['home-proconnect']; const withProConnect = componentTokens['home-proconnect'];
const { data: config } = useConfig();
const icon =
config?.theme_customization?.header?.icon || componentTokens.icon;
return ( return (
<Box <Box
@@ -47,15 +50,21 @@ export default function HomeBanner() {
$align="center" $align="center"
$gap={spacingsTokens['sm']} $gap={spacingsTokens['sm']}
> >
<IconDocs <Image
aria-label={t('Back to homepage')} data-testid="header-icon-docs"
width={64} src={icon.src || ''}
color={colorsTokens['primary-text']} alt=""
width={0}
height={0}
style={{
width: '64px',
height: 'auto',
}}
priority
/> />
<Text <Text
as="h2" as="h2"
$size={!isMobile ? 'xs-alt' : '2.3rem'} $size={!isMobile ? 'xs-alt' : '2.3rem'}
$variation="800"
$weight="bold" $weight="bold"
$textAlign="center" $textAlign="center"
$margin="none" $margin="none"
@@ -67,9 +76,9 @@ export default function HomeBanner() {
</Text> </Text>
<Text <Text
$size="lg" $size="lg"
$variation="700"
$textAlign="center" $textAlign="center"
$margin={{ bottom: 'small' }} $margin={{ bottom: 'small' }}
$variation="secondary"
> >
{t( {t(
'Collaborate and write in real time, without layout constraints.', 'Collaborate and write in real time, without layout constraints.',
@@ -88,7 +97,6 @@ export default function HomeBanner() {
</Box> </Box>
{!isMobile && ( {!isMobile && (
<Image <Image
className="c__image-system-filter"
src={banner} src={banner}
alt={t('Banner image')} alt={t('Banner image')}
priority priority
@@ -104,10 +112,9 @@ export default function HomeBanner() {
</Box> </Box>
<Box $css="bottom: 3rem" $position="absolute"> <Box $css="bottom: 3rem" $position="absolute">
<Button <Button
color="secondary" color="brand"
icon={ variant="secondary"
<Icon $theme="primary" $variation="800" iconName="expand_more" /> icon={<Icon $color="inherit" iconName="expand_more" />}
}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
document document

View File

@@ -20,7 +20,7 @@ export function HomeBottom() {
function HomeProConnect() { function HomeProConnect() {
const { t } = useTranslation(); const { t } = useTranslation();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { isMobile } = useResponsiveStore(); const { isMobile } = useResponsiveStore();
const parentGap = '230px'; const parentGap = '230px';
@@ -43,15 +43,12 @@ function HomeProConnect() {
$position="relative" $position="relative"
$height="fit-content" $height="fit-content"
$css="zoom: 1.9;" $css="zoom: 1.9;"
$theme="brand"
> >
<IconDocs <IconDocs aria-label={t('Docs Logo')} width={34} />
aria-label={t('Docs Logo')}
width={34}
color={colorsTokens['primary-text']}
/>
<Title /> <Title />
</Box> </Box>
<Text $size="md" $variation="1000" $textAlign="center"> <Text $size="md" $variation="secondary" $textAlign="center">
{t('Docs is already available, log in to use it now.')} {t('Docs is already available, log in to use it now.')}
</Text> </Text>
<ProConnectButton /> <ProConnectButton />

View File

@@ -3,7 +3,6 @@ import { Trans, useTranslation } from 'react-i18next';
import { css } from 'styled-components'; import { css } from 'styled-components';
import { Box, Icon, Text } from '@/components'; import { Box, Icon, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Footer } from '@/features/footer'; import { Footer } from '@/features/footer';
import { LeftPanel } from '@/features/left-panel'; import { LeftPanel } from '@/features/left-panel';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
@@ -28,7 +27,6 @@ import { HomeSection } from './HomeSection';
export function HomeContent() { export function HomeContent() {
const { i18n, t } = useTranslation(); const { i18n, t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
const { isMobile, isSmallMobile, isTablet } = useResponsiveStore(); const { isMobile, isSmallMobile, isTablet } = useResponsiveStore();
const isFrLanguage = i18n.resolvedLanguage === 'fr'; const isFrLanguage = i18n.resolvedLanguage === 'fr';
@@ -76,84 +74,89 @@ export function HomeContent() {
textWidth="60%" textWidth="60%"
$css={`min-height: calc(100vh - ${getHeaderHeight(isSmallMobile)}px);`} $css={`min-height: calc(100vh - ${getHeaderHeight(isSmallMobile)}px);`}
description={ description={
<Box <Box>
$css={css` <Box
& a { $css={css`
color: ${colorsTokens['primary-600']}; & a {
} color: inherit;
`} }
> `}
<Text as="p" $display="inline"> >
<Trans t={t} i18nKey="home-content-open-source-part1"> <Text as="p" $display="inline" $variation="secondary">
Docs is built on top of{' '} <Trans t={t} i18nKey="home-content-open-source-part1">
<a Docs is built on top of{' '}
href="https://www.django-rest-framework.org/" <a
target="_blank" href="https://www.django-rest-framework.org/"
> target="_blank"
Django Rest Framework >
</a>{' '} Django Rest Framework
and{' '} </a>{' '}
<a href="https://nextjs.org/" target="_blank"> and{' '}
Next.js <a href="https://nextjs.org/" target="_blank">
</a> Next.js
. We also use{' '} </a>
<a href="https://github.com/yjs" target="_blank"> . We also use{' '}
Yjs <a href="https://github.com/yjs" target="_blank">
</a>{' '} Yjs
and{' '} </a>{' '}
<a href="https://www.blocknotejs.org/" target="_blank"> and{' '}
BlockNote.js <a
</a> href="https://www.blocknotejs.org/"
, both of which we are proud to sponsor. target="_blank"
</Trans> >
</Text> BlockNote.js
<Text as="p" $display="inline"> </a>
<Trans t={t} i18nKey="home-content-open-source-part2"> , both of which we are proud to sponsor.
You can easily self-host Docs (check our installation{' '} </Trans>
<a </Text>
href="https://github.com/suitenumerique/docs/tree/main/docs" <Text as="p" $display="inline">
target="_blank" <Trans t={t} i18nKey="home-content-open-source-part2">
> You can easily self-host Docs (check our installation{' '}
documentation <a
</a> href="https://github.com/suitenumerique/docs/tree/main/docs"
). target="_blank"
<br /> >
Docs uses an innovation and business friendly{' '} documentation
<a </a>
href="https://github.com/suitenumerique/docs/blob/main/LICENSE" ).
target="_blank" <br />
> Docs uses an innovation and business friendly{' '}
licence <a
</a>{' '} href="https://github.com/suitenumerique/docs/blob/main/LICENSE"
(MIT). target="_blank"
<br /> >
Contributions are welcome (see our roadmap{' '} licence
<a </a>{' '}
href="https://github.com/orgs/numerique-gouv/projects/13/views/11" (MIT).
target="_blank" <br />
> Contributions are welcome (see our roadmap{' '}
here <a
</a> href="https://github.com/orgs/numerique-gouv/projects/13/views/11"
). target="_blank"
</Trans> >
</Text> here
<Text as="p" $display="inline"> </a>
<Trans t={t} i18nKey="home-content-open-source-part3"> ).
Docs is the result of a joint effort lead by the French </Trans>
🇫🇷🥖 </Text>
<a <Text as="p" $display="inline">
href="https://www.numerique.gouv.fr/dinum/" <Trans t={t} i18nKey="home-content-open-source-part3">
target="_blank" Docs is the result of a joint effort lead by the
> French 🇫🇷🥖
(DINUM) <a
</a>{' '} href="https://www.numerique.gouv.fr/dinum/"
and German 🇩🇪🥨 governments{' '} target="_blank"
<a href="https://zendis.de/" target="_blank"> >
(ZenDiS) (DINUM)
</a> </a>{' '}
. and German 🇩🇪🥨 governments{' '}
</Trans> <a href="https://zendis.de/" target="_blank">
</Text> (ZenDiS)
</a>
.
</Trans>
</Text>
</Box>
<Box <Box
$direction="row" $direction="row"
$gap="1rem" $gap="1rem"
@@ -164,10 +167,11 @@ export function HomeContent() {
href="https://matrix.to/#/#docs-official:matrix.org" href="https://matrix.to/#/#docs-official:matrix.org"
target="_blank" target="_blank"
> >
<Text $color="white">Matrix</Text> Matrix
</Button> </Button>
<Button <Button
color="secondary" color="neutral"
variant="secondary"
icon={<GithubIcon />} icon={<GithubIcon />}
href="https://github.com/suitenumerique/docs" href="https://github.com/suitenumerique/docs"
target="_blank" target="_blank"

View File

@@ -117,7 +117,6 @@ export const HomeSection = ({
$css={css` $css={css`
line-height: ${!isSmallDevice ? '50px' : 'normal'}; line-height: ${!isSmallDevice ? '50px' : 'normal'};
`} `}
$variation="1000"
$weight="bold" $weight="bold"
$size={!isSmallDevice ? 'xs-alt' : isSmallMobile ? 'h6' : 'h4'} $size={!isSmallDevice ? 'xs-alt' : isSmallMobile ? 'h6' : 'h4'}
$textAlign="left" $textAlign="left"
@@ -127,7 +126,7 @@ export const HomeSection = ({
</Text> </Text>
<Text <Text
as="div" as="div"
$variation="700" $variation="secondary"
$weight="400" $weight="400"
$size={isSmallMobile ? 'ml' : 'md'} $size={isSmallMobile ? 'ml' : 'md'}
> >
@@ -175,7 +174,6 @@ export const HomeSection = ({
{illustration && (isSmallDevice || !video) && ( {illustration && (isSmallDevice || !video) && (
<Image <Image
className="c__image-system-filter"
src={illustration} src={illustration}
alt={t('Illustration')} alt={t('Illustration')}
style={{ style={{
@@ -200,28 +198,19 @@ const SectionTag = ({
tag: string; tag: string;
availableSoon?: boolean; availableSoon?: boolean;
}) => { }) => {
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
return ( return (
<Box <Box
$background={
!availableSoon
? colorsTokens['primary-100']
: colorsTokens['warning-100']
}
$padding={{ horizontal: spacingsTokens['sm'], vertical: '6px' }} $padding={{ horizontal: spacingsTokens['sm'], vertical: '6px' }}
$css={css` $css={css`
align-self: flex-start; align-self: flex-start;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
`} `}
$theme={availableSoon ? 'warning' : 'brand'}
$variation="tertiary"
$withThemeBG
> >
<Text {tag}
$size="md"
$variation={availableSoon ? '600' : '800'}
$weight="bold"
$theme={availableSoon ? 'warning' : 'primary'}
>
{tag}
</Text>
</Box> </Box>
); );
}; };

View File

@@ -2,7 +2,7 @@ import { useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components'; import { css } from 'styled-components';
import { DropdownMenu, Icon, Text } from '@/components/'; import { Box, DropdownMenu, Icon } from '@/components/';
import { useConfig } from '@/core'; import { useConfig } from '@/core';
import { useAuthQuery } from '@/features/auth'; import { useAuthQuery } from '@/features/auth';
import { import {
@@ -41,32 +41,32 @@ export const LanguagePicker = () => {
showArrow showArrow
label={t('Select language')} label={t('Select language')}
buttonCss={css` buttonCss={css`
transition: all 0.15s ease-in-out !important; transition: all var(--c--globals--transitions--duration)
border-radius: 4px; var(--c--globals--transitions--ease-out) !important;
border-radius: var(--c--globals--spacings--st);
padding: 0.5rem 0.6rem; padding: 0.5rem 0.6rem;
& > div { & > div {
gap: 0.2rem; gap: 0.2rem;
display: flex; display: flex;
} }
& .material-icons { & .material-icons {
color: var(--c--components--button--primary-text--color) !important; color: var(
--c--contextuals--content--palette--brand--primary
) !important;
} }
`} `}
> >
<Text <Box
$theme="primary" className="--docs--language-picker-text"
$theme="brand"
$variation="tertiary"
$direction="row" $direction="row"
$gap="0.5rem" $gap="0.5rem"
className="--docs--language-picker-text" $align="center"
> >
<Icon <Icon iconName="translate" $color="inherit" $size="xl" />
iconName="translate"
$color="inherit"
$size="xl"
aria-hidden="true"
/>
{currentLanguageLabel} {currentLanguageLabel}
</Text> </Box>
</DropdownMenu> </DropdownMenu>
); );
}; };

View File

@@ -78,29 +78,26 @@ export const LeftPanelTargetFilters = () => {
padding: ${spacingsTokens['2xs']}; padding: ${spacingsTokens['2xs']};
border-radius: ${spacingsTokens['3xs']}; border-radius: ${spacingsTokens['3xs']};
background-color: ${isActive background-color: ${isActive
? colorsTokens['greyscale-100'] ? 'var(--c--contextuals--background--semantic--contextual--primary)'
: 'transparent'}; : 'transparent'};
font-weight: ${isActive ? 700 : 400}; font-weight: ${isActive ? 700 : 400};
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: ${colorsTokens['greyscale-100']}; background-color: var(
--c--contextuals--background--semantic--contextual--primary
);
} }
&:focus-visible { &:focus-visible {
outline: none !important; outline: none !important;
box-shadow: 0 0 0 2px ${colorsTokens['primary-500']} !important; box-shadow: 0 0 0 2px ${colorsTokens['brand-400']} !important;
border-radius: 4px; border-radius: var(--c--globals--spacings--st);
} }
`} `}
> >
<Icon <Icon iconName={query.icon} />
$variation={isActive ? '1000' : '700'} <Text $size="sm">{query.label}</Text>
iconName={query.icon}
/>
<Text $variation={isActive ? '1000' : '700'} $size="sm">
{query.label}
</Text>
</StyledLink> </StyledLink>
); );
})} })}

View File

@@ -25,7 +25,7 @@ export const LeftPanel = () => {
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { t } = useTranslation(); const { t } = useTranslation();
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const { togglePanel, isPanelOpen } = useLeftPanelStore(); const { togglePanel, isPanelOpen } = useLeftPanelStore();
const pathname = usePathname(); const pathname = usePathname();
@@ -43,7 +43,7 @@ export const LeftPanel = () => {
height: calc(100vh - ${HEADER_HEIGHT}px); height: calc(100vh - ${HEADER_HEIGHT}px);
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
background-color: ${colorsTokens['greyscale-000']}; background-color: var(--c--globals--colors--gray-000);
`} `}
className="--docs--left-panel-desktop" className="--docs--left-panel-desktop"
as="nav" as="nav"
@@ -69,10 +69,10 @@ export const LeftPanel = () => {
z-index: 999; z-index: 999;
width: 100dvw; width: 100dvw;
height: calc(100dvh - 52px); height: calc(100dvh - 52px);
border-right: 1px solid var(--c--theme--colors--greyscale-200); border-right: 1px solid var(--c--globals--colors--gray-200);
position: fixed; position: fixed;
transform: translateX(${isPanelOpen ? '0' : '-100dvw'}); transform: translateX(${isPanelOpen ? '0' : '-100dvw'});
background-color: var(--c--theme--colors--greyscale-000); background-color: var(--c--globals--colors--gray-000);
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
`} `}

View File

@@ -32,11 +32,16 @@ export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
opacity: ${isDesktop ? 0 : 1}; opacity: ${isDesktop ? 0 : 1};
} }
&:hover { &:hover {
background-color: ${colorsTokens['greyscale-100']}; background-color: var(
--c--contextuals--background--semantic--contextual--primary
);
.pinned-actions {
opacity: 1;
}
} }
&:focus-within { &:focus-within {
cursor: pointer; cursor: pointer;
box-shadow: 0 0 0 2px ${colorsTokens['primary-500']} !important; box-shadow: 0 0 0 2px ${colorsTokens['brand-400']} !important;
.pinned-actions { .pinned-actions {
opacity: 1; opacity: 1;
} }
@@ -55,9 +60,9 @@ export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
> >
<SimpleDocItem showAccesses doc={doc} /> <SimpleDocItem showAccesses doc={doc} />
</StyledLink> </StyledLink>
<div className="pinned-actions"> <Box className="pinned-actions" $align="center">
<DocsGridActions doc={doc} openShareModal={shareModal.open} /> <DocsGridActions doc={doc} openShareModal={shareModal.open} />
</div> </Box>
{shareModal.isOpen && ( {shareModal.isOpen && (
<DocShareModal doc={doc} onClose={shareModal.close} /> <DocShareModal doc={doc} onClose={shareModal.close} />
)} )}

View File

@@ -38,7 +38,6 @@ export const LeftPanelFavorites = () => {
> >
<Text <Text
$size="sm" $size="sm"
$variation="700"
$padding={{ horizontal: '3xs' }} $padding={{ horizontal: '3xs' }}
$weight="700" $weight="700"
id="pinned-docs-title" id="pinned-docs-title"
@@ -46,7 +45,7 @@ export const LeftPanelFavorites = () => {
{t('Pinned documents')} {t('Pinned documents')}
</Text> </Text>
<Box> <Box>
<Box as="ul" $padding="none"> <Box as="ul" $padding="none" $margin={{ top: '4xs' }}>
{favoriteDocs.map((doc) => ( {favoriteDocs.map((doc) => (
<LeftPanelFavoriteItem key={doc.id} doc={doc} /> <LeftPanelFavoriteItem key={doc.id} doc={doc} />
))} ))}

View File

@@ -52,42 +52,45 @@ export const LeftPanelHeader = ({ children }: PropsWithChildren) => {
$justify="space-between" $justify="space-between"
$align="center" $align="center"
> >
<Box $direction="row" $gap="2px">
<Button
data-testid="home-button"
onClick={goToHome}
aria-label={t('Back to homepage')}
size="medium"
color="tertiary-text"
icon={
<Icon
$variation="800"
$theme="primary"
iconName="house"
aria-hidden="true"
/>
}
/>
{authenticated && (
<Button
data-testid="search-docs-button"
onClick={openSearchModal}
size="medium"
color="tertiary-text"
aria-label={t('Search docs')}
icon={
<Icon
$variation="800"
$theme="primary"
iconName="search"
aria-hidden="true"
/>
}
/>
)}
</Box>
{authenticated && <LeftPanelHeaderButton />} {authenticated && <LeftPanelHeaderButton />}
{(router.pathname !== '/' || authenticated) && (
<Box $direction="row" $gap="2px">
{router.pathname !== '/' && (
<Button
data-testid="home-button"
onClick={goToHome}
aria-label={t('Back to homepage')}
size="medium"
color="brand"
variant="tertiary"
icon={
<Icon
$color="inherit"
iconName="house"
aria-hidden="true"
/>
}
/>
)}
{authenticated && (
<Button
data-testid="search-docs-button"
onClick={openSearchModal}
size="medium"
color="brand"
variant="tertiary"
aria-label={t('Search docs')}
icon={
<Icon
$color="inherit"
iconName="search"
aria-hidden="true"
/>
}
/>
)}
</Box>
)}
</Box> </Box>
</SeparatedSection> </SeparatedSection>
{children} {children}

View File

@@ -50,9 +50,9 @@ export const LeftPanelHeaderButton = () => {
return ( return (
<Button <Button
data-testid="new-doc-button" data-testid="new-doc-button"
color="primary" color="brand"
onClick={handleClick} onClick={handleClick}
icon={<Icon $variation="000" iconName="add" aria-hidden="true" />} icon={<Icon $color="inherit" iconName="add" aria-hidden="true" />}
disabled={isLoading} disabled={isLoading}
> >
{t('New doc')} {t('New doc')}

View File

@@ -6,8 +6,6 @@ import {
PanelResizeHandle, PanelResizeHandle,
} from 'react-resizable-panels'; } from 'react-resizable-panels';
import { useCunninghamTheme } from '@/cunningham';
// Convert a target pixel width to a percentage of the current viewport width. // Convert a target pixel width to a percentage of the current viewport width.
const pxToPercent = (px: number) => { const pxToPercent = (px: number) => {
return (px / window.innerWidth) * 100; return (px / window.innerWidth) * 100;
@@ -26,7 +24,6 @@ export const ResizableLeftPanel = ({
minPanelSizePx = 300, minPanelSizePx = 300,
maxPanelSizePx = 450, maxPanelSizePx = 450,
}: ResizableLeftPanelProps) => { }: ResizableLeftPanelProps) => {
const { colorsTokens } = useCunninghamTheme();
const ref = useRef<ImperativePanelHandle>(null); const ref = useRef<ImperativePanelHandle>(null);
const savedWidthPxRef = useRef<number>(minPanelSizePx); const savedWidthPxRef = useRef<number>(minPanelSizePx);
@@ -76,7 +73,7 @@ export const ResizableLeftPanel = ({
style={{ style={{
borderRightWidth: '1px', borderRightWidth: '1px',
borderRightStyle: 'solid', borderRightStyle: 'solid',
borderRightColor: colorsTokens['greyscale-200'], borderRightColor: 'var(--c--contextuals--border--surface--primary)',
width: '1px', width: '1px',
cursor: 'col-resize', cursor: 'col-resize',
}} }}

View File

@@ -29,9 +29,9 @@ export const DocEditorSkeleton = () => {
$css={css` $css={css`
background: linear-gradient( background: linear-gradient(
90deg, 90deg,
${colorsTokens['greyscale-100']} 0%, ${colorsTokens['black-050']} 0%,
${colorsTokens['greyscale-200']} 50%, ${colorsTokens['black-100']} 50%,
${colorsTokens['greyscale-100']} 100% ${colorsTokens['black-050']} 100%
); );
background-size: 1000px 100%; background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear; animation: ${shimmer} 2s infinite linear;
@@ -51,9 +51,9 @@ export const DocEditorSkeleton = () => {
$css={css` $css={css`
background: linear-gradient( background: linear-gradient(
90deg, 90deg,
${colorsTokens['greyscale-100']} 0%, ${colorsTokens['black-050']} 0%,
${colorsTokens['greyscale-200']} 50%, ${colorsTokens['black-100']} 50%,
${colorsTokens['greyscale-100']} 100% ${colorsTokens['black-050']} 100%
); );
background-size: 1000px 100%; background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear; animation: ${shimmer} 2s infinite linear;
@@ -100,7 +100,7 @@ export const DocEditorSkeleton = () => {
> >
{/* Title and metadata skeleton */} {/* Title and metadata skeleton */}
<Box $gap="0.25rem" $css="flex:1;"> <Box $gap="0.25rem" $css="flex:1;">
{/* Title - "Document sans titre" style */} {/* Title - "Untitled Document" style */}
<SkeletonLine $width="35%" $height="40px" /> <SkeletonLine $width="35%" $height="40px" />
{/* Metadata (role and last update) */} {/* Metadata (role and last update) */}
@@ -111,7 +111,7 @@ export const DocEditorSkeleton = () => {
{/* Toolbox skeleton (buttons) */} {/* Toolbox skeleton (buttons) */}
<Box $direction="row" $gap="0.75rem" $align="center"> <Box $direction="row" $gap="0.75rem" $align="center">
{/* Partager button */} {/* Share button */}
<SkeletonLine $width="90px" $height="40px" /> <SkeletonLine $width="90px" $height="40px" />
{/* Download icon */} {/* Download icon */}
<SkeletonCircle $width="40px" $height="40px" /> <SkeletonCircle $width="40px" $height="40px" />

Some files were not shown because too many files have changed in this diff Show More