Skip to content

Commit a973eea

Browse files
committed
Setup a MUI playground
1 parent 0492715 commit a973eea

File tree

8 files changed

+761
-133
lines changed

8 files changed

+761
-133
lines changed

src/lib/start.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export async function startDsfrReact(params: Params) {
8686
// NOTE: @gouvfr/dsfr/dist/dsfr.module.js is not isomorphic, it can't run on the Server.",
8787
// We set an artificial delay before starting the module otherwise to avoid getting",
8888
// Hydration error from Next.js
89-
await new Promise(resolve => setTimeout(resolve, 150));
89+
await new Promise(resolve => setTimeout(resolve, 400));
9090
}
9191

9292
(window as any).dsfr.start();

src/mui.tsx

Lines changed: 104 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,35 @@ import { useIsDark } from "./lib/darkMode";
99
import { typography } from "./lib/generatedFromCss/typography";
1010
import { spacingTokenByValue } from "./lib/generatedFromCss/spacing";
1111
import type { ColorTheme } from "./lib/colors";
12-
import { memoize } from "./lib/tools/memoize";
1312
import type { Theme as NonAugmentedMuiTheme } from "./lib/tools/@mui/material/styles/createTheme";
13+
import { assert } from "tsafe/assert";
14+
import { objectKeys } from "tsafe/objectKeys";
1415

