From 3578b336fd8b7a62fc5720cf5964981731df68e5 Mon Sep 17 00:00:00 2001 From: el-makarova Date: Tue, 12 Dec 2023 18:13:46 +0300 Subject: [PATCH 1/4] feat: calculate body class names seperately --- src/components/theme/ThemeProvider.tsx | 22 +++++++++--------- src/components/theme/constants.ts | 2 -- src/components/theme/getBodyClassName.ts | 24 ++++++++++++++++++++ src/components/theme/index.ts | 1 + src/components/theme/updateBodyClassName.ts | 25 +++++++++++---------- 5 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 src/components/theme/getBodyClassName.ts diff --git a/src/components/theme/ThemeProvider.tsx b/src/components/theme/ThemeProvider.tsx index 6714b7ac53..3a2a8e8b78 100644 --- a/src/components/theme/ThemeProvider.tsx +++ b/src/components/theme/ThemeProvider.tsx @@ -1,17 +1,13 @@ import React from 'react'; -import {block, blockNew} from '../utils/cn'; - import {ThemeContext} from './ThemeContext'; import {ThemeSettingsContext} from './ThemeSettingsContext'; -import {DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, DEFAULT_THEME, ROOT_CLASS_NAME} from './constants'; +import {DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, DEFAULT_THEME} from './constants'; +import {getBodyRootClassName, getDeprecatedBodyRootClassName} from './getBodyClassName'; import type {RealTheme, Theme} from './types'; import {updateBodyClassName} from './updateBodyClassName'; import {useSystemTheme} from './useSystemTheme'; -const b = block(ROOT_CLASS_NAME); -const bNew = blockNew(ROOT_CLASS_NAME); - interface ThemeProviderExternalProps {} interface ThemeProviderDefaultProps { @@ -66,10 +62,16 @@ export function ThemeProvider({ {scoped ? (
{children}
diff --git a/src/components/theme/constants.ts b/src/components/theme/constants.ts index 89db77e2a5..bfff80768d 100644 --- a/src/components/theme/constants.ts +++ b/src/components/theme/constants.ts @@ -5,5 +5,3 @@ export const DEFAULT_DARK_THEME = 'dark'; export const LIGHT_THEMES = ['light', 'light-hc']; export const DARK_THEMES = ['dark', 'dark-hc']; export const THEMES = [...LIGHT_THEMES, ...DARK_THEMES]; - -export const ROOT_CLASS_NAME = 'root'; diff --git a/src/components/theme/getBodyClassName.ts b/src/components/theme/getBodyClassName.ts new file mode 100644 index 0000000000..3f32779be5 --- /dev/null +++ b/src/components/theme/getBodyClassName.ts @@ -0,0 +1,24 @@ +import {block, blockNew} from '../utils/cn'; + +import type {RealTheme} from './types'; + +const ROOT_CLASS_NAME = 'root'; + +const bNew = blockNew(ROOT_CLASS_NAME); +const b = block(ROOT_CLASS_NAME); + +export function getDeprecatedBodyRootClassName( + modifier?: Record, +) { + return b(modifier); +} +export function getBodyRootClassName( + modifier?: Record, + addition?: string[], +) { + return bNew(modifier, addition); +} + +export function getBaseBodyRootClassName(theme?: RealTheme) { + return getBodyRootClassName({theme}); +} diff --git a/src/components/theme/index.ts b/src/components/theme/index.ts index 63ad45175b..b20f30c848 100644 --- a/src/components/theme/index.ts +++ b/src/components/theme/index.ts @@ -8,4 +8,5 @@ export * from './useThemeType'; export * from './withTheme'; export * from './withThemeValue'; export * from './getThemeType'; +export {getBaseBodyRootClassName} from './getBodyClassName'; export type {Theme, RealTheme, ThemeType} from './types'; diff --git a/src/components/theme/updateBodyClassName.ts b/src/components/theme/updateBodyClassName.ts index 46a1597a98..135cbd084a 100644 --- a/src/components/theme/updateBodyClassName.ts +++ b/src/components/theme/updateBodyClassName.ts @@ -1,12 +1,10 @@ -import {block, blockNew, modsClassName} from '../utils/cn'; +import {modsClassName} from '../utils/cn'; -import {ROOT_CLASS_NAME} from './constants'; +import {getBodyRootClassName, getDeprecatedBodyRootClassName} from './getBodyClassName'; import type {RealTheme} from './types'; -const b = block(ROOT_CLASS_NAME); -const bNew = blockNew(ROOT_CLASS_NAME); -const rootClassName = b(); -const rootNewClassName = bNew(); +const rootClassName = getDeprecatedBodyRootClassName(); +const rootNewClassName = getBodyRootClassName(); export type BodyClassNameModifiers = { 'native-scrollbar': boolean; @@ -41,19 +39,22 @@ export function updateBodyClassName( } [...bodyEl.classList].forEach((cls) => { - if (cls.startsWith(modsClassName(b({theme: true})))) { + if (cls.startsWith(modsClassName(getDeprecatedBodyRootClassName({theme: true})))) { bodyEl.classList.remove(cls); } - if (cls.startsWith(modsClassName(bNew({theme: true})))) { + if (cls.startsWith(modsClassName(getBodyRootClassName({theme: true})))) { bodyEl.classList.remove(cls); } }); - bodyEl.classList.add(modsClassName(b({theme: newTheme}))); - bodyEl.classList.add(modsClassName(bNew({theme: newTheme}))); + bodyEl.classList.add(modsClassName(getDeprecatedBodyRootClassName({theme: newTheme}))); + bodyEl.classList.add(modsClassName(getBodyRootClassName({theme: newTheme}))); for (const [key, value] of Object.entries({...defaultModifiers, ...modifiers})) { - bodyEl.classList.toggle(modsClassName(b({[key]: true})), value); - bodyEl.classList.toggle(modsClassName(bNew({[key]: true})), value); + bodyEl.classList.toggle( + modsClassName(getDeprecatedBodyRootClassName({[key]: true})), + value, + ); + bodyEl.classList.toggle(modsClassName(getBodyRootClassName({[key]: true})), value); } } From 654f35a69986e987483d0503fd77f711cea44260 Mon Sep 17 00:00:00 2001 From: el-makarova Date: Mon, 25 Dec 2023 14:08:54 +0300 Subject: [PATCH 2/4] fix: modifier types --- src/components/theme/getBodyClassName.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/theme/getBodyClassName.ts b/src/components/theme/getBodyClassName.ts index 3f32779be5..261c28fb95 100644 --- a/src/components/theme/getBodyClassName.ts +++ b/src/components/theme/getBodyClassName.ts @@ -1,6 +1,7 @@ import {block, blockNew} from '../utils/cn'; import type {RealTheme} from './types'; +import type {BodyClassNameModifiers} from './updateBodyClassName'; const ROOT_CLASS_NAME = 'root'; @@ -8,12 +9,12 @@ const bNew = blockNew(ROOT_CLASS_NAME); const b = block(ROOT_CLASS_NAME); export function getDeprecatedBodyRootClassName( - modifier?: Record, + modifier?: Partial, ) { return b(modifier); } export function getBodyRootClassName( - modifier?: Record, + modifier?: Partial, addition?: string[], ) { return bNew(modifier, addition); From 22f293b2d7181aa3440945fb4bfe7bddebd58445 Mon Sep 17 00:00:00 2001 From: el-makarova Date: Mon, 25 Dec 2023 17:54:21 +0300 Subject: [PATCH 3/4] fix: code-review --- README.md | 9 +++++++++ src/components/theme/ThemeProvider.tsx | 6 +++--- src/components/theme/getBodyClassName.ts | 8 ++++---- src/components/theme/index.ts | 2 +- src/components/theme/updateBodyClassName.ts | 21 +++++++++------------ 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8fb5ba6ba1..3fe2f2f098 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,15 @@ or add specific CSS-classes to the root node: ``` +it is possible to generate initial CSS-classes during SSR: + +```js +import {getInitialRootClassName} from '@gravity-ui/uikit'; + +const theme = 'light'; +const rootClassName = getInitialRootClassName(theme); +``` + ```js // index.js import {createRoot} from 'react-dom/client'; diff --git a/src/components/theme/ThemeProvider.tsx b/src/components/theme/ThemeProvider.tsx index 3a2a8e8b78..506c4cde01 100644 --- a/src/components/theme/ThemeProvider.tsx +++ b/src/components/theme/ThemeProvider.tsx @@ -3,7 +3,7 @@ import React from 'react'; import {ThemeContext} from './ThemeContext'; import {ThemeSettingsContext} from './ThemeSettingsContext'; import {DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, DEFAULT_THEME} from './constants'; -import {getBodyRootClassName, getDeprecatedBodyRootClassName} from './getBodyClassName'; +import {getDeprecatedRootClassName, getRootClassName} from './getBodyClassName'; import type {RealTheme, Theme} from './types'; import {updateBodyClassName} from './updateBodyClassName'; import {useSystemTheme} from './useSystemTheme'; @@ -62,10 +62,10 @@ export function ThemeProvider({ {scoped ? (
, ) { return b(modifier); } -export function getBodyRootClassName( +export function getRootClassName( modifier?: Partial, addition?: string[], ) { return bNew(modifier, addition); } -export function getBaseBodyRootClassName(theme?: RealTheme) { - return getBodyRootClassName({theme}); +export function getInitialRootClassName(theme?: RealTheme) { + return getRootClassName({theme}); } diff --git a/src/components/theme/index.ts b/src/components/theme/index.ts index b20f30c848..baa894abfd 100644 --- a/src/components/theme/index.ts +++ b/src/components/theme/index.ts @@ -8,5 +8,5 @@ export * from './useThemeType'; export * from './withTheme'; export * from './withThemeValue'; export * from './getThemeType'; -export {getBaseBodyRootClassName} from './getBodyClassName'; +export {getInitialRootClassName} from './getBodyClassName'; export type {Theme, RealTheme, ThemeType} from './types'; diff --git a/src/components/theme/updateBodyClassName.ts b/src/components/theme/updateBodyClassName.ts index 135cbd084a..02d3ffbf3f 100644 --- a/src/components/theme/updateBodyClassName.ts +++ b/src/components/theme/updateBodyClassName.ts @@ -1,10 +1,10 @@ import {modsClassName} from '../utils/cn'; -import {getBodyRootClassName, getDeprecatedBodyRootClassName} from './getBodyClassName'; +import {getDeprecatedRootClassName, getRootClassName} from './getBodyClassName'; import type {RealTheme} from './types'; -const rootClassName = getDeprecatedBodyRootClassName(); -const rootNewClassName = getBodyRootClassName(); +const rootClassName = getDeprecatedRootClassName(); +const rootNewClassName = getRootClassName(); export type BodyClassNameModifiers = { 'native-scrollbar': boolean; @@ -39,22 +39,19 @@ export function updateBodyClassName( } [...bodyEl.classList].forEach((cls) => { - if (cls.startsWith(modsClassName(getDeprecatedBodyRootClassName({theme: true})))) { + if (cls.startsWith(modsClassName(getDeprecatedRootClassName({theme: true})))) { bodyEl.classList.remove(cls); } - if (cls.startsWith(modsClassName(getBodyRootClassName({theme: true})))) { + if (cls.startsWith(modsClassName(getRootClassName({theme: true})))) { bodyEl.classList.remove(cls); } }); - bodyEl.classList.add(modsClassName(getDeprecatedBodyRootClassName({theme: newTheme}))); - bodyEl.classList.add(modsClassName(getBodyRootClassName({theme: newTheme}))); + bodyEl.classList.add(modsClassName(getDeprecatedRootClassName({theme: newTheme}))); + bodyEl.classList.add(modsClassName(getRootClassName({theme: newTheme}))); for (const [key, value] of Object.entries({...defaultModifiers, ...modifiers})) { - bodyEl.classList.toggle( - modsClassName(getDeprecatedBodyRootClassName({[key]: true})), - value, - ); - bodyEl.classList.toggle(modsClassName(getBodyRootClassName({[key]: true})), value); + bodyEl.classList.toggle(modsClassName(getDeprecatedRootClassName({[key]: true})), value); + bodyEl.classList.toggle(modsClassName(getRootClassName({[key]: true})), value); } } From 89aa963728bc525806e08e9ed4464467fcdb26bc Mon Sep 17 00:00:00 2001 From: el-makarova Date: Mon, 25 Dec 2023 18:13:32 +0300 Subject: [PATCH 4/4] fix: code-review --- README.md | 2 +- src/components/theme/getBodyClassName.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3fe2f2f098..d2edd26615 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ it is possible to generate initial CSS-classes during SSR: import {getInitialRootClassName} from '@gravity-ui/uikit'; const theme = 'light'; -const rootClassName = getInitialRootClassName(theme); +const rootClassName = getInitialRootClassName({theme}); ``` ```js diff --git a/src/components/theme/getBodyClassName.ts b/src/components/theme/getBodyClassName.ts index c8402496d5..5c658a49f7 100644 --- a/src/components/theme/getBodyClassName.ts +++ b/src/components/theme/getBodyClassName.ts @@ -20,6 +20,7 @@ export function getRootClassName( return bNew(modifier, addition); } -export function getInitialRootClassName(theme?: RealTheme) { +export function getInitialRootClassName(props: {theme?: RealTheme} = {}) { + const {theme} = props; return getRootClassName({theme}); }