Skip to content

Commit 20430bf

Browse files
committed
feat: add themes
1 parent f638490 commit 20430bf

File tree

16 files changed

+1393
-67
lines changed

16 files changed

+1393
-67
lines changed

global.css

Lines changed: 123 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,128 @@
1-
.ch-scrollycoding {
2-
flex-direction: row-reverse;
1+
@import '@unocss/reset/tailwind.css';
2+
@unocss all;
3+
4+
h1 {
5+
@apply text-4xl font-montserrat font-900 pb-5 pt-10;
6+
}
7+
8+
h2 {
9+
@apply text-3xl font-montserrat font-700 pb-5 pt-8;
10+
}
11+
12+
p {
13+
@apply text-base font-merriweather py-3;
314
}
415

5-
.ch-scrollycoding-sticker {
6-
flex: 1 1;
7-
max-height: unset;
8-
height: 95vh;
9-
top: 2.5vh;
16+
a {
17+
@apply cursor-pointer underline underline-dashed;
1018
}
1119

12-
.ch-scrollycoding-sticker .ch-codeblock,
13-
.ch-scrollycoding-sticker .ch-codegroup {
14-
max-height: unset;
15-
height: 95vh;
20+
.ch-scrollycoding {
21+
@apply max-w-screen-xl flex-row-reverse mx-auto my-0 gap-0;
22+
23+
.ch-scrollycoding-content {
24+
@apply flex-1 text-brand-1 p-10 bg-brand-2;
25+
26+
.ch-scrollycoding-step-content {
27+
@apply px-5 max-w-lg min-w-0;
28+
/* @apply w-full */
29+
/* @apply border-none; */
30+
31+
.ch-codeblock,
32+
.ch-codegroup,
33+
.ch-inline-code {
34+
--ch-t-background: var(--brand-1);
35+
--ch-t-tab-activeBackground: var(--brand-1);
36+
--ch-t-tab-inactiveBackground: var(--brand-1);
37+
--ch-t-tab-activeBorder: #ffffff1f;
38+
--ch-t-editorGroupHeader-tabsBackground: var(
39+
--brand-1
40+
);
41+
--ch-t-lighter-inlineBackground: var(--brand-1);
42+
}
43+
}
44+
.ch-scrollycoding-step-content[data-selected] {
45+
@apply border-brand-1;
46+
}
47+
}
48+
49+
.ch-scrollycoding-sticker {
50+
@apply flex-1 max-h-unset h-screen top-0 py-5 px-10 bg-brand-1;
51+
52+
.ch-codegroup {
53+
--ch-t-colorScheme: dark;
54+
--ch-t-foreground: #a6accd;
55+
--ch-t-background: #33333333;
56+
--ch-t-lighter-inlineBackground: #3333332e;
57+
--ch-t-editor-background: #33333333;
58+
--ch-t-editor-foreground: #a6accd;
59+
--ch-t-editor-lineHighlightBackground: #717cb425;
60+
--ch-t-editor-rangeHighlightBackground: #ffffff0b;
61+
--ch-t-editor-infoForeground: #ffffffff;
62+
--ch-t-editor-selectionBackground: #717cb425;
63+
--ch-t-focusBorder: #00000000;
64+
--ch-t-tab-activeBackground: #33333366;
65+
--ch-t-tab-activeForeground: #e4f0fb;
66+
--ch-t-tab-inactiveBackground: #33333333;
67+
--ch-t-tab-inactiveForeground: #767c9d;
68+
--ch-t-tab-border: #00000000;
69+
--ch-t-tab-activeBorder: #33333366;
70+
--ch-t-editorGroup-border: #00000030;
71+
--ch-t-editorGroupHeader-tabsBackground: #33333333;
72+
--ch-t-editorLineNumber-foreground: #767c9d50;
73+
--ch-t-input-background: #ffffff05;
74+
--ch-t-input-foreground: #e4f0fb;
75+
--ch-t-input-border: #ffffff10;
76+
--ch-t-icon-foreground: #a6accd;
77+
--ch-t-sideBar-background: #1b1e28;
78+
--ch-t-sideBar-foreground: #767c9d;
79+
--ch-t-sideBar-border: #1b1e28;
80+
--ch-t-list-activeSelectionBackground: #30334080;
81+
--ch-t-list-activeSelectionForeground: #e4f0fb;
82+
--ch-t-list-hoverBackground: #30334080;
83+
--ch-t-list-hoverForeground: #e4f0fb;
84+
@apply max-h-unset h-screen;
85+
}
86+
87+
.ch-codeblock {
88+
--ch-t-background: var(--brand-1);
89+
--ch-t-tab-activeBackground: var(--brand-1);
90+
--ch-t-tab-inactiveBackground: var(--brand-1);
91+
--ch-t-tab-activeBorder: #ffffff1f;
92+
--ch-t-editorGroupHeader-tabsBackground: var(
93+
--brand-1
94+
);
95+
--ch-t-lighter-inlineBackground: var(--brand-1);
96+
}
97+
98+
.ch-expand-dialog-content {
99+
@apply border-4;
100+
border-color: var(--brand-2);
101+
102+
.ch-code-browser-sidebar {
103+
@apply bg-brand-2;
104+
}
105+
106+
.ch-code-browser-content {
107+
@apply bg-brand-1 text-sm;
108+
}
109+
}
110+
}
111+
}
112+
113+
.ch-scrollycoding-static {
114+
@apply bg-brand-2 text-brand-1 p-5;
115+
116+
.ch-codeblock,
117+
.ch-codegroup,
118+
.ch-inline-code {
119+
--ch-t-background: var(--brand-1);
120+
--ch-t-tab-activeBackground: var(--brand-1);
121+
--ch-t-tab-inactiveBackground: var(--brand-1);
122+
--ch-t-tab-activeBorder: #ffffff1f;
123+
--ch-t-editorGroupHeader-tabsBackground: var(--brand-1);
124+
--ch-t-lighter-inlineBackground: var(--brand-1);
125+
}
16126
}
17127

18128
img.tutorial {
@@ -21,7 +131,6 @@ img.tutorial {
21131

22132
table {
23133
border-collapse: collapse;
24-
border-color: inherit;
25134
border-spacing: 0;
26135
display: block;
27136
margin-bottom: 2.5rem;
@@ -35,10 +144,8 @@ table {
35144

36145
table th {
37146
background-color: transparent;
38-
--border-color: rgb(200 200 200);
39147
--border-width: 2px;
40-
border-bottom: var(--border-width) solid
41-
var(--border-color);
148+
border-bottom: var(--border-width) solid var(--brand-1);
42149
font-weight: 600;
43150
padding: 0 1rem 0.25rem 0;
44151
position: sticky;
@@ -47,10 +154,8 @@ table th {
47154

48155
table td {
49156
background-color: transparent;
50-
--border-color: rgb(227 227 227);
51157
--border-width: 1px;
52-
border-bottom: var(--border-width) solid
53-
var(--border-color);
158+
border-bottom: var(--border-width) solid var(--brand-1);
54159
padding: 0.5rem 1rem 0.5rem 0;
55160
white-space: nowrap;
56161
}

next.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const { remarkCodeHike } = require('@code-hike/mdx')
33
const withMDX = require('@next/mdx')({
44
extension: /\.mdx?$/,
55
options: {
6-
remarkPlugins: [[remarkCodeHike, { theme: 'nord' }]],
6+
remarkPlugins: [
7+
[remarkCodeHike, { theme: 'poimandres' }],
8+
],
79
},
810
})
911

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"sort-by": "^1.2.0"
2929
},
3030
"devDependencies": {
31+
"@unocss/postcss": "^0.58.8",
32+
"@unocss/transformer-directives": "^0.58.8",
3133
"@vitejs/plugin-react": "^4.2.1",
34+
"unocss": "^0.58.8",
3235
"vite": "^5.2.2"
3336
}
3437
}

pages/_app.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
11
import '@code-hike/mdx/dist/index.css'
2+
import App from 'next/app'
23
import '../global.css'
4+
import Dropdown from './components/Dropdown'
5+
import { THEME } from './common/constants'
36

4-
function App({ Component, pageProps }) {
5-
return <Component {...pageProps} />
7+
export default function MyApp({
8+
Component,
9+
pageProps,
10+
defaultTheme,
11+
}) {
12+
return (
13+
<div
14+
id="theme-root"
15+
style={{
16+
'--brand-1': THEME[defaultTheme].brand1,
17+
'--brand-2': THEME[defaultTheme].brand2,
18+
'--img-hue-rotate': THEME[defaultTheme].hueRotate,
19+
}}
20+
>
21+
<div className="min-h-screen md:bg-gradient-to-r from-brand-1 from-50% to-brand-2 to-50%">
22+
<Dropdown className="fixed top-5 right-5 md:right-1/2 md:translate-x-1/2" />
23+
<Component {...pageProps} />
24+
</div>
25+
</div>
26+
)
627
}
728

8-
export default App
29+
MyApp.getInitialProps = async (context) => {
30+
const ctx = await App.getInitialProps(context)
31+
// Fix theme switching after first loading
32+
// https://nextjs.org/docs/pages/building-your-application/routing/custom-app#getinitialprops-with-app
33+
const theme = context.ctx.req.cookies['--yulei-theme']
34+
return { ...ctx, defaultTheme: theme || 'theme0' }
35+
}

pages/common/constants.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// https://2colors.colorion.co/
2+
export const THEME = {
3+
theme0: {
4+
brand1: '#000000',
5+
brand2: '#FFFFFF',
6+
hueRotate: '0deg',
7+
},
8+
theme1: {
9+
brand1: '#02343F',
10+
brand2: '#F0EDCC',
11+
hueRotate: '90deg',
12+
},
13+
theme2: {
14+
brand1: '#331B3F',
15+
brand2: '#ACC7B4',
16+
hueRotate: '180deg',
17+
},
18+
theme3: {
19+
brand1: '#0A174E',
20+
brand2: '#F5D042',
21+
hueRotate: '135deg',
22+
},
23+
theme4: {
24+
brand1: '#07553B',
25+
brand2: '#CED46A',
26+
hueRotate: '45deg',
27+
},
28+
theme5: {
29+
brand1: '#50586C',
30+
brand2: '#DCE2F0',
31+
hueRotate: '110deg',
32+
},
33+
theme6: {
34+
brand1: '#815854',
35+
brand2: '#F9EBDE',
36+
hueRotate: '270deg',
37+
},
38+
theme7: {
39+
brand1: '#1E4174',
40+
brand2: '#DDA94B',
41+
hueRotate: '112deg',
42+
},
43+
theme8: {
44+
brand1: '#6a7ba2',
45+
brand2: '#ffdfde',
46+
hueRotate: '112deg',
47+
},
48+
theme9: {
49+
brand1: '#00203F',
50+
brand2: '#ADEFD1',
51+
hueRotate: '90deg',
52+
},
53+
}

pages/common/utils.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { THEME } from './constants'
2+
3+
export function setTheme(theme) {
4+
document
5+
.querySelector('#theme-root')
6+
.style.setProperty('--brand-1', THEME[theme].brand1)
7+
document
8+
.querySelector('#theme-root')
9+
.style.setProperty('--brand-2', THEME[theme].brand2)
10+
document
11+
.querySelector('#theme-root')
12+
.style.setProperty(
13+
'--img-hue-rotate',
14+
THEME[theme].hueRotate
15+
)
16+
}

pages/components/BicolorCircle.jsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function BicolorCircle({ from, to, className = "", ...props }) {
2+
return (
3+
<div
4+
className={`
5+
h-6 w-6 rounded-full cursor-pointer mb-1
6+
bg-gradient-to-b from-${from} from-50% to-${to} to-50%
7+
border-1 border-white hover:brightness-110
8+
transition-transform-300
9+
md:border-none md:bg-gradient-to-r
10+
${className}
11+
`}
12+
{...props}
13+
/>
14+
);
15+
}
16+
17+
export default BicolorCircle;

pages/components/Dropdown.jsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use client'
2+
3+
import { useState } from 'react'
4+
import BicolorCircle from './BicolorCircle'
5+
import { THEME } from '../common/constants'
6+
import { setTheme } from '../common/utils'
7+
8+
function Dropdown({ className = '' }) {
9+
const [dropdownVisible, setDropdownVisible] =
10+
useState(false)
11+
12+
return (
13+
<div
14+
className={`flex flex-col z-1 ${className}`}
15+
tabIndex={0}
16+
onBlur={() => setDropdownVisible(false)}
17+
>
18+
<BicolorCircle
19+
from="brand-2"
20+
to="brand-1"
21+
className={dropdownVisible ? 'rotate-180' : ''}
22+
onClick={() => setDropdownVisible((prev) => !prev)}
23+
/>
24+
{dropdownVisible && (
25+
<ul>
26+
<DropdownItem value="theme0" />
27+
<DropdownItem value="theme1" />
28+
<DropdownItem value="theme2" />
29+
<DropdownItem value="theme3" />
30+
<DropdownItem value="theme4" />
31+
<DropdownItem value="theme5" />
32+
<DropdownItem value="theme6" />
33+
<DropdownItem value="theme7" />
34+
<DropdownItem value="theme8" />
35+
<DropdownItem value="theme9" />
36+
</ul>
37+
)}
38+
</div>
39+
)
40+
}
41+
42+
function DropdownItem({ value }) {
43+
const handleThemeChange = (newTheme) => {
44+
setTheme(newTheme)
45+
if (process.env === 'production') {
46+
document.cookie = `--yulei-theme=${newTheme}; domain=yulei.monster;`
47+
} else {
48+
document.cookie = `--yulei-theme=${newTheme};`
49+
}
50+
}
51+
52+
return (
53+
<BicolorCircle
54+
from={THEME[value].brand2}
55+
to={THEME[value].brand1}
56+
onClick={() => handleThemeChange(value)}
57+
/>
58+
)
59+
}
60+
61+
export default Dropdown

pages/components/Intro.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function Intro({ className = "" }) {
2+
return (
3+
<div className={`text-center md:text-left ${className}`}>
4+
<h1 className="text-4xl pb-3 font-montserrat font-900">I'm Yulei Chen</h1>
5+
<p className="text-xl">I know nothing about JavaScript.</p>
6+
</div>
7+
);
8+
}
9+
10+
export default Intro;

0 commit comments

Comments
 (0)