15-
const createMuiDsfrTheme = memoize(
16-
(isDark: boolean): MuiTheme => {
17-
const muiTheme = createTheme({
18-
"shape": {
19-
"borderRadius": 0
20-
},
21-
"breakpoints": {
22-
"unit": breakpointValuesUnit,
23-
"values": breakpointValues
24-
},
25-
"palette": (() => {
26-
const { decisions } = getColors(isDark);
27-
28-
return {
29-
"mode": isDark ? "dark" : "light",
30-
"primary": {
31-
"main": decisions.background.actionHigh.blueFrance.default,
32-
"light": decisions.background.actionLow.blueFrance.default
33-
},
34-
"secondary": {
35-
"main": decisions.background.actionHigh.redMarianne.default,
36-
"light": decisions.background.actionLow.redMarianne.default
37-
}
38-
/*
16+
function createMuiDsfrTheme(params: { isDark: boolean }): MuiTheme {
17+
const { isDark } = params;
18+
19+
const muiTheme = createTheme({
20+
"shape": {
21+
"borderRadius": 0
22+
},
23+
"breakpoints": {
24+
"unit": breakpointValuesUnit,
25+
"values": breakpointValues
26+
},
27+
"palette": (() => {
28+
const { decisions } = getColors(isDark);
29+
30+
return {
31+
"mode": isDark ? "dark" : "light",
32+
"primary": {
33+
"main": decisions.background.actionHigh.blueFrance.default,
34+
"light": decisions.background.actionLow.blueFrance.default
35+
},
36+
"secondary": {
37+
"main": decisions.background.actionHigh.redMarianne.default,
38+
"light": decisions.background.actionLow.redMarianne.default
39+
}
40+
/*
3941
"primary": {
4042
"900": colorOptions.blueFrance._925_125.default,
4143
"800": colorOptions.blueFrance._850_200.default,
@@ -45,73 +47,99 @@ const createMuiDsfrTheme = memoize(
4547
"light": colorDecisions.background.actionLow.redMarianne.default,
4648
},
4749
*/
48-
} as const;
49-
})(),
50-
"typography": {
50+
} as const;
51+
})(),
52+
"typography": (() => {
53+
const getBySelector = (selector: typeof typography[number]["selector"]) => {
54+
const variant = typography.find(variant => variant.selector === selector);
55+
assert(variant !== undefined);
56+
57+
const style = { ...variant.style };
58+
59+
//TODO: Investigate why we need to do that.
60+
delete (style as any).margin;
61+
62+
return style;
63+
};
64+
65+
return {
5166
"fontFamily": '"Marianne", arial, sans-serif',
52-
"h1": typography.find(({ selector }) => selector === "h1")!.style,
53-
"h2": typography.find(({ selector }) => selector === "h2")!.style,
54-
"h3": typography.find(({ selector }) => selector === "h3")!.style,
55-
"h4": typography.find(({ selector }) => selector === "h4")!.style,
56-
"h5": typography.find(({ selector }) => selector === "h5")!.style,
57-
"h6": typography.find(({ selector }) => selector === "h6")!.style,
67+
"h1": getBySelector("h1"),
68+
"h2": getBySelector("h2"),
69+
"h3": getBySelector("h3"),
70+
"h4": getBySelector("h4"),
71+
"h5": getBySelector("h5"),
72+
"h6": getBySelector("h6"),
5873
//"subtitle1":
5974
//"subtitle2":
60-
"body1": typography.find(({ selector }) => selector === "p")!.style
75+
"body1": getBySelector("p")
6176
//"body2": {},
6277
//"caption": {},
6378
//"button": {},
6479
//"overline": {}
65-
},
66-
"spacing": (() => {
67-
//NOTE: The properties are declared sorted in the object.
68-
const values = Object.values(spacingTokenByValue);
69-
70-
return (abs: string | number) =>
71-
typeof abs === "string"
72-
? abs
73-
: abs === 0
74-
? 0
75-
: (() => {
76-
const value = values[abs - 1];
77-
return value === undefined ? abs : value;
78-
})();
79-
})()
80-
});
81-
82-
return muiTheme;
83-
},
84-
{ "max": 1 }
85-
);
86-
87-
export type MuiDsfrThemeProviderProps = {
88-
children: ReactNode;
89-
/** If you have implemented theme augmentation */
90-
augmentMuiTheme?: (params: {
80+
};
81+
})(),
82+
"spacing": (() => {
83+
const values: string[] = [];
84+
85+
//NOTE: The properties are declared sorted in the object.
86+
objectKeys(spacingTokenByValue).forEach(key => {
87+
if (key.endsWith("w")) {
88+
values.push(spacingTokenByValue[key]);
89+
}
90+
});
91+
92+
return (abs: string | number) =>
93+
typeof abs === "string"
94+
? abs
95+
: abs === 0
96+
? 0
97+
: (() => {
98+
const value = values[abs - 1];
99+
return value === undefined ? abs : value;
100+
})();
101+
})()
102+
});
103+
104+
return muiTheme;
105+
}
106+
107+
export function createMuiDsfrThemeProvider(params: {
108+
augmentMuiTheme: (params: {
91109
nonAugmentedMuiTheme: NonAugmentedMuiTheme;
92110
frColorTheme: ColorTheme;
93111
}) => MuiTheme;
94-
};
112+
}) {
113+
const { augmentMuiTheme } = params;
95114

96-
export function MuiDsfrThemeProvider(props: MuiDsfrThemeProviderProps) {
97-
const { children, augmentMuiTheme } = props;
115+
type Props = {
116+
children: ReactNode;
117+
/** If you have implemented theme augmentation */
118+
};
98119

99-
const { isDark } = useIsDark();
120+
function MuiDsfrThemeProvider(props: Props) {
121+
const { children } = props;
100122

101-
const theme = useMemo(() => {
102-
const theme = createMuiDsfrTheme(isDark);
123+
const { isDark } = useIsDark();
103124

104-
if (augmentMuiTheme === undefined) {
105-
return theme;
106-
}
125+
const theme = useMemo(
126+
() =>
127+
augmentMuiTheme({
128+
"frColorTheme": getColors(isDark),
129+
"nonAugmentedMuiTheme": createMuiDsfrTheme({ isDark })
130+
}),
131+
[isDark]
132+
);
133+
134+
return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>;
135+
}
107136

108-
return augmentMuiTheme({
109-
"frColorTheme": getColors(isDark),
110-
"nonAugmentedMuiTheme": theme
111-
});
112-
}, [isDark, augmentMuiTheme]);
137+
return { MuiDsfrThemeProvider };
138+
}
113139

114-
return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>;
140+
export function noAugmentation(params: { nonAugmentedMuiTheme: MuiTheme }) {
141+
const { nonAugmentedMuiTheme } = params;
142+
return nonAugmentedMuiTheme;
115143
}
116144

117145
/*

src/scripts/yarn-link.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import { getProjectRoot } from "../bin/tools/getProjectRoot";
88
const projectDirPath = getProjectRoot();
99

1010
const commonThirdPartyDeps = (() => {
11-
const namespaceModuleNames: string[] = [
12-
/*"@emotion"*/
13-
];
11+
const namespaceModuleNames: string[] = ["@emotion", "@mui"];
1412
const standaloneModuleNames = ["react", "@types/react"];
1513

