File tree Expand file tree Collapse file tree 3 files changed +86
-16
lines changed
Expand file tree Collapse file tree 3 files changed +86
-16
lines changed Original file line number Diff line number Diff line change @@ -3,6 +3,8 @@ import type { Metadata } from 'next';
33import Head from 'next/head' ;
44import { Geist , Geist_Mono } from 'next/font/google' ;
55
6+ import { ThemeProvider } from '@/components/ThemeProvider' ;
7+
68import './globals.css' ;
79
810const geistSans = Geist ( {
@@ -29,7 +31,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
2931 < body
3032 className = { `${ geistSans . variable } ${ geistMono . variable } antialiased` }
3133 >
32- { children }
34+ < ThemeProvider > { children } </ ThemeProvider >
3335 </ body >
3436 </ html >
3537 ) ;
Original file line number Diff line number Diff line change 22
33import { Suspense } from 'react' ;
44import dynamic from 'next/dynamic' ;
5- import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs' ;
5+ import {
6+ docco ,
7+ stackoverflowDark ,
8+ } from 'react-syntax-highlighter/dist/esm/styles/hljs' ;
9+ import { useTheme } from '@/components/ThemeProvider' ;
610
711const SyntaxHighlighter = dynamic ( ( ) => import ( 'react-syntax-highlighter' ) ) ;
812
@@ -11,18 +15,25 @@ type Props = {
1115 children : string ;
1216} ;
1317
14- export const CodeSnippet = ( { type, children } : Props ) => (
15- < div className = "my-2" >
16- < Suspense
17- fallback = {
18- < div className = "monospaced whitespace-pre-wrap bg-secondary px-2 py-[0.5em] border-l-4" >
18+ export const CodeSnippet = ( { type, children } : Props ) => {
19+ const theme = useTheme ( ) ;
20+
21+ return (
22+ < div className = "my-2" >
23+ < Suspense
24+ fallback = {
25+ < div className = "monospaced whitespace-pre-wrap bg-secondary px-2 py-[0.5em] border-l-4" >
26+ { children }
27+ </ div >
28+ }
29+ >
30+ < SyntaxHighlighter
31+ language = { type }
32+ style = { theme === 'light' ? docco : stackoverflowDark }
33+ >
1934 { children }
20- </ div >
21- }
22- >
23- < SyntaxHighlighter language = { type } style = { docco } >
24- { children }
25- </ SyntaxHighlighter >
26- </ Suspense >
27- </ div >
28- ) ;
35+ </ SyntaxHighlighter >
36+ </ Suspense >
37+ </ div >
38+ ) ;
39+ } ;
Original file line number Diff line number Diff line change 1+ 'use client' ;
2+
3+ import {
4+ createContext ,
5+ ReactNode ,
6+ useContext ,
7+ useLayoutEffect ,
8+ useState ,
9+ } from 'react' ;
10+
11+ export type Theme = 'light' | 'dark' ;
12+
13+ type ThemeProviderState = {
14+ theme : Theme ;
15+ } ;
16+
17+ const ThemeContext = createContext < ThemeProviderState > ( {
18+ theme : 'light' ,
19+ } ) ;
20+
21+ export const ThemeProvider = ( { children } : { children ?: ReactNode } ) => {
22+ const [ themeState , setThemeState ] = useState < ThemeProviderState > ( {
23+ theme : 'light' ,
24+ } ) ;
25+
26+ useLayoutEffect ( ( ) => {
27+ const match = window . matchMedia ( '(prefers-color-scheme:dark)' ) ;
28+
29+ function onChange ( event : { matches : boolean } ) {
30+ setThemeState ( ( themeState ) => {
31+ const targetTheme = event . matches ? 'dark' : 'light' ;
32+
33+ if ( themeState . theme === targetTheme ) {
34+ return themeState ;
35+ }
36+
37+ return {
38+ ...themeState ,
39+ theme : targetTheme ,
40+ } ;
41+ } ) ;
42+ }
43+
44+ onChange ( match ) ;
45+
46+ match . addEventListener ( 'change' , onChange ) ;
47+ return ( ) => {
48+ match . removeEventListener ( 'change' , onChange ) ;
49+ } ;
50+ } , [ ] ) ;
51+
52+ return < ThemeContext value = { themeState } > { children } </ ThemeContext > ;
53+ } ;
54+
55+ export function useTheme ( ) : Theme {
56+ return useContext ( ThemeContext ) . theme ;
57+ }
You can’t perform that action at this time.
0 commit comments