From 6fdefea794f97d971c2497a16363f938bf501e86 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 23 Nov 2023 18:43:55 +0900 Subject: [PATCH 01/29] feat: implement alpha bezier provider (wip) --- .../src/providers/AlphaBezierProvider.tsx | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 packages/bezier-react/src/providers/AlphaBezierProvider.tsx diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx new file mode 100644 index 0000000000..c251317e99 --- /dev/null +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -0,0 +1,62 @@ +import React, { + useEffect, + useMemo, +} from 'react' + +import { tokens } from '@channel.io/bezier-tokens' + +import { document } from '~/src//utils/domUtils' +import { createContext } from '~/src/utils/reactUtils' + +// TODO: Change theme name constant to import from bezier-tokens +type ThemeName = 'light' | 'dark' + +const tokenSet = { + light: { + ...tokens.global, + ...tokens.lightTheme, + }, + dark: { + ...tokens.global, + ...tokens.darkTheme, + }, +} as const + +interface ThemeContextValue { + themeName: ThemeName + tokens: typeof tokenSet[ThemeName] +} + +const [ThemeContextProvider] = + createContext(null, 'ThemeContext') + +interface AlphaBezierProviderProps { + themeName?: ThemeName + children: React.ReactNode +} + +function AlphaBezierProvider({ + themeName = 'light', + children, +}: AlphaBezierProviderProps) { + useEffect(function updateThemeDataAttribute() { + const root = document.documentElement + // TODO: Change data attribute constant to import from bezier-tokens + root.setAttribute('data-bezier-theme', themeName) + return function cleanup() { + root.removeAttribute('data-bezier-theme') + } + }, [themeName]) + + return ( + ({ + themeName, + tokens: tokenSet[themeName], + }), [themeName])} + > + { children } + + ) +} + +export default AlphaBezierProvider From 3e0fa8fe2d8b107a99e9889c7b729a21aa4051c6 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 23 Nov 2023 19:04:36 +0900 Subject: [PATCH 02/29] feat(styles): add color-scheme style --- packages/bezier-react/src/styles/_base.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index 986b49235a..605f44baab 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -1,6 +1,16 @@ html { font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); + + color-scheme: light; + + &[data-bezier-theme='light'] { + color-scheme: light; + } + + &[data-bezier-theme='dark'] { + color-scheme: dark; + } } :lang(ja) { From 0b4e6eab859203600be35f7d91608be5510e0924 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 23 Nov 2023 19:06:09 +0900 Subject: [PATCH 03/29] chore(styles): add comment --- packages/bezier-react/src/styles/_base.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index 605f44baab..58c9c2791a 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -4,10 +4,12 @@ html { color-scheme: light; + // TODO: Change data attribute constant to import from bezier-tokens &[data-bezier-theme='light'] { color-scheme: light; } + // TODO: Change data attribute constant to import from bezier-tokens &[data-bezier-theme='dark'] { color-scheme: dark; } From 1c73be343c71f15e21f1aaad89e10c25093ed6d3 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 23 Nov 2023 19:09:55 +0900 Subject: [PATCH 04/29] feat(styles): add base font color style --- packages/bezier-react/src/styles/_base.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index 58c9c2791a..69c08181e0 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -1,6 +1,7 @@ html { font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); + color: var(--txt-black-darkest); color-scheme: light; From 99351609709e0f5ed4ff8c73286a6ae71f5097bc Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 17:10:32 +0900 Subject: [PATCH 05/29] feat(bezier-react): implement useToken hook --- packages/bezier-react/src/hooks/useToken.ts | 24 ++++++++++++++ .../src/providers/AlphaBezierProvider.tsx | 31 +++++-------------- 2 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 packages/bezier-react/src/hooks/useToken.ts diff --git a/packages/bezier-react/src/hooks/useToken.ts b/packages/bezier-react/src/hooks/useToken.ts new file mode 100644 index 0000000000..b28975eaaf --- /dev/null +++ b/packages/bezier-react/src/hooks/useToken.ts @@ -0,0 +1,24 @@ +import { type tokens } from '@channel.io/bezier-tokens' + +import { createContext } from '~/src/utils/reactUtils' + +type Tokens = typeof tokens +type GlobalTokens = Tokens['global'] +type SemanticTokens = Omit + +export type TokenContextValue = GlobalTokens & SemanticTokens[keyof SemanticTokens] + +const [TokenContextProvider, useTokenContext] = createContext(null, 'ThemeContext') + +function useToken() { + return useTokenContext('useToken') +} + +export { + /** For internal use only. + * @private + */ + TokenContextProvider, +} + +export default useToken diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index c251317e99..25a929c20e 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -1,17 +1,14 @@ -import React, { - useEffect, - useMemo, -} from 'react' +import React, { useEffect } from 'react' import { tokens } from '@channel.io/bezier-tokens' -import { document } from '~/src//utils/domUtils' -import { createContext } from '~/src/utils/reactUtils' +import { TokenContextProvider } from '~/src/hooks/useToken' +import { document } from '~/src/utils/domUtils' // TODO: Change theme name constant to import from bezier-tokens -type ThemeName = 'light' | 'dark' +export type ThemeName = 'light' | 'dark' -const tokenSet = { +const tokenSet = Object.freeze({ light: { ...tokens.global, ...tokens.lightTheme, @@ -20,15 +17,7 @@ const tokenSet = { ...tokens.global, ...tokens.darkTheme, }, -} as const - -interface ThemeContextValue { - themeName: ThemeName - tokens: typeof tokenSet[ThemeName] -} - -const [ThemeContextProvider] = - createContext(null, 'ThemeContext') +} as const) interface AlphaBezierProviderProps { themeName?: ThemeName @@ -49,13 +38,9 @@ function AlphaBezierProvider({ }, [themeName]) return ( - ({ - themeName, - tokens: tokenSet[themeName], - }), [themeName])} - > + { children } - + ) } From 244f5cf855635ed027f732882519f3ee4fb64efd Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 17:34:59 +0900 Subject: [PATCH 06/29] refactor(use-token): include token set --- packages/bezier-react/src/hooks/useToken.ts | 24 -------- packages/bezier-react/src/hooks/useToken.tsx | 57 +++++++++++++++++++ .../src/providers/AlphaBezierProvider.tsx | 25 ++------ 3 files changed, 63 insertions(+), 43 deletions(-) delete mode 100644 packages/bezier-react/src/hooks/useToken.ts create mode 100644 packages/bezier-react/src/hooks/useToken.tsx diff --git a/packages/bezier-react/src/hooks/useToken.ts b/packages/bezier-react/src/hooks/useToken.ts deleted file mode 100644 index b28975eaaf..0000000000 --- a/packages/bezier-react/src/hooks/useToken.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { type tokens } from '@channel.io/bezier-tokens' - -import { createContext } from '~/src/utils/reactUtils' - -type Tokens = typeof tokens -type GlobalTokens = Tokens['global'] -type SemanticTokens = Omit - -export type TokenContextValue = GlobalTokens & SemanticTokens[keyof SemanticTokens] - -const [TokenContextProvider, useTokenContext] = createContext(null, 'ThemeContext') - -function useToken() { - return useTokenContext('useToken') -} - -export { - /** For internal use only. - * @private - */ - TokenContextProvider, -} - -export default useToken diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx new file mode 100644 index 0000000000..326c752710 --- /dev/null +++ b/packages/bezier-react/src/hooks/useToken.tsx @@ -0,0 +1,57 @@ +import React from 'react' + +import { tokens } from '@channel.io/bezier-tokens' + +import { createContext } from '~/src/utils/reactUtils' + +type Tokens = typeof tokens +type GlobalTokens = Tokens['global'] +type SemanticTokens = Omit + +export type TokenContextValue = GlobalTokens & SemanticTokens[keyof SemanticTokens] + +const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') + +// TODO: Change theme name constant to import from bezier-tokens +export type ThemeName = 'light' | 'dark' + +const tokenSet: Record = Object.freeze({ + light: { + ...tokens.global, + ...tokens.lightTheme, + }, + dark: { + ...tokens.global, + ...tokens.darkTheme, + }, +}) + +/** + * For internal use only. + * @private + */ +export interface TokenProviderProps { + themeName: ThemeName + children: React.ReactNode +} + +/** + * For internal use only. + * @private + */ +export function TokenProvider({ + themeName, + children, +}: TokenProviderProps) { + return ( + + { children } + + ) +} + +function useToken() { + return useTokenContext('useToken') +} + +export default useToken diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index 25a929c20e..de66950e5d 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -1,24 +1,11 @@ import React, { useEffect } from 'react' -import { tokens } from '@channel.io/bezier-tokens' - -import { TokenContextProvider } from '~/src/hooks/useToken' +import { + type ThemeName, + TokenProvider, +} from '~/src/hooks/useToken' import { document } from '~/src/utils/domUtils' -// TODO: Change theme name constant to import from bezier-tokens -export type ThemeName = 'light' | 'dark' - -const tokenSet = Object.freeze({ - light: { - ...tokens.global, - ...tokens.lightTheme, - }, - dark: { - ...tokens.global, - ...tokens.darkTheme, - }, -} as const) - interface AlphaBezierProviderProps { themeName?: ThemeName children: React.ReactNode @@ -38,9 +25,9 @@ function AlphaBezierProvider({ }, [themeName]) return ( - + { children } - + ) } From 1677c2f8869f260db6b6b27e8087e1a0cdf90b91 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 18:09:34 +0900 Subject: [PATCH 07/29] feat(use-tokens): add themeName value to context value and implement useThemeName hook --- packages/bezier-react/src/hooks/useToken.tsx | 28 +++++++++++++------ .../src/providers/AlphaBezierProvider.tsx | 4 +-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx index 326c752710..66d4b8451d 100644 --- a/packages/bezier-react/src/hooks/useToken.tsx +++ b/packages/bezier-react/src/hooks/useToken.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useMemo } from 'react' import { tokens } from '@channel.io/bezier-tokens' @@ -7,15 +7,19 @@ import { createContext } from '~/src/utils/reactUtils' type Tokens = typeof tokens type GlobalTokens = Tokens['global'] type SemanticTokens = Omit - -export type TokenContextValue = GlobalTokens & SemanticTokens[keyof SemanticTokens] - -const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') +type FlattedTokens = GlobalTokens & SemanticTokens[keyof SemanticTokens] // TODO: Change theme name constant to import from bezier-tokens export type ThemeName = 'light' | 'dark' -const tokenSet: Record = Object.freeze({ +export interface TokenContextValue { + themeName: ThemeName + tokens: FlattedTokens +} + +const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') + +const tokenSet: Record = Object.freeze({ light: { ...tokens.global, ...tokens.lightTheme, @@ -44,14 +48,22 @@ export function TokenProvider({ children, }: TokenProviderProps) { return ( - + ({ + themeName, + tokens: tokenSet[themeName], + }), [themeName])} + > { children } ) } +export function useThemeName() { + return useTokenContext('useThemeName').themeName +} + function useToken() { - return useTokenContext('useToken') + return useTokenContext('useToken').tokens } export default useToken diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index de66950e5d..1be28ce2b5 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -7,13 +7,13 @@ import { import { document } from '~/src/utils/domUtils' interface AlphaBezierProviderProps { - themeName?: ThemeName children: React.ReactNode + themeName?: ThemeName } function AlphaBezierProvider({ - themeName = 'light', children, + themeName = 'light', }: AlphaBezierProviderProps) { useEffect(function updateThemeDataAttribute() { const root = document.documentElement From b0fc27bd5eb8e9157b6cf8881ff5600923b54804 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 18:11:46 +0900 Subject: [PATCH 08/29] feat: implement fixed theme providers --- .../src/providers/FixedThemeProvider.tsx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 packages/bezier-react/src/providers/FixedThemeProvider.tsx diff --git a/packages/bezier-react/src/providers/FixedThemeProvider.tsx b/packages/bezier-react/src/providers/FixedThemeProvider.tsx new file mode 100644 index 0000000000..f560240f54 --- /dev/null +++ b/packages/bezier-react/src/providers/FixedThemeProvider.tsx @@ -0,0 +1,54 @@ +import React from 'react' + +import { Slot } from '@radix-ui/react-slot' + +import { + type ThemeName, + TokenProvider, + useThemeName, +} from '~/src/hooks/useToken' + +interface FixedThemeProviderBuilderProps { + themeName: ThemeName + children: React.ReactElement +} + +type FixedThemeProviderProps = Omit + +function FixedThemeProviderBuilder({ + themeName, + children, +}: FixedThemeProviderBuilderProps) { + return ( + + { /* TODO: Change data attribute constant to import from bezier-tokens */ } + + { children } + + + ) +} + +export function LightTheme({ children }: FixedThemeProviderProps) { + return ( + + { children } + + ) +} + +export function DarkTheme({ children }: FixedThemeProviderProps) { + return ( + + { children } + + ) +} + +export function InvertedTheme({ children }: FixedThemeProviderProps) { + return ( + + { children } + + ) +} From 367a0c62503f221d67dc20f59a7b4b41be97d54e Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 20:29:50 +0900 Subject: [PATCH 09/29] feat(alpha-bezier-provider): add tooltip provider --- packages/bezier-react/src/providers/AlphaBezierProvider.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index 1be28ce2b5..cf1f308265 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -6,6 +6,8 @@ import { } from '~/src/hooks/useToken' import { document } from '~/src/utils/domUtils' +import { TooltipProvider } from '~/src/components/Tooltip' + interface AlphaBezierProviderProps { children: React.ReactNode themeName?: ThemeName @@ -26,7 +28,9 @@ function AlphaBezierProvider({ return ( - { children } + + { children } + ) } From 187450b58c1f113ffd6f9aeae857324dbfa21b8e Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 21:20:39 +0900 Subject: [PATCH 10/29] feat(alpha-bezier-provider): consider when other root elements may exist, such as a shadow DOM --- .../bezier-react/src/providers/AlphaBezierProvider.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index cf1f308265..7bf8597eea 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -11,20 +11,24 @@ import { TooltipProvider } from '~/src/components/Tooltip' interface AlphaBezierProviderProps { children: React.ReactNode themeName?: ThemeName + root?: HTMLElement } function AlphaBezierProvider({ children, themeName = 'light', + root = document.documentElement, }: AlphaBezierProviderProps) { useEffect(function updateThemeDataAttribute() { - const root = document.documentElement // TODO: Change data attribute constant to import from bezier-tokens root.setAttribute('data-bezier-theme', themeName) return function cleanup() { root.removeAttribute('data-bezier-theme') } - }, [themeName]) + }, [ + root, + themeName, + ]) return ( From 52bc57d67baa38574af63c39ce2863578320108e Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 21:32:19 +0900 Subject: [PATCH 11/29] feat(alpha-bezier-provider): add feature provider --- packages/bezier-react/src/features/index.ts | 1 + .../src/providers/AlphaBezierProvider.tsx | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/bezier-react/src/features/index.ts b/packages/bezier-react/src/features/index.ts index d63c91c461..1dc94e5a4e 100644 --- a/packages/bezier-react/src/features/index.ts +++ b/packages/bezier-react/src/features/index.ts @@ -1,3 +1,4 @@ +export type { Feature } from './Feature' export { FeatureType } from './Feature' export { diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx index 7bf8597eea..d688c2cf66 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaBezierProvider.tsx @@ -1,5 +1,9 @@ import React, { useEffect } from 'react' +import { + type Feature, + FeatureProvider, +} from '~/src/features' import { type ThemeName, TokenProvider, @@ -11,12 +15,14 @@ import { TooltipProvider } from '~/src/components/Tooltip' interface AlphaBezierProviderProps { children: React.ReactNode themeName?: ThemeName + features?: Feature[] root?: HTMLElement } function AlphaBezierProvider({ children, themeName = 'light', + features = [], root = document.documentElement, }: AlphaBezierProviderProps) { useEffect(function updateThemeDataAttribute() { @@ -32,9 +38,11 @@ function AlphaBezierProvider({ return ( - - { children } - + + + { children } + + ) } From c10dc90c8340aa47d345064608f06b55eb38bbf5 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 21:36:53 +0900 Subject: [PATCH 12/29] refactor: rename to AlphaAppProvider To emphasize that this is the provider you use for the root of your app. --- .../{AlphaBezierProvider.tsx => AlphaAppProvider.tsx} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename packages/bezier-react/src/providers/{AlphaBezierProvider.tsx => AlphaAppProvider.tsx} (88%) diff --git a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx similarity index 88% rename from packages/bezier-react/src/providers/AlphaBezierProvider.tsx rename to packages/bezier-react/src/providers/AlphaAppProvider.tsx index d688c2cf66..ec26e4d0e9 100644 --- a/packages/bezier-react/src/providers/AlphaBezierProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -12,19 +12,19 @@ import { document } from '~/src/utils/domUtils' import { TooltipProvider } from '~/src/components/Tooltip' -interface AlphaBezierProviderProps { +interface AlphaAppProviderProps { children: React.ReactNode themeName?: ThemeName features?: Feature[] root?: HTMLElement } -function AlphaBezierProvider({ +function AlphaAppProvider({ children, themeName = 'light', features = [], root = document.documentElement, -}: AlphaBezierProviderProps) { +}: AlphaAppProviderProps) { useEffect(function updateThemeDataAttribute() { // TODO: Change data attribute constant to import from bezier-tokens root.setAttribute('data-bezier-theme', themeName) @@ -47,4 +47,4 @@ function AlphaBezierProvider({ ) } -export default AlphaBezierProvider +export default AlphaAppProvider From 58e123a397d390bd82e1620e204ba47c76d6ddae Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 21:39:06 +0900 Subject: [PATCH 13/29] fix(styles): change html to where selector to support shadow root host element --- packages/bezier-react/src/styles/_base.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index 69c08181e0..4f80d1da22 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -1,4 +1,4 @@ -html { +:where(:root, :host) { font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); color: var(--txt-black-darkest); From 7975f56ec764dcfb3474797742447c05abc5be56 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Tue, 28 Nov 2023 21:54:57 +0900 Subject: [PATCH 14/29] fix(styles): change data selector to affect all elements --- packages/bezier-react/src/styles/_base.scss | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index 4f80d1da22..b265edfeef 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -2,18 +2,17 @@ font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); color: var(--txt-black-darkest); - color-scheme: light; +} - // TODO: Change data attribute constant to import from bezier-tokens - &[data-bezier-theme='light'] { - color-scheme: light; - } +// TODO: Change data attribute constant to import from bezier-tokens +[data-bezier-theme='light'] { + color-scheme: light; +} - // TODO: Change data attribute constant to import from bezier-tokens - &[data-bezier-theme='dark'] { - color-scheme: dark; - } +// TODO: Change data attribute constant to import from bezier-tokens +[data-bezier-theme='dark'] { + color-scheme: dark; } :lang(ja) { From 59158f4a4b888184ee0bbd1f4bcd5363dd637f47 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 14:04:28 +0900 Subject: [PATCH 15/29] refactor(alpha-app-provider): rename prop --- .../bezier-react/src/providers/AlphaAppProvider.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index ec26e4d0e9..349799a26c 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -16,23 +16,23 @@ interface AlphaAppProviderProps { children: React.ReactNode themeName?: ThemeName features?: Feature[] - root?: HTMLElement + rootElement?: HTMLElement } function AlphaAppProvider({ children, themeName = 'light', features = [], - root = document.documentElement, + rootElement = document.documentElement, }: AlphaAppProviderProps) { useEffect(function updateThemeDataAttribute() { // TODO: Change data attribute constant to import from bezier-tokens - root.setAttribute('data-bezier-theme', themeName) + rootElement.setAttribute('data-bezier-theme', themeName) return function cleanup() { - root.removeAttribute('data-bezier-theme') + rootElement.removeAttribute('data-bezier-theme') } }, [ - root, + rootElement, themeName, ]) From 0ed795c3c8a17bf153370570427a6021540b1856 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 16:50:20 +0900 Subject: [PATCH 16/29] docs(alpha-app-provider): add jsdoc --- .../src/providers/AlphaAppProvider.tsx | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index 349799a26c..d38f064979 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -14,16 +14,48 @@ import { TooltipProvider } from '~/src/components/Tooltip' interface AlphaAppProviderProps { children: React.ReactNode + /** + * Name of the theme to use for the app. + * @default 'light' + */ themeName?: ThemeName + /** + * List of features to enable for the app. + * @default [] + */ features?: Feature[] + /** + * Root element to apply theme data attribute to. + * @default document.body + */ rootElement?: HTMLElement } +/** + * `AlphaAppProvider` is a required wrapper component that provides context for the app. + * + * @example + * + * ```tsx + * import React from 'react' + * import { createRoot } from 'react-dom/client' + * import { AlphaAppProvider } from '@channel.io/bezier-react' + * + * const container = document.getElementById('root') + * const root = createRoot(container) + * + * root.render( + * + * + * , + * ) + * ``` + */ function AlphaAppProvider({ children, themeName = 'light', features = [], - rootElement = document.documentElement, + rootElement = document.body, }: AlphaAppProviderProps) { useEffect(function updateThemeDataAttribute() { // TODO: Change data attribute constant to import from bezier-tokens From 4462f81af1dfbd206c2be1e12788ce5ab7c84b1d Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 16:56:37 +0900 Subject: [PATCH 17/29] docs: add jsdoc --- packages/bezier-react/src/hooks/useToken.tsx | 6 ++++++ .../bezier-react/src/providers/FixedThemeProvider.tsx | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx index 66d4b8451d..60a1328820 100644 --- a/packages/bezier-react/src/hooks/useToken.tsx +++ b/packages/bezier-react/src/hooks/useToken.tsx @@ -58,10 +58,16 @@ export function TokenProvider({ ) } +/** + * `useThemeName` is a hook that returns the current theme name. + */ export function useThemeName() { return useTokenContext('useThemeName').themeName } +/** + * `useToken` is a hook that returns the design token for the current theme. + */ function useToken() { return useTokenContext('useToken').tokens } diff --git a/packages/bezier-react/src/providers/FixedThemeProvider.tsx b/packages/bezier-react/src/providers/FixedThemeProvider.tsx index f560240f54..8029459d15 100644 --- a/packages/bezier-react/src/providers/FixedThemeProvider.tsx +++ b/packages/bezier-react/src/providers/FixedThemeProvider.tsx @@ -29,6 +29,9 @@ function FixedThemeProviderBuilder({ ) } +/** + * `LightTheme` is a wrapper component that provides light theme context. + */ export function LightTheme({ children }: FixedThemeProviderProps) { return ( @@ -37,6 +40,9 @@ export function LightTheme({ children }: FixedThemeProviderProps) { ) } +/** + * `DarkTheme` is a wrapper component that provides dark theme context. + */ export function DarkTheme({ children }: FixedThemeProviderProps) { return ( @@ -45,6 +51,9 @@ export function DarkTheme({ children }: FixedThemeProviderProps) { ) } +/** + * `InvertedTheme` is a wrapper component that provides inverted theme context. + */ export function InvertedTheme({ children }: FixedThemeProviderProps) { return ( From 4c3c8873f54d841247a6f9c586cd2a974e915c72 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 17:09:09 +0900 Subject: [PATCH 18/29] feat(root): export modules --- packages/bezier-react/src/hooks/useToken.tsx | 6 ++---- packages/bezier-react/src/index.ts | 7 +++++++ packages/bezier-react/src/providers/AlphaAppProvider.tsx | 6 ++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx index 60a1328820..1f2cf312b3 100644 --- a/packages/bezier-react/src/hooks/useToken.tsx +++ b/packages/bezier-react/src/hooks/useToken.tsx @@ -12,7 +12,7 @@ type FlattedTokens = GlobalTokens & SemanticTokens[keyof SemanticTokens] // TODO: Change theme name constant to import from bezier-tokens export type ThemeName = 'light' | 'dark' -export interface TokenContextValue { +interface TokenContextValue { themeName: ThemeName tokens: FlattedTokens } @@ -68,8 +68,6 @@ export function useThemeName() { /** * `useToken` is a hook that returns the design token for the current theme. */ -function useToken() { +export function useToken() { return useTokenContext('useToken').tokens } - -export default useToken diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index f867045692..423fdfcce4 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -3,6 +3,8 @@ import '~/src/styles/index.scss' /* Provider */ export { default as BezierProvider } from '~/src/providers/BezierProvider' export { default as WindowProvider, useWindow } from '~/src/providers/WindowProvider' +export * from '~/src/providers/AlphaAppProvider' +export * from '~/src/providers/FixedThemeProvider' /* Foundation */ export * from '~/src/foundation' @@ -77,6 +79,11 @@ export { ZIndex } from '~/src/constants/ZIndex' export { default as useEventHandler } from '~/src/hooks/useEventHandler' export { default as useMergeRefs } from '~/src/hooks/useMergeRefs' export { default as useId } from '~/src/hooks/useId' +export { + useToken, + useThemeName, + type ThemeName, +} from '~/src/hooks/useToken' /* Utils */ export { getRootElement } from '~/src/utils/dom' diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index d38f064979..e42679183b 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -12,7 +12,7 @@ import { document } from '~/src/utils/domUtils' import { TooltipProvider } from '~/src/components/Tooltip' -interface AlphaAppProviderProps { +export interface AlphaAppProviderProps { children: React.ReactNode /** * Name of the theme to use for the app. @@ -51,7 +51,7 @@ interface AlphaAppProviderProps { * ) * ``` */ -function AlphaAppProvider({ +export function AlphaAppProvider({ children, themeName = 'light', features = [], @@ -78,5 +78,3 @@ function AlphaAppProvider({ ) } - -export default AlphaAppProvider From 45606aa625e0df7253af1ea08d710cebd3867fb7 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 17:10:33 +0900 Subject: [PATCH 19/29] chore(changeset): add changeset --- .changeset/chilled-dots-divide.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilled-dots-divide.md diff --git a/.changeset/chilled-dots-divide.md b/.changeset/chilled-dots-divide.md new file mode 100644 index 0000000000..a687358a76 --- /dev/null +++ b/.changeset/chilled-dots-divide.md @@ -0,0 +1,5 @@ +--- +"@channel.io/bezier-react": minor +--- + +Implement multi theme feature based on data attributes. From dce4b9c3b649beca6b9389a85a428278b0a8f942 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 17:32:35 +0900 Subject: [PATCH 20/29] fix: fix typecheck error --- packages/bezier-react/src/hooks/useToken.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx index 1f2cf312b3..d6b3d371ec 100644 --- a/packages/bezier-react/src/hooks/useToken.tsx +++ b/packages/bezier-react/src/hooks/useToken.tsx @@ -30,11 +30,7 @@ const tokenSet: Record = Object.freeze({ }, }) -/** - * For internal use only. - * @private - */ -export interface TokenProviderProps { +interface TokenProviderProps { themeName: ThemeName children: React.ReactNode } From e96e4de8b8abd3f7a75447ca6f27ed0d1e6c7040 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 19:52:04 +0900 Subject: [PATCH 21/29] fix: fix import path --- packages/bezier-react/src/providers/AlphaAppProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index e42679183b..8669b238ea 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -8,7 +8,7 @@ import { type ThemeName, TokenProvider, } from '~/src/hooks/useToken' -import { document } from '~/src/utils/domUtils' +import { document } from '~/src/utils/dom' import { TooltipProvider } from '~/src/components/Tooltip' From c943fa15f9b260cc2c7e7f138329770c70c1204b Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 20:39:02 +0900 Subject: [PATCH 22/29] refactor(window-provider): rm document from window provider --- .../bezier-react/src/providers/BezierProvider.tsx | 12 +++--------- .../bezier-react/src/providers/WindowProvider.tsx | 11 +++-------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/packages/bezier-react/src/providers/BezierProvider.tsx b/packages/bezier-react/src/providers/BezierProvider.tsx index 88760007f3..52e20dee9d 100644 --- a/packages/bezier-react/src/providers/BezierProvider.tsx +++ b/packages/bezier-react/src/providers/BezierProvider.tsx @@ -9,10 +9,7 @@ import { type ThemeVarsAdditionalType, } from '~/src/foundation' -import { - document as defaultDocument, - window as defaultWindow, -} from '~/src/utils/dom' +import { window as defaultWindow } from '~/src/utils/dom' import { TooltipProvider } from '~/src/components/Tooltip' @@ -29,13 +26,10 @@ function BezierProvider({ foundation, children, themeVarsScope, - externalWindow, + externalWindow = defaultWindow, }: BezierProviderProps) { return ( - + diff --git a/packages/bezier-react/src/providers/WindowProvider.tsx b/packages/bezier-react/src/providers/WindowProvider.tsx index 74033d08cb..e4107a1cdb 100644 --- a/packages/bezier-react/src/providers/WindowProvider.tsx +++ b/packages/bezier-react/src/providers/WindowProvider.tsx @@ -23,19 +23,14 @@ interface WindowProviderProps extends PropsWithChildren { * @required */ window: Window - - /** - * injected document - * @required - */ - document: Document } /** * A Provider that provides window and document object * you can use this provider to inject an external window */ -function WindowProvider({ window, document, children }: WindowProviderProps) { +function WindowProvider({ window, children }: WindowProviderProps) { + const document = window.document const rootElement = document.body const value = useMemo(() => ({ @@ -43,8 +38,8 @@ function WindowProvider({ window, document, children }: WindowProviderProps) { document, rootElement, }), [ - document, window, + document, rootElement, ]) From 3c9889320d4d88a73164f6e7b0b58f61e61ceb27 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 20:39:53 +0900 Subject: [PATCH 23/29] feat(alpha-app-provider): apply WindowProvider and add window prop --- .../src/providers/AlphaAppProvider.tsx | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index 8669b238ea..3dc49e5b3f 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -8,10 +8,12 @@ import { type ThemeName, TokenProvider, } from '~/src/hooks/useToken' -import { document } from '~/src/utils/dom' +import { window as defaultWindow } from '~/src/utils/dom' import { TooltipProvider } from '~/src/components/Tooltip' +import WindowProvider from './WindowProvider' + export interface AlphaAppProviderProps { children: React.ReactNode /** @@ -25,8 +27,13 @@ export interface AlphaAppProviderProps { */ features?: Feature[] /** - * Root element to apply theme data attribute to. - * @default document.body + * Window object to use for the app. + * @default window + */ + window?: Window + /** + * Root element to apply theme data attribute to. window of default value is a window object passed by `window` prop + * @default window.document.body */ rootElement?: HTMLElement } @@ -55,7 +62,8 @@ export function AlphaAppProvider({ children, themeName = 'light', features = [], - rootElement = document.body, + window = defaultWindow, + rootElement = window.document.body, }: AlphaAppProviderProps) { useEffect(function updateThemeDataAttribute() { // TODO: Change data attribute constant to import from bezier-tokens @@ -69,12 +77,14 @@ export function AlphaAppProvider({ ]) return ( - - - - { children } - - - + + + + + { children } + + + + ) } From f2090b9f4c947440288b0833bb1859e2443168e1 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 23:09:34 +0900 Subject: [PATCH 24/29] feat(alpha-app-provider): change to use ThemeProvider internally --- packages/bezier-react/src/hooks/useToken.tsx | 69 --------- packages/bezier-react/src/index.ts | 9 +- .../src/providers/AlphaAppProvider.tsx | 45 ++---- .../src/providers/BezierProvider.tsx | 2 +- .../src/providers/FixedThemeProvider.tsx | 63 -------- .../src/providers/ThemeProvider.tsx | 144 ++++++++++++++++++ .../src/providers/WindowProvider.tsx | 4 +- 7 files changed, 163 insertions(+), 173 deletions(-) delete mode 100644 packages/bezier-react/src/hooks/useToken.tsx delete mode 100644 packages/bezier-react/src/providers/FixedThemeProvider.tsx create mode 100644 packages/bezier-react/src/providers/ThemeProvider.tsx diff --git a/packages/bezier-react/src/hooks/useToken.tsx b/packages/bezier-react/src/hooks/useToken.tsx deleted file mode 100644 index d6b3d371ec..0000000000 --- a/packages/bezier-react/src/hooks/useToken.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useMemo } from 'react' - -import { tokens } from '@channel.io/bezier-tokens' - -import { createContext } from '~/src/utils/reactUtils' - -type Tokens = typeof tokens -type GlobalTokens = Tokens['global'] -type SemanticTokens = Omit -type FlattedTokens = GlobalTokens & SemanticTokens[keyof SemanticTokens] - -// TODO: Change theme name constant to import from bezier-tokens -export type ThemeName = 'light' | 'dark' - -interface TokenContextValue { - themeName: ThemeName - tokens: FlattedTokens -} - -const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') - -const tokenSet: Record = Object.freeze({ - light: { - ...tokens.global, - ...tokens.lightTheme, - }, - dark: { - ...tokens.global, - ...tokens.darkTheme, - }, -}) - -interface TokenProviderProps { - themeName: ThemeName - children: React.ReactNode -} - -/** - * For internal use only. - * @private - */ -export function TokenProvider({ - themeName, - children, -}: TokenProviderProps) { - return ( - ({ - themeName, - tokens: tokenSet[themeName], - }), [themeName])} - > - { children } - - ) -} - -/** - * `useThemeName` is a hook that returns the current theme name. - */ -export function useThemeName() { - return useTokenContext('useThemeName').themeName -} - -/** - * `useToken` is a hook that returns the design token for the current theme. - */ -export function useToken() { - return useTokenContext('useToken').tokens -} diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index 423fdfcce4..f147483761 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -2,9 +2,9 @@ import '~/src/styles/index.scss' /* Provider */ export { default as BezierProvider } from '~/src/providers/BezierProvider' -export { default as WindowProvider, useWindow } from '~/src/providers/WindowProvider' +export * from '~/src/providers/WindowProvider' export * from '~/src/providers/AlphaAppProvider' -export * from '~/src/providers/FixedThemeProvider' +export * from '~/src/providers/ThemeProvider' /* Foundation */ export * from '~/src/foundation' @@ -79,11 +79,6 @@ export { ZIndex } from '~/src/constants/ZIndex' export { default as useEventHandler } from '~/src/hooks/useEventHandler' export { default as useMergeRefs } from '~/src/hooks/useMergeRefs' export { default as useId } from '~/src/hooks/useId' -export { - useToken, - useThemeName, - type ThemeName, -} from '~/src/hooks/useToken' /* Utils */ export { getRootElement } from '~/src/utils/dom' diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index 3dc49e5b3f..8ee68adf9e 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -1,18 +1,18 @@ -import React, { useEffect } from 'react' +import React from 'react' import { type Feature, FeatureProvider, } from '~/src/features' -import { - type ThemeName, - TokenProvider, -} from '~/src/hooks/useToken' import { window as defaultWindow } from '~/src/utils/dom' import { TooltipProvider } from '~/src/components/Tooltip' -import WindowProvider from './WindowProvider' +import { + type ThemeName, + ThemeProvider, +} from './ThemeProvider' +import { WindowProvider } from './WindowProvider' export interface AlphaAppProviderProps { children: React.ReactNode @@ -31,11 +31,6 @@ export interface AlphaAppProviderProps { * @default window */ window?: Window - /** - * Root element to apply theme data attribute to. window of default value is a window object passed by `window` prop - * @default window.document.body - */ - rootElement?: HTMLElement } /** @@ -63,28 +58,18 @@ export function AlphaAppProvider({ themeName = 'light', features = [], window = defaultWindow, - rootElement = window.document.body, }: AlphaAppProviderProps) { - useEffect(function updateThemeDataAttribute() { - // TODO: Change data attribute constant to import from bezier-tokens - rootElement.setAttribute('data-bezier-theme', themeName) - return function cleanup() { - rootElement.removeAttribute('data-bezier-theme') - } - }, [ - rootElement, - themeName, - ]) - return ( - - - - { children } - - - + + + +
+ { children } +
+
+
+
) } diff --git a/packages/bezier-react/src/providers/BezierProvider.tsx b/packages/bezier-react/src/providers/BezierProvider.tsx index 52e20dee9d..d1543bb0b1 100644 --- a/packages/bezier-react/src/providers/BezierProvider.tsx +++ b/packages/bezier-react/src/providers/BezierProvider.tsx @@ -13,7 +13,7 @@ import { window as defaultWindow } from '~/src/utils/dom' import { TooltipProvider } from '~/src/components/Tooltip' -import WindowProvider from './WindowProvider' +import { WindowProvider } from './WindowProvider' interface BezierProviderProps { foundation: Foundation & GlobalStyleProp diff --git a/packages/bezier-react/src/providers/FixedThemeProvider.tsx b/packages/bezier-react/src/providers/FixedThemeProvider.tsx deleted file mode 100644 index 8029459d15..0000000000 --- a/packages/bezier-react/src/providers/FixedThemeProvider.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react' - -import { Slot } from '@radix-ui/react-slot' - -import { - type ThemeName, - TokenProvider, - useThemeName, -} from '~/src/hooks/useToken' - -interface FixedThemeProviderBuilderProps { - themeName: ThemeName - children: React.ReactElement -} - -type FixedThemeProviderProps = Omit - -function FixedThemeProviderBuilder({ - themeName, - children, -}: FixedThemeProviderBuilderProps) { - return ( - - { /* TODO: Change data attribute constant to import from bezier-tokens */ } - - { children } - - - ) -} - -/** - * `LightTheme` is a wrapper component that provides light theme context. - */ -export function LightTheme({ children }: FixedThemeProviderProps) { - return ( - - { children } - - ) -} - -/** - * `DarkTheme` is a wrapper component that provides dark theme context. - */ -export function DarkTheme({ children }: FixedThemeProviderProps) { - return ( - - { children } - - ) -} - -/** - * `InvertedTheme` is a wrapper component that provides inverted theme context. - */ -export function InvertedTheme({ children }: FixedThemeProviderProps) { - return ( - - { children } - - ) -} diff --git a/packages/bezier-react/src/providers/ThemeProvider.tsx b/packages/bezier-react/src/providers/ThemeProvider.tsx new file mode 100644 index 0000000000..1827a8d0ed --- /dev/null +++ b/packages/bezier-react/src/providers/ThemeProvider.tsx @@ -0,0 +1,144 @@ +import React, { + forwardRef, + useMemo, +} from 'react' + +import { tokens } from '@channel.io/bezier-tokens' +import { Slot } from '@radix-ui/react-slot' + +import { createContext } from '~/src/utils/react' + +type Tokens = typeof tokens +type GlobalTokens = Tokens['global'] +type SemanticTokens = Omit +type FlattedTokens = GlobalTokens & SemanticTokens[keyof SemanticTokens] + +// TODO: Change theme name constant to import from bezier-tokens +export type ThemeName = 'light' | 'dark' + +interface TokenContextValue { + themeName: ThemeName + tokens: FlattedTokens +} + +const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') + +const tokenSet: Record = Object.freeze({ + light: { + ...tokens.global, + ...tokens.lightTheme, + }, + dark: { + ...tokens.global, + ...tokens.darkTheme, + }, +}) + +interface TokenProviderProps { + themeName: ThemeName + children: React.ReactNode +} + +function TokenProvider({ + themeName, + children, +}: TokenProviderProps) { + return ( + ({ + themeName, + tokens: tokenSet[themeName], + }), [themeName])} + > + { children } + + ) +} + +/** + * `useThemeName` is a hook that returns the current theme name. + */ +export function useThemeName() { + return useTokenContext('useThemeName').themeName +} + +/** + * `useToken` is a hook that returns the design token for the current theme. + */ +export function useToken() { + return useTokenContext('useToken').tokens +} + +export interface ThemeProviderProps { + themeName: ThemeName + children: React.ReactElement +} + +export type FixedThemeProviderProps = Omit + +/** + * `ThemeProvider` is a wrapper component that provides theme context. + */ +export const ThemeProvider = forwardRef(function ThemeProvider({ + themeName, + children, +}, forwardedRef) { + return ( + + + { children } + + + ) +}) + +/** + * `LightTheme` is a wrapper component that provides light theme context. + */ +export const LightTheme = forwardRef(function LightTheme({ + children, +}, forwardedRef) { + return ( + + { children } + + ) +}) + +/** + * `DarkTheme` is a wrapper component that provides dark theme context. + */ +export const DarkTheme = forwardRef(function DarkTheme({ + children, +}, forwardedRef) { + return ( + + { children } + + ) +}) + +/** + * `InvertedTheme` is a wrapper component that provides inverted theme context. + */ +export const InvertedTheme = forwardRef(function InvertedTheme({ + children, +}, forwardedRef) { + return ( + + { children } + + ) +}) diff --git a/packages/bezier-react/src/providers/WindowProvider.tsx b/packages/bezier-react/src/providers/WindowProvider.tsx index e4107a1cdb..e8e251660d 100644 --- a/packages/bezier-react/src/providers/WindowProvider.tsx +++ b/packages/bezier-react/src/providers/WindowProvider.tsx @@ -29,7 +29,7 @@ interface WindowProviderProps extends PropsWithChildren { * A Provider that provides window and document object * you can use this provider to inject an external window */ -function WindowProvider({ window, children }: WindowProviderProps) { +export function WindowProvider({ window, children }: WindowProviderProps) { const document = window.document const rootElement = document.body @@ -47,5 +47,3 @@ function WindowProvider({ window, children }: WindowProviderProps) { { children } ) } - -export default WindowProvider From f8befb7fa7a8d6cc08c094a3d2e5f3b0ef04717e Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Wed, 29 Nov 2023 23:29:28 +0900 Subject: [PATCH 25/29] feat(styles): rm root color scheme --- packages/bezier-react/src/styles/_base.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index b265edfeef..b6f733e28e 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -2,7 +2,6 @@ font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); color: var(--txt-black-darkest); - color-scheme: light; } // TODO: Change data attribute constant to import from bezier-tokens From f2faf6b07f1a9ed4bc62412d0f8150bcd9fac94b Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 30 Nov 2023 00:11:05 +0900 Subject: [PATCH 26/29] feat: back to the root element --- packages/bezier-react/src/index.ts | 12 +++++++- .../src/providers/AlphaAppProvider.tsx | 28 +++++++++++++------ .../src/providers/ThemeProvider.tsx | 7 +++-- packages/bezier-react/src/styles/_base.scss | 1 + 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index f147483761..6ea93fabc0 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -4,7 +4,17 @@ import '~/src/styles/index.scss' export { default as BezierProvider } from '~/src/providers/BezierProvider' export * from '~/src/providers/WindowProvider' export * from '~/src/providers/AlphaAppProvider' -export * from '~/src/providers/ThemeProvider' +export { + useThemeName, + useToken, + ThemeProvider, + LightTheme, + DarkTheme, + InvertedTheme, + type ThemeName, + type ThemeProviderProps, + type FixedThemeProviderProps, +} from '~/src/providers/ThemeProvider' /* Foundation */ export * from '~/src/foundation' diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index 8ee68adf9e..1733bcc58c 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { type Feature, @@ -10,7 +10,7 @@ import { TooltipProvider } from '~/src/components/Tooltip' import { type ThemeName, - ThemeProvider, + TokenProvider, } from './ThemeProvider' import { WindowProvider } from './WindowProvider' @@ -59,16 +59,26 @@ export function AlphaAppProvider({ features = [], window = defaultWindow, }: AlphaAppProviderProps) { + useEffect(function updateThemeDataAttribute() { + const rootElement = window.document.documentElement + // TODO: Change data attribute constant to import from bezier-tokens + rootElement.setAttribute('data-bezier-theme', themeName) + return function cleanup() { + rootElement.removeAttribute('data-bezier-theme') + } + }, [ + window, + themeName, + ]) + return ( - - -
- { children } -
-
-
+ + + { children } + +
) diff --git a/packages/bezier-react/src/providers/ThemeProvider.tsx b/packages/bezier-react/src/providers/ThemeProvider.tsx index 1827a8d0ed..fd302d93cf 100644 --- a/packages/bezier-react/src/providers/ThemeProvider.tsx +++ b/packages/bezier-react/src/providers/ThemeProvider.tsx @@ -39,7 +39,10 @@ interface TokenProviderProps { children: React.ReactNode } -function TokenProvider({ +/** + * @private For internal use only. + */ +export function TokenProvider({ themeName, children, }: TokenProviderProps) { @@ -120,7 +123,7 @@ export const DarkTheme = forwardRef(functi return ( { children } diff --git a/packages/bezier-react/src/styles/_base.scss b/packages/bezier-react/src/styles/_base.scss index b6f733e28e..b265edfeef 100644 --- a/packages/bezier-react/src/styles/_base.scss +++ b/packages/bezier-react/src/styles/_base.scss @@ -2,6 +2,7 @@ font-size: 62.5%; // 10/16 = 0.625. Make REM calculations easier. font-family: var(--font-family-sans-kr); color: var(--txt-black-darkest); + color-scheme: light; } // TODO: Change data attribute constant to import from bezier-tokens From 97762217a708a504f0dd369412d009094b83b612 Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Thu, 30 Nov 2023 15:03:52 +0900 Subject: [PATCH 27/29] feat(theme-provider): apply the changed design token structure --- .../src/providers/ThemeProvider.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/bezier-react/src/providers/ThemeProvider.tsx b/packages/bezier-react/src/providers/ThemeProvider.tsx index fd302d93cf..5a51ad6651 100644 --- a/packages/bezier-react/src/providers/ThemeProvider.tsx +++ b/packages/bezier-react/src/providers/ThemeProvider.tsx @@ -11,26 +11,30 @@ import { createContext } from '~/src/utils/react' type Tokens = typeof tokens type GlobalTokens = Tokens['global'] type SemanticTokens = Omit -type FlattedTokens = GlobalTokens & SemanticTokens[keyof SemanticTokens] + +interface ThemedTokenSet { + global: GlobalTokens + semantic: SemanticTokens[keyof SemanticTokens] +} // TODO: Change theme name constant to import from bezier-tokens export type ThemeName = 'light' | 'dark' interface TokenContextValue { themeName: ThemeName - tokens: FlattedTokens + tokens: ThemedTokenSet } const [TokenContextProvider, useTokenContext] = createContext(null, 'TokenProvider') -const tokenSet: Record = Object.freeze({ +const tokenSet: Record = Object.freeze({ light: { - ...tokens.global, - ...tokens.lightTheme, + global: tokens.global, + semantic: tokens.lightTheme, }, dark: { - ...tokens.global, - ...tokens.darkTheme, + global: tokens.global, + semantic: tokens.darkTheme, }, }) From 257b8d9d307424597a65bd96cc6966b3403715be Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Fri, 1 Dec 2023 13:49:27 +0900 Subject: [PATCH 28/29] refactor(theme-provider): add Provider suffix --- packages/bezier-react/src/index.ts | 6 +++--- .../bezier-react/src/providers/ThemeProvider.tsx | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index 6ea93fabc0..c4efe51ee1 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -8,9 +8,9 @@ export { useThemeName, useToken, ThemeProvider, - LightTheme, - DarkTheme, - InvertedTheme, + LightThemeProvider, + DarkThemeProvider, + InvertedThemeProvider, type ThemeName, type ThemeProviderProps, type FixedThemeProviderProps, diff --git a/packages/bezier-react/src/providers/ThemeProvider.tsx b/packages/bezier-react/src/providers/ThemeProvider.tsx index 5a51ad6651..5a980b1c4d 100644 --- a/packages/bezier-react/src/providers/ThemeProvider.tsx +++ b/packages/bezier-react/src/providers/ThemeProvider.tsx @@ -103,9 +103,9 @@ export const ThemeProvider = forwardRef(functio }) /** - * `LightTheme` is a wrapper component that provides light theme context. + * `LightThemeProvider` is a wrapper component that provides light theme context. */ -export const LightTheme = forwardRef(function LightTheme({ +export const LightThemeProvider = forwardRef(function LightTheme({ children, }, forwardedRef) { return ( @@ -119,9 +119,9 @@ export const LightTheme = forwardRef(funct }) /** - * `DarkTheme` is a wrapper component that provides dark theme context. + * `DarkThemeProvider` is a wrapper component that provides dark theme context. */ -export const DarkTheme = forwardRef(function DarkTheme({ +export const DarkThemeProvider = forwardRef(function DarkTheme({ children, }, forwardedRef) { return ( @@ -135,9 +135,9 @@ export const DarkTheme = forwardRef(functi }) /** - * `InvertedTheme` is a wrapper component that provides inverted theme context. + * `InvertedThemeProvider` is a wrapper component that provides inverted theme context. */ -export const InvertedTheme = forwardRef(function InvertedTheme({ +export const InvertedThemeProvider = forwardRef(function InvertedTheme({ children, }, forwardedRef) { return ( From d89ea83bca4f10c3b30322067ac35cfc654a385d Mon Sep 17 00:00:00 2001 From: Ed Sungik Choi Date: Fri, 1 Dec 2023 13:51:21 +0900 Subject: [PATCH 29/29] refactor(alpha-app-provider): change callback fn name --- packages/bezier-react/src/providers/AlphaAppProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bezier-react/src/providers/AlphaAppProvider.tsx b/packages/bezier-react/src/providers/AlphaAppProvider.tsx index 1733bcc58c..37c687fad5 100644 --- a/packages/bezier-react/src/providers/AlphaAppProvider.tsx +++ b/packages/bezier-react/src/providers/AlphaAppProvider.tsx @@ -59,7 +59,7 @@ export function AlphaAppProvider({ features = [], window = defaultWindow, }: AlphaAppProviderProps) { - useEffect(function updateThemeDataAttribute() { + useEffect(function updateRootThemeDataAttribute() { const rootElement = window.document.documentElement // TODO: Change data attribute constant to import from bezier-tokens rootElement.setAttribute('data-bezier-theme', themeName)