1614
return [

test/integration/next/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
"@emotion/react": "^11.10.5",
2020
"@emotion/server": "^11.10.0",
2121
"tss-react": "^4.4.4",
22+
"@mui/material": "^5.10.15",
23+
"@mui/icons-material": "5.10.15",
24+
"@emotion/styled": "^11.10.5",
25+
"dayjs": "^1.11.6",
26+
"@mui/x-date-pickers": "^5.0.9",
2227
"@codegouvfr/react-dsfr": "file:../../../dist"
28+
2329
},
2430
"devDependencies": {
2531
"@types/react": "18.0.21",

test/integration/next/pages/_app.tsx

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { DsfrLangProvider } from "@codegouvfr/react-dsfr";
33
import { createNextDsfrIntegrationApi } from "@codegouvfr/react-dsfr/next";
44
import { Header } from "@codegouvfr/react-dsfr/Header";
55
import { createEmotionSsrAdvancedApproach } from "tss-react/next";
6+
import { useStyles } from "tss-react/dsfr";
7+
import { fr } from "@codegouvfr/react-dsfr";
8+
69

710
const {
811
withDsfr,
@@ -24,38 +27,49 @@ const {
2427
"doPersistDarkModePreferenceWithCookie": true
2528
});
2629

27-
const { augmentDocumentWithEmotionCache, withAppEmotionCache} = createEmotionSsrAdvancedApproach({
30+
const { augmentDocumentWithEmotionCache, withAppEmotionCache } = createEmotionSsrAdvancedApproach({
2831
"key": "css"
2932
});
3033

3134
export { dsfrDocumentApi, augmentDocumentWithEmotionCache };
3235

3336
function App({ Component, pageProps }: AppProps) {
37+
38+
const { css } = useStyles();
39+
3440
return (
3541
<DsfrLangProvider lang="fr">
36-
<Header
37-
intituléOfficiel="Intitulé officiel"
38-
baselinePrécisionsSurLorganisation="baseline - Précision sur l'organisation"
39-
nomDuSiteSlashService="Nom du site / service"
40-
links={[
41-
{
42-
"text": "Créer un espace",
43-
"iconId": "fr-icon-add-circle-line",
44-
"href": "#"
45-
},
46-
{
47-
"text": "Se connecter",
48-
"iconId": "fr-icon-lock-line",
49-
"href": "#"
50-
},
51-
{
52-
"text": "S'enregistrer",
53-
"iconId": "fr-icon-account-line",
54-
"href": "#"
55-
}
56-
]}
57-
/>
58-
<Component {...pageProps} />
42+
<Header
43+
intituléOfficiel="Intitulé officiel"
44+
baselinePrécisionsSurLorganisation="baseline - Précision sur l'organisation"
45+
nomDuSiteSlashService="Nom du site / service"
46+
links={[
47+
{
48+
"text": "Créer un espace",
49+
"iconId": "fr-icon-add-circle-line",
50+
"href": "#"
51+
},
52+
{
53+
"text": "Se connecter",
54+
"iconId": "fr-icon-lock-line",
55+
"href": "#"
56+
},
57+
{
58+
"text": "S'enregistrer",
59+
"iconId": "fr-icon-account-line",
60+
"href": "#"
61+
}
62+
]}
63+
/>
64+
<div className={css({
65+
"margin": "auto",
66+
"maxWidth": 1000,
67+
...fr.spacing("padding", {
68+
"topBottom": "10v"
69+
})
70+
})}>
71+
<Component {...pageProps} />
72+
</div>
5973
</DsfrLangProvider>
6074
);
6175
}

test/integration/next/pages/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { useStyles } from "tss-react/dsfr";
88
export default function App() {
99
const { isDark, setIsDark } = useIsDark();
1010

11-
1211
return (
1312
<>
1413
<Alert

0 commit comments

Comments
 (0)