mirror of
				https://github.com/yude-jp/yude.jp
				synced 2025-11-04 05:38:33 +09:00 
			
		
		
		
	Add checkbox to toggle dark-mode
This commit is contained in:
		@@ -2,12 +2,15 @@ import Head from "next/head"
 | 
				
			|||||||
import Link from "next/link"
 | 
					import Link from "next/link"
 | 
				
			||||||
import "tailwindcss/tailwind.css";
 | 
					import "tailwindcss/tailwind.css";
 | 
				
			||||||
import React, { useEffect, useState } from 'react'
 | 
					import React, { useEffect, useState } from 'react'
 | 
				
			||||||
 | 
					import { ThemeProvider } from "./themeContext"
 | 
				
			||||||
 | 
					import Toggle from "./toggle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Layout = (props) => {
 | 
					const Layout = (props) => {
 | 
				
			||||||
  const { title, children } = props
 | 
					  const { title, children } = props
 | 
				
			||||||
  const siteTitle = "yude.jp"
 | 
					  const siteTitle = "yude.jp"
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="page">
 | 
					    <div className="page">
 | 
				
			||||||
 | 
					      <ThemeProvider>
 | 
				
			||||||
      <Head>
 | 
					      <Head>
 | 
				
			||||||
        <title>{title ? `${title} - ${siteTitle}` : siteTitle}</title>
 | 
					        <title>{title ? `${title} - ${siteTitle}` : siteTitle}</title>
 | 
				
			||||||
        <link rel="icon" href="/static/images/favicon.ico" />
 | 
					        <link rel="icon" href="/static/images/favicon.ico" />
 | 
				
			||||||
@@ -33,11 +36,13 @@ const Layout = (props) => {
 | 
				
			|||||||
                <p className="text-sm text-gray-700 font-bold mb-2">
 | 
					                <p className="text-sm text-gray-700 font-bold mb-2">
 | 
				
			||||||
                    This page is licensed under the MIT License. / Powered by Tailwind CSS and Next.js.
 | 
					                    This page is licensed under the MIT License. / Powered by Tailwind CSS and Next.js.
 | 
				
			||||||
                </p>
 | 
					                </p>
 | 
				
			||||||
 | 
					                <Toggle />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </footer>
 | 
					      </footer>
 | 
				
			||||||
      </body>
 | 
					      </body>
 | 
				
			||||||
 | 
					      </ThemeProvider>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ const Navbar = () => {
 | 
				
			|||||||
        <nav className='flex items-center flex-wrap p-3'>
 | 
					        <nav className='flex items-center flex-wrap p-3'>
 | 
				
			||||||
        <Link href='/'>
 | 
					        <Link href='/'>
 | 
				
			||||||
          <a className='inline-flex items-center p-2 mr-4'>
 | 
					          <a className='inline-flex items-center p-2 mr-4'>
 | 
				
			||||||
            <span className='text-xl text-black font-bold tracking-wide'>
 | 
					            <span className='text-xl text-black font-bold tracking-wide dark:text-white'>
 | 
				
			||||||
              yude.jp
 | 
					              yude.jp
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										53
									
								
								pages/components/themeContext.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								pages/components/themeContext.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					import React from 'react'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getInitialTheme = _ => {
 | 
				
			||||||
 | 
					    if (typeof window !== "undefined" && window.localStorage) {
 | 
				
			||||||
 | 
					      const storedPrefs = window.localStorage.getItem("color-theme")
 | 
				
			||||||
 | 
					      if (typeof storedPrefs === "string") {
 | 
				
			||||||
 | 
					        return storedPrefs
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      const userMedia = window.matchMedia("(prefers-color-scheme: dark)")
 | 
				
			||||||
 | 
					      if (userMedia.matches) {
 | 
				
			||||||
 | 
					        return "dark"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    // If you want to use light theme as the default, return "light" instead
 | 
				
			||||||
 | 
					    return "dark"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ThemeContext = React.createContext()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ThemeContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ThemeProvider = ({ initialTheme, children }) => {
 | 
				
			||||||
 | 
					    const [theme, setTheme] = React.useState(getInitialTheme)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    const rawSetTheme = theme => {
 | 
				
			||||||
 | 
					      const root = window.document.documentElement
 | 
				
			||||||
 | 
					      const isDark = theme === "dark"
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      root.classList.remove(isDark ? "light" : "dark")
 | 
				
			||||||
 | 
					      root.classList.add(theme)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      localStorage.setItem("color-theme", theme)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    if (initialTheme) {
 | 
				
			||||||
 | 
					      rawSetTheme(initialTheme)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    React.useEffect(
 | 
				
			||||||
 | 
					      _ => {
 | 
				
			||||||
 | 
					        rawSetTheme(theme)
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      [theme]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <ThemeContext.Provider value={{ theme, setTheme }}>
 | 
				
			||||||
 | 
					        {children}
 | 
				
			||||||
 | 
					      </ThemeContext.Provider>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
							
								
								
									
										23
									
								
								pages/components/toggle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								pages/components/toggle.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					import React from 'react'
 | 
				
			||||||
 | 
					import ThemeContext from './themeContext'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Toggle = () => {
 | 
				
			||||||
 | 
					    const { theme, setTheme } = React.useContext(ThemeContext)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    function isDark() {
 | 
				
			||||||
 | 
					      return theme === "dark"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <label>
 | 
				
			||||||
 | 
					        <input
 | 
				
			||||||
 | 
					          type="checkbox"
 | 
				
			||||||
 | 
					          checked={isDark()}
 | 
				
			||||||
 | 
					          onChange={e => setTheme(e.target.checked ? "dark" : "light")}
 | 
				
			||||||
 | 
					        ></input>
 | 
				
			||||||
 | 
					        ダーク モード
 | 
				
			||||||
 | 
					      </label>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Toggle
 | 
				
			||||||
		Reference in New Issue
	
	Block a user