├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.js ├── _document.js ├── api │ └── hello.js └── index.js ├── public ├── favicon.ico └── vercel.svg └── styles └── globals.css /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | # nextjs-darkmode 36 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reactStrictMode: true, 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-darkmode", 3 | "private": true, 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start", 8 | "lint": "next lint" 9 | }, 10 | "dependencies": { 11 | "next": "12.0.3", 12 | "react": "17.0.2", 13 | "react-dom": "17.0.2" 14 | }, 15 | "devDependencies": { 16 | "eslint": "7.32.0", 17 | "eslint-config-next": "12.0.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css'; 2 | 3 | export default function MyApp({ Component, pageProps }) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 2 | 3 | class MyDocument extends Document { 4 | render() { 5 | return ( 6 | 7 | 8 | 9 | 14 |
15 | 16 | 17 | 18 | ); 19 | } 20 | } 21 | 22 | // This function needs to be a String 23 | const themeInitializerScript = `(function() { 24 | ${setInitialColorMode.toString()} 25 | setInitialColorMode(); 26 | })() 27 | `; 28 | 29 | function setInitialColorMode() { 30 | // Check initial color preference 31 | function getInitialColorMode() { 32 | const persistedPreferenceMode = window.localStorage.getItem('theme'); 33 | const hasPersistedPreference = typeof persistedPreferenceMode === 'string'; 34 | 35 | if (hasPersistedPreference) { 36 | return persistedPreferenceMode; 37 | } 38 | 39 | // Check the current preference 40 | const preference = window.matchMedia('(prefers-color-scheme: dark)'); 41 | const hasMediaQueryPreference = typeof preference.matches === 'boolean'; 42 | 43 | if (hasMediaQueryPreference) { 44 | return preference.matches ? 'dark' : 'light'; 45 | } 46 | 47 | return 'light'; 48 | } 49 | 50 | const currentColorMode = getInitialColorMode(); 51 | const element = document.documentElement; 52 | element.style.setProperty('--initial-color-mode', currentColorMode); 53 | 54 | // If darkmode apply darkmode 55 | if (currentColorMode === 'dark') 56 | document.documentElement.setAttribute('data-theme', 'dark'); 57 | } 58 | 59 | export default MyDocument; 60 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default function handler(req, res) { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | const HomePage = () => { 4 | const [darkTheme, setDarkTheme] = useState(undefined); 5 | 6 | const handleToggle = (event) => { 7 | setDarkTheme(event.target.checked); 8 | }; 9 | 10 | useEffect(() => { 11 | if (darkTheme !== undefined) { 12 | if (darkTheme) { 13 | // Set value of darkmode to dark 14 | document.documentElement.setAttribute('data-theme', 'dark'); 15 | window.localStorage.setItem('theme', 'dark'); 16 | } else { 17 | // Set value of darkmode to light 18 | document.documentElement.removeAttribute('data-theme'); 19 | window.localStorage.setItem('theme', 'light'); 20 | } 21 | } 22 | }, [darkTheme]); 23 | 24 | useEffect(() => { 25 | const root = window.document.documentElement; 26 | const initialColorValue = root.style.getPropertyValue( 27 | '--initial-color-mode' 28 | ); 29 | // Set initial darkmode to light 30 | setDarkTheme(initialColorValue === 'dark'); 31 | }, []); 32 | 33 | return ( 34 | <> 35 |
36 | 53 |
54 |
55 |

👋 Hey I’m Ishan

56 |

57 | I am a designer, frontend developer writer and content creator. 58 |

59 |

60 | You can find me in 61 | 62 | 63 | Twitter 64 | 65 | 66 | where I talk about design and development topics. I am glad you 67 | are hear. I would love to speak and talk to new happy faces and 68 | share my work process and tech talks with you. 69 |

70 | 71 |
72 |
73 |
74 | 75 | ); 76 | }; 77 | 78 | export default HomePage; 79 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isNan909/nextjs-darkmode/fc222277a1925db153a7910c6930896ef902c2e2/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,400;0,500;1,300&display=swap'); 2 | 3 | /* declaring the css variables colors */ 4 | :root { 5 | --color-primary-accent: #2614c7; 6 | --color-primary: #000; 7 | --color-button: #3d486c; 8 | --color-paragraph: #797979; 9 | --color-button-text: rgb(255, 255, 255); 10 | --color-background: #fff; 11 | --color-anchor: #000aff; 12 | } 13 | 14 | [data-theme='dark'] { 15 | --color-primary-accent: #00ff4c; 16 | --color-primary: #fff; 17 | --color-button: #00ff4c; 18 | --color-paragraph: #8a8a8a; 19 | --color-button-text: rgb(0, 0, 0); 20 | --color-background: #22212b; 21 | --color-anchor: #00ff4c; 22 | } 23 | 24 | body { 25 | background-color: var(--color-background); 26 | color: var(--color-primary); 27 | font-size: 16px; 28 | font-family: 'Poppins', sans-serif; 29 | } 30 | 31 | h1, 32 | h3, 33 | p { 34 | margin: 0; 35 | padding: 0; 36 | } 37 | 38 | /* swtich taken from W3 schools */ 39 | 40 | .switch { 41 | position: relative; 42 | display: inline-block; 43 | width: 60px; 44 | height: 34px; 45 | } 46 | 47 | .switch input { 48 | opacity: 0; 49 | width: 0; 50 | height: 0; 51 | } 52 | 53 | .slider { 54 | position: absolute; 55 | cursor: pointer; 56 | top: 0; 57 | left: 0; 58 | right: 0; 59 | bottom: 0; 60 | background-color: #ccc; 61 | -webkit-transition: 0.4s; 62 | transition: 0.4s; 63 | } 64 | 65 | .slider:before { 66 | position: absolute; 67 | content: ''; 68 | height: 26px; 69 | width: 26px; 70 | left: 4px; 71 | bottom: 4px; 72 | background-color: white; 73 | -webkit-transition: 0.4s; 74 | transition: 0.4s; 75 | } 76 | 77 | input:checked + .slider { 78 | background-color: #33f321; 79 | } 80 | 81 | input:focus + .slider { 82 | box-shadow: 0 0 1px #33f321; 83 | } 84 | 85 | input:checked + .slider:before { 86 | -webkit-transform: translateX(26px); 87 | -ms-transform: translateX(26px); 88 | transform: translateX(26px); 89 | } 90 | 91 | .slider { 92 | border-radius: 34px; 93 | } 94 | 95 | .slider:before { 96 | border-radius: 50%; 97 | } 98 | 99 | /* adding some custom CSS */ 100 | 101 | nav { 102 | display: flex; 103 | justify-content: space-between; 104 | } 105 | nav .mybrand { 106 | font-style: normal; 107 | font-weight: bold; 108 | font-size: 18px; 109 | line-height: 21px; 110 | color: var(--color-primary); 111 | } 112 | .container { 113 | max-width: 800px; 114 | margin: 0 auto; 115 | margin-top: 2.5rem; 116 | } 117 | section .heroSection { 118 | display: flex; 119 | flex-direction: column; 120 | align-items: flex-start; 121 | justify-content: center; 122 | height: 100vh; 123 | } 124 | 125 | .heroSection > h1 { 126 | font-size: 55px; 127 | } 128 | 129 | .heroSection > h3 { 130 | padding: 30px 0px 15px 0px; 131 | font-weight: bold; 132 | font-size: 25px; 133 | } 134 | 135 | .heroSection > p { 136 | font-size: 18px; 137 | color: var(--color-paragraph); 138 | } 139 | 140 | .heroSection button { 141 | cursor: pointer; 142 | margin-top: 30px; 143 | background: var(--color-button); 144 | color: var(--color-button-text); 145 | border-radius: 5px; 146 | padding: 15px 30px; 147 | font-weight: bold; 148 | font-size: 17px; 149 | } 150 | 151 | a { 152 | color: var(--color-anchor); 153 | } 154 | --------------------------------------------------------------------------------