├── .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 |
37 | My Personal Site
38 |
39 | {darkTheme !== undefined && (
40 |
50 | )}
51 |
52 |
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 |
Connect with me
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 |
--------------------------------------------------------------------------------