Content-Length: 703624 | pFad | http://github.com/pixelbrackets/github-docs/commit/a8d45acea9bc69fe4cbbdf67e2bde3924cbd1bde

27 refactor getThemeProps to be available in JS (#27439) · pixelbrackets/github-docs@a8d45ac · GitHub
Skip to content

Commit a8d45ac

Browse files
authored
refactor getThemeProps to be available in JS (github#27439)
* refactor getThemeProps to be available in JS * wip * mike's idea * delete no longer used file
1 parent 2cebc49 commit a8d45ac

File tree

4 files changed

+110
-27
lines changed

4 files changed

+110
-27
lines changed
Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
type ThemeT = { name: string; color_mode: string }
2-
3-
const defaultCSSThemeProps = {
1+
// export const defaultCSSThemeProps = {
2+
export const defaultCSSTheme = {
43
colorMode: 'auto', // light, dark, auto
54
nightTheme: 'dark',
65
dayTheme: 'light',
76
}
87

9-
export const defaultComponentThemeProps = {
8+
// export const defaultComponentThemeProps = {
9+
export const defaultComponentTheme = {
1010
colorMode: 'auto', // day, night, auto
1111
nightTheme: 'dark',
1212
dayTheme: 'light',
1313
}
1414

15-
const cssColorModeToComponentColorMode: Record<string, string> = {
15+
const cssColorModeToComponentColorMode = {
1616
auto: 'auto',
1717
light: 'day',
1818
dark: 'night',
@@ -24,7 +24,7 @@ const supportedThemes = ['light', 'dark', 'dark_dimmed']
2424
* Our version of primer/css is out of date, so we can only support known themes.
2525
* For the least jarring experience possible, we fallback to the color_mode (light / dark) if provided by the theme, otherwise our own defaults
2626
*/
27-
function getSupportedTheme(theme: ThemeT | undefined, fallbackTheme: string) {
27+
function getSupportedTheme(theme, fallbackTheme) {
2828
if (!theme) {
2929
return fallbackTheme
3030
}
@@ -33,35 +33,36 @@ function getSupportedTheme(theme: ThemeT | undefined, fallbackTheme: string) {
3333
}
3434

3535
/*
36-
* Returns theme props for consumption by either primer/css or primer/components
36+
* Returns theme for consumption by either primer/css or primer/components
3737
* based on the cookie and/or fallback values
3838
*/
39-
export function getThemeProps(req: any, mode?: 'css') {
40-
let cookieValue: {
41-
color_mode?: 'auto' | 'light' | 'dark'
42-
dark_theme?: ThemeT
43-
light_theme?: ThemeT
44-
} = {}
45-
const defaultThemeProps = mode === 'css' ? defaultCSSThemeProps : defaultComponentThemeProps
39+
export function getTheme(req, cssMode = false) {
40+
const cookieValue = {}
41+
42+
const defaultTheme = cssMode ? defaultCSSTheme : defaultComponentTheme
4643

4744
if (req.cookies?.color_mode) {
4845
try {
49-
cookieValue = JSON.parse(decodeURIComponent(req.cookies.color_mode))
50-
} catch {
51-
// do nothing
46+
const parsed = JSON.parse(decodeURIComponent(req.cookies.color_mode))
47+
cookieValue.color_mode = parsed.color_mode
48+
cookieValue.dark_theme = parsed.dark_theme
49+
cookieValue.light_theme = parsed.light_theme
50+
} catch (err) {
51+
if (process.env.NODE_ENV !== 'test') {
52+
console.warn("Unable to parse 'color_mode' cookie", err)
53+
}
5254
}
5355
}
5456

5557
// The cookie value is a primer/css color_mode. sometimes we need to convert that to a primer/components compatible version
5658
const colorMode =
57-
(mode === 'css'
59+
(cssMode
5860
? cookieValue.color_mode
59-
: cssColorModeToComponentColorMode[cookieValue.color_mode || '']) ||
60-
defaultThemeProps.colorMode
61+
: cssColorModeToComponentColorMode[cookieValue.color_mode || '']) || defaultTheme.colorMode
6162

6263
return {
6364
colorMode,
64-
nightTheme: getSupportedTheme(cookieValue.dark_theme, defaultThemeProps.nightTheme),
65-
dayTheme: getSupportedTheme(cookieValue.light_theme, defaultThemeProps.dayTheme),
65+
nightTheme: getSupportedTheme(cookieValue.dark_theme, defaultTheme.nightTheme),
66+
dayTheme: getSupportedTheme(cookieValue.light_theme, defaultTheme.dayTheme),
6667
}
6768
}

pages/_app.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ import type { AppProps, AppContext } from 'next/app'
44
import Head from 'next/head'
55
import { ThemeProvider, ThemeProviderProps } from '@primer/react'
66
import { SSRProvider } from '@react-aria/ssr'
7-
import { defaultComponentThemeProps, getThemeProps } from 'components/lib/getThemeProps'
87

98
import '../stylesheets/index.scss'
109

1110
import events from 'components/lib/events'
1211
import experiment from 'components/lib/experiment'
1312
import { LanguagesContext, LanguagesContextT } from 'components/context/LanguagesContext'
13+
import { defaultComponentTheme } from 'lib/get-theme.js'
1414

1515
type MyAppProps = AppProps & {
1616
csrfToken: string
17-
themeProps: typeof defaultComponentThemeProps & Pick<ThemeProviderProps, 'colorMode'>
17+
themeProps: typeof defaultComponentTheme & Pick<ThemeProviderProps, 'colorMode'>
1818
languagesContext: LanguagesContextT
1919
}
2020
const MyApp = ({ Component, pageProps, csrfToken, themeProps, languagesContext }: MyAppProps) => {
@@ -72,9 +72,11 @@ MyApp.getInitialProps = async (appContext: AppContext) => {
7272
const appProps = await App.getInitialProps(appContext)
7373
const req: any = ctx.req
7474

75+
const { getTheme } = await import('lib/get-theme.js')
76+
7577
return {
7678
...appProps,
77-
themeProps: getThemeProps(req),
79+
themeProps: getTheme(req),
7880
csrfToken: req?.csrfToken?.() || '',
7981
languagesContext: { languages: req.context.languages },
8082
}

pages/_document.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Document, { DocumentContext, Html, Head, Main, NextScript } from 'next/do
22

33
import { ServerStyleSheet } from 'styled-components'
44

5-
import { getThemeProps } from 'components/lib/getThemeProps'
5+
import { getTheme } from 'lib/get-theme.js'
66

77
export default class MyDocument extends Document {
88
static async getInitialProps(ctx: DocumentContext) {
@@ -18,7 +18,7 @@ export default class MyDocument extends Document {
1818
const initialProps = await Document.getInitialProps(ctx)
1919
return {
2020
...initialProps,
21-
cssThemeProps: getThemeProps(ctx.req, 'css'),
21+
cssThemeProps: getTheme(ctx.req, true),
2222
styles: (
2323
<>
2424
{initialProps.styles}

tests/unit/get-theme.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { describe, expect, test } from '@jest/globals'
2+
3+
import { getTheme, defaultCSSTheme, defaultComponentTheme } from '../../lib/get-theme.js'
4+
5+
function serializeCookieValue(obj) {
6+
return encodeURIComponent(JSON.stringify(obj))
7+
}
8+
9+
describe('getTheme basics', () => {
10+
test('always return an object with certain keys', () => {
11+
const req = {} // doesn't even have a `.cookies`.
12+
const theme = getTheme(req)
13+
expect(theme.colorMode).toBe(defaultComponentTheme.colorMode)
14+
expect(theme.nightTheme).toBe(defaultComponentTheme.nightTheme)
15+
expect(theme.dayTheme).toBe(defaultComponentTheme.dayTheme)
16+
const cssTheme = getTheme(req, true)
17+
expect(cssTheme.colorMode).toBe(defaultCSSTheme.colorMode)
18+
expect(cssTheme.nightTheme).toBe(defaultCSSTheme.nightTheme)
19+
expect(cssTheme.dayTheme).toBe(defaultCSSTheme.dayTheme)
20+
})
21+
22+
test('respect the color_mode cookie value', () => {
23+
const req = {
24+
cookies: {
25+
color_mode: serializeCookieValue({
26+
color_mode: 'dark',
27+
light_theme: { name: 'light_colorblind', color_mode: 'light' },
28+
dark_theme: { name: 'dark_tritanopia', color_mode: 'dark' },
29+
}),
30+
},
31+
}
32+
const theme = getTheme(req)
33+
expect(theme.colorMode).toBe('night')
34+
expect(theme.nightTheme).toBe(defaultComponentTheme.nightTheme)
35+
expect(theme.dayTheme).toBe(defaultComponentTheme.dayTheme)
36+
37+
const cssTheme = getTheme(req, true)
38+
expect(cssTheme.colorMode).toBe('dark')
39+
expect(cssTheme.nightTheme).toBe(defaultCSSTheme.nightTheme)
40+
expect(cssTheme.dayTheme).toBe(defaultCSSTheme.dayTheme)
41+
})
42+
43+
test('respect the color_mode cookie value', () => {
44+
const req = {
45+
cookies: {
46+
color_mode: serializeCookieValue({
47+
color_mode: 'dark',
48+
light_theme: { name: 'light_colorblind', color_mode: 'light' },
49+
dark_theme: { name: 'dark_tritanopia', color_mode: 'dark' },
50+
}),
51+
},
52+
}
53+
const theme = getTheme(req)
54+
expect(theme.colorMode).toBe('night')
55+
expect(theme.nightTheme).toBe(defaultComponentTheme.nightTheme)
56+
expect(theme.dayTheme).toBe(defaultComponentTheme.dayTheme)
57+
58+
const cssTheme = getTheme(req, true)
59+
expect(cssTheme.colorMode).toBe('dark')
60+
expect(cssTheme.nightTheme).toBe(defaultCSSTheme.nightTheme)
61+
expect(cssTheme.dayTheme).toBe(defaultCSSTheme.dayTheme)
62+
})
63+
64+
test('ignore "junk" cookie values', () => {
65+
const req = {
66+
cookies: {
67+
color_mode: '[This is not valid JSON}',
68+
},
69+
}
70+
const theme = getTheme(req)
71+
expect(theme.colorMode).toBe('auto')
72+
expect(theme.nightTheme).toBe(defaultComponentTheme.nightTheme)
73+
expect(theme.dayTheme).toBe(defaultComponentTheme.dayTheme)
74+
75+
const cssTheme = getTheme(req, true)
76+
expect(cssTheme.colorMode).toBe('auto')
77+
expect(cssTheme.nightTheme).toBe(defaultCSSTheme.nightTheme)
78+
expect(cssTheme.dayTheme).toBe(defaultCSSTheme.dayTheme)
79+
})
80+
})

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/pixelbrackets/github-docs/commit/a8d45acea9bc69fe4cbbdf67e2bde3924cbd1bde

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy