Make theme wrapper components use as property for less nesting
Luke Karrys committed
Oct 22, 2023 at 11:13 UTC
a355a6af3ce2acc27ce0c4695883e2c42ba99ffd
5 files changed
+135
-140
src/components/header.js
+45
-47
@@ -29,54 +29,52 @@ function Header() {
29
const search = useSearch()
30
31
return (
32
- <DarkTheme>
33
- <Box sx={{top: 0, position: 'sticky', zIndex: 1}}>
34
- <NpmHeaderBar />
35
- <Box
36
- as="header"
37
- sx={{
38
- display: 'flex',
39
- height: HEADER_HEIGHT,
40
- px: [3, null, null, 4],
41
- alignItems: 'center',
42
- justifyContent: 'space-between',
43
- bg: 'canvas.default',
44
- border: '1px solid',
45
- borderLeftWidth: 0,
46
- borderRightWidth: 0,
47
- borderColor: 'border.muted',
48
- }}
49
- >
50
- <Box sx={{display: 'flex', alignItems: 'center'}}>
51
- <Link
52
- to="/"
53
- sx={{
54
- mr: 4,
55
- fontWeight: 'bold',
56
- color: 'fg.default',
57
- display: 'flex',
58
- alignItems: 'center',
59
- }}
60
- >
61
- <NpmLogo size="32" sx={{display: 'flex', mr: 3}} />
62
- {siteMetadata.title}
63
- </Link>
64
- <Box sx={{display: ['none', null, null, 'block'], ml: 4}}>
65
- <Search.Desktop {...search} />
66
- </Box>
32
+ <DarkTheme sx={{top: 0, position: 'sticky', zIndex: 1}}>
33
+ <NpmHeaderBar />
34
+ <Box
35
+ as="header"
36
+ sx={{
37
+ display: 'flex',
38
+ height: HEADER_HEIGHT,
39
+ px: [3, null, null, 4],
40
+ alignItems: 'center',
41
+ justifyContent: 'space-between',
42
+ bg: 'canvas.default',
43
+ border: '1px solid',
44
+ borderLeftWidth: 0,
45
+ borderRightWidth: 0,
46
+ borderColor: 'border.muted',
47
+ }}
48
+ >
49
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
50
+ <Link
51
+ to="/"
52
+ sx={{
53
+ mr: 4,
54
+ fontWeight: 'bold',
55
+ color: 'fg.default',
56
+ display: 'flex',
57
+ alignItems: 'center',
58
+ }}
59
+ >
60
+ <NpmLogo size="32" sx={{display: 'flex', mr: 3}} />
61
+ {siteMetadata.title}
62
+ </Link>
63
+ <Box sx={{display: ['none', null, null, 'block'], ml: 4}}>
64
+ <Search.Desktop {...search} />
65
</Box>
68
- <Box sx={{display: 'flex'}}>
69
- <Box sx={{display: ['none', null, null, 'flex'], alignItems: 'center'}}>
70
- {headerNavItems.map((item, index) => (
71
- <Link key={index} href={item.url} sx={{display: 'block', ml: 4, color: 'fg.default'}}>
72
- {item.title}
73
- </Link>
74
- ))}
75
- </Box>
76
- <Box sx={{display: ['flex', null, null, 'none']}}>
77
- <Search.Mobile {...search} />
78
- <NavDrawer />
79
- </Box>
66
+ </Box>
67
+ <Box sx={{display: 'flex'}}>
68
+ <Box sx={{display: ['none', null, null, 'flex'], alignItems: 'center'}}>
69
+ {headerNavItems.map((item, index) => (
70
+ <Link key={index} href={item.url} sx={{display: 'block', ml: 4, color: 'fg.default'}}>
71
+ {item.title}
72
+ </Link>
73
+ ))}
74
+ </Box>
75
+ <Box sx={{display: ['flex', null, null, 'none']}}>
76
+ <Search.Mobile {...search} />
77
+ <NavDrawer />
78
</Box>
79
</Box>
80
</Box>
src/components/nav-drawer.js
+40
-44
@@ -32,64 +32,60 @@ function NavDrawer() {
32
<Button aria-label="Menu" aria-expanded={isOpen} onClick={setOpen} sx={{ml: 3}}>
33
<ThreeBarsIcon />
34
</Button>
35
- <LightTheme>
36
- <Drawer isOpen={isOpen} onDismiss={setClose}>
35
+ <LightTheme as={Drawer} isOpen={isOpen} onDismiss={setClose}>
36
+ <Box
37
+ sx={{
38
+ display: 'flex',
39
+ flexDirection: 'column',
40
+ height: '100%',
41
+ bg: 'canvas.backdrop',
42
+ overflow: 'auto',
43
+ }}
44
+ style={{WebkitOverflowScrolling: 'touch'}}
45
+ >
46
<Box
47
sx={{
48
display: 'flex',
49
flexDirection: 'column',
41
- height: '100%',
42
- bg: 'canvas.backdrop',
43
- overflow: 'auto',
50
+ flex: '1 0 auto',
51
+ color: 'fg.default',
52
+ bg: 'canvas.default',
53
}}
45
- style={{WebkitOverflowScrolling: 'touch'}}
54
>
47
- <Box
55
+ <DarkTheme
56
sx={{
49
- display: 'flex',
50
- flexDirection: 'column',
51
- flex: '1 0 auto',
57
+ borderWidth: 0,
58
+ borderRadius: 0,
59
+ borderBottomWidth: 1,
60
+ borderColor: 'border.muted',
61
+ borderStyle: 'solid',
62
color: 'fg.default',
63
bg: 'canvas.default',
64
}}
65
>
56
- <DarkTheme>
57
- <Box
58
- sx={{
59
- borderWidth: 0,
60
- borderRadius: 0,
61
- borderBottomWidth: 1,
62
- borderColor: 'border.muted',
63
- borderStyle: 'solid',
64
- color: 'fg.default',
65
- bg: 'canvas.default',
66
- }}
67
- >
68
- <Box
69
- sx={{
70
- py: 3,
71
- pl: 4,
72
- pr: 3,
73
- alignItems: 'center',
74
- justifyContent: 'space-between',
75
- display: 'flex',
76
- }}
77
- >
78
- <Link to="/" sx={{fontSize: 2, color: 'fg.default'}}>
79
- {siteMetadata.title}
80
- </Link>
81
- <Button aria-label="Close" onClick={setClose}>
82
- <XIcon />
83
- </Button>
84
- </Box>
85
- </Box>
86
- </DarkTheme>
87
- <Box sx={{display: 'flex', flexDirection: 'column'}}>
88
- <NavItems />
66
+ <Box
67
+ sx={{
68
+ py: 3,
69
+ pl: 4,
70
+ pr: 3,
71
+ alignItems: 'center',
72
+ justifyContent: 'space-between',
73
+ display: 'flex',
74
+ }}
75
+ >
76
+ <Link to="/" sx={{fontSize: 2, color: 'fg.default'}}>
77
+ {siteMetadata.title}
78
+ </Link>
79
+ <Button aria-label="Close" onClick={setClose}>
80
+ <XIcon />
81
+ </Button>
82
</Box>
83
+ </DarkTheme>
84
+ <Box sx={{display: 'flex', flexDirection: 'column'}}>
85
+ <NavItems />
86
</Box>
87
</Box>
92
- </Drawer>
88
+ </Box>
89
</LightTheme>
90
</>
91
)
src/components/search.js
+29
-33
@@ -23,22 +23,20 @@ export const Desktop = props => {
23
/>
24
<Box sx={{position: 'absolute', left: 0, right: 0, pt: 1}} {...getMenuProps()}>
25
{isOpen ? (
26
- <LightTheme>
27
- <Box
28
- sx={{
29
- overflow: 'auto',
30
- minWidth: 300,
31
- maxHeight: '70vh',
32
- boxShadow: 'shadow.large',
33
- borderColor: 'border.muted',
34
- bg: 'canvas.overlay',
35
- borderRadius: 2,
36
- borderWidth: 1,
37
- borderStyle: 'solid',
38
- }}
39
- >
40
- <SearchResults {...{results, getItemProps, highlightedIndex}} />
41
- </Box>
26
+ <LightTheme
27
+ sx={{
28
+ overflow: 'auto',
29
+ minWidth: 300,
30
+ maxHeight: '70vh',
31
+ boxShadow: 'shadow.large',
32
+ borderColor: 'border.muted',
33
+ bg: 'canvas.overlay',
34
+ borderRadius: 2,
35
+ borderWidth: 1,
36
+ borderStyle: 'solid',
37
+ }}
38
+ >
39
+ <SearchResults {...{results, getItemProps, highlightedIndex}} />
40
</LightTheme>
41
) : null}
42
</Box>
@@ -175,23 +173,21 @@ export const Mobile = props => {
173
</Button>
174
</Box>
175
</Box>
178
- <LightTheme>
179
- <Box
180
- sx={{
181
- display: 'flex',
182
- bg: 'canvas.default',
183
- py: resultsOpen ? 1 : 0,
184
- flexDirection: 'column',
185
- flex: '1 1 auto',
186
- overflow: 'auto',
187
- }}
188
- style={{
189
- WebkitOverflowScrolling: 'touch',
190
- }}
191
- {...getMenuProps()}
192
- >
193
- {resultsOpen ? <SearchResults {...{results, getItemProps, highlightedIndex}} /> : null}
194
- </Box>
176
+ <LightTheme
177
+ sx={{
178
+ display: 'flex',
179
+ bg: 'canvas.default',
180
+ py: resultsOpen ? 1 : 0,
181
+ flexDirection: 'column',
182
+ flex: '1 1 auto',
183
+ overflow: 'auto',
184
+ }}
185
+ style={{
186
+ WebkitOverflowScrolling: 'touch',
187
+ }}
188
+ {...getMenuProps()}
189
+ >
190
+ {resultsOpen ? <SearchResults {...{results, getItemProps, highlightedIndex}} /> : null}
191
</LightTheme>
192
</Box>
193
</Box>
src/layout.js
+9
-11
@@ -16,17 +16,15 @@ const HeroLayout = ({children}) => {
16
17
return (
18
<Box as="main" sx={{width: '100%'}}>
19
- <DarkTheme>
20
- <Box sx={{bg: 'canvas.inset', py: 6}}>
21
- <Container>
22
- <Heading as="h1" sx={{color: 'fg.default', fontSize: 7, m: 0}}>
23
- {title}
24
- </Heading>
25
- <Text as="p" sx={{m: 0, color: 'fg.onEmphasis', fontSize: 4}}>
26
- {description}
27
- </Text>
28
- </Container>
29
- </Box>
19
+ <DarkTheme sx={{bg: 'canvas.inset', py: 6}}>
20
+ <Container>
21
+ <Heading as="h1" sx={{color: 'fg.default', fontSize: 7, m: 0}}>
22
+ {title}
23
+ </Heading>
24
+ <Text as="p" sx={{m: 0, color: 'fg.onEmphasis', fontSize: 4}}>
25
+ {description}
26
+ </Text>
27
+ </Container>
28
</DarkTheme>
29
<SkipNav />
30
<Container>{children}</Container>
src/theme.js
+12
-5
@@ -1,10 +1,10 @@
1
import React from 'react'
2
-import {ThemeProvider as PrimerThemeProvider, theme as primerTheme} from '@primer/react'
2
+import {ThemeProvider as Provider, theme, Box} from '@primer/react'
3
import deepmerge from 'deepmerge'
4
5
export const NPM_RED = '#cb0000'
6
7
-export const theme = deepmerge(primerTheme, {
7
+export const npmTheme = deepmerge(theme, {
8
colors: {
9
logoBg: NPM_RED,
10
},
@@ -37,6 +37,13 @@ export const theme = deepmerge(primerTheme, {
37
},
38
})
39
40
-export const ThemeProvider = props => <PrimerThemeProvider theme={theme} {...props} />
41
-export const LightTheme = props => <ThemeProvider colorMode="light" {...props} />
42
-export const DarkTheme = props => <ThemeProvider colorMode="dark" nightScheme="dark_dimmed" {...props} />
40
+export const ThemeProvider = props => <Provider theme={npmTheme} {...props} />
41
+
42
+export const Theme = ({theme: colorMode, as = Box, ...props}) => (
43
+ <Provider colorMode={colorMode} nightScheme="dark_dimmed">
44
+ {React.createElement(as, props)}
45
+ </Provider>
46
+)
47
+
48
+export const LightTheme = props => <Theme theme="light" {...props} />
49
+export const DarkTheme = props => <Theme theme="dark" {...props} />