mirror of
https://github.com/kremalicious/portfolio.git
synced 2025-01-03 10:25:00 +01:00
favicon & web manifest changes
This commit is contained in:
parent
23b0f8dcc7
commit
88e5ef9502
@ -149,10 +149,12 @@ SLUG-03.png
|
|||||||
|
|
||||||
### 🌄 Favicon generation
|
### 🌄 Favicon generation
|
||||||
|
|
||||||
This generates all required favcion sizes from:
|
This generates all required favicon sizes from:
|
||||||
|
|
||||||
- `src/images/favicon-512.png`
|
- `src/images/favicon-512.png`
|
||||||
- `src/images/favicon.svg`
|
- `src/images/favicon.svg` (handcrafted, adaptive based on OS theme)
|
||||||
|
|
||||||
|
Also creates a web manifest.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run favicon
|
npm run favicon
|
||||||
|
77
package-lock.json
generated
77
package-lock.json
generated
@ -27,13 +27,12 @@
|
|||||||
"@svgr/webpack": "^6.5.1",
|
"@svgr/webpack": "^6.5.1",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@types/jest": "^29.2.2",
|
"@types/jest": "^29.2.3",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/sharp": "^0.31.0",
|
"@types/sharp": "^0.31.0",
|
||||||
"chalk": "^5.1.2",
|
"chalk": "^5.1.2",
|
||||||
"eslint": "^8.27.0",
|
"eslint": "^8.27.0",
|
||||||
"eslint-config-next": "^13.0.3",
|
"eslint-config-next": "^13.0.3",
|
||||||
"favicons": "^7.0.2",
|
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
"jest-canvas-mock": "^2.4.0",
|
"jest-canvas-mock": "^2.4.0",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.3.1",
|
||||||
@ -44,11 +43,11 @@
|
|||||||
"sharp": "^0.31.2",
|
"sharp": "^0.31.2",
|
||||||
"sharp-ico": "^0.1.5",
|
"sharp-ico": "^0.1.5",
|
||||||
"slugify": "^1.6.5",
|
"slugify": "^1.6.5",
|
||||||
"stylelint": "^14.14.1",
|
"stylelint": "^14.15.0",
|
||||||
"stylelint-config-prettier": "^9.0.4",
|
"stylelint-config-prettier": "^9.0.4",
|
||||||
"stylelint-prettier": "^2.0.0",
|
"stylelint-prettier": "^2.0.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.x"
|
"node": "16.x"
|
||||||
@ -3598,9 +3597,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/jest": {
|
"node_modules/@types/jest": {
|
||||||
"version": "29.2.2",
|
"version": "29.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.3.tgz",
|
||||||
"integrity": "sha512-og1wAmdxKoS71K2ZwSVqWPX6OVn3ihZ6ZT2qvZvZQm90lJVDyXIjYcu4Khx2CNIeaFv12rOU/YObOsI3VOkzog==",
|
"integrity": "sha512-6XwoEbmatfyoCjWRX7z0fKMmgYKe9+/HrviJ5k0X/tjJWHGAezZOfYaxqQKuzG/TvQyr+ktjm4jgbk0s4/oF2w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"expect": "^29.0.0",
|
"expect": "^29.0.0",
|
||||||
@ -5472,12 +5471,6 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/escape-html": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
@ -6204,20 +6197,6 @@
|
|||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/favicons": {
|
|
||||||
"version": "7.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/favicons/-/favicons-7.0.2.tgz",
|
|
||||||
"integrity": "sha512-M/qE3ERHOBu0+Op+61jx8CdvOnSKrrl2zxUPpoGgsNyfjuGqRsK80zYoA5Uwdxl8QM4egfhBWZp1j7KK3YnOMg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"escape-html": "^1.0.3",
|
|
||||||
"sharp": "^0.31.1",
|
|
||||||
"xml2js": "^0.4.23"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fb-watchman": {
|
"node_modules/fb-watchman": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
|
||||||
@ -11388,12 +11367,6 @@
|
|||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/sax": {
|
|
||||||
"version": "1.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
|
||||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/saxes": {
|
"node_modules/saxes": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
||||||
@ -11924,15 +11897,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stylelint": {
|
"node_modules/stylelint": {
|
||||||
"version": "14.14.1",
|
"version": "14.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.15.0.tgz",
|
||||||
"integrity": "sha512-Jnftu+lSD8cSpcV/+Z2nfgfgFpTIS1FcujezXPngtoIQ6wtwutL22MsNE0dJuMiM1h1790g2qIjAyUZCMrX4sw==",
|
"integrity": "sha512-JOgDAo5QRsqiOZPZO+B9rKJvBm64S0xasbuRPAbPs6/vQDgDCnZLIiw6XcAS6GQKk9k1sBWR6rmH3Mfj8OknKg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/selector-specificity": "^2.0.2",
|
"@csstools/selector-specificity": "^2.0.2",
|
||||||
"balanced-match": "^2.0.0",
|
"balanced-match": "^2.0.0",
|
||||||
"colord": "^2.9.3",
|
"colord": "^2.9.3",
|
||||||
"cosmiconfig": "^7.0.1",
|
"cosmiconfig": "^7.1.0",
|
||||||
"css-functions-list": "^3.1.0",
|
"css-functions-list": "^3.1.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.2.12",
|
"fast-glob": "^3.2.12",
|
||||||
@ -11952,7 +11925,7 @@
|
|||||||
"micromatch": "^4.0.5",
|
"micromatch": "^4.0.5",
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"postcss": "^8.4.18",
|
"postcss": "^8.4.19",
|
||||||
"postcss-media-query-parser": "^0.2.3",
|
"postcss-media-query-parser": "^0.2.3",
|
||||||
"postcss-resolve-nested-selector": "^0.1.1",
|
"postcss-resolve-nested-selector": "^0.1.1",
|
||||||
"postcss-safe-parser": "^6.0.0",
|
"postcss-safe-parser": "^6.0.0",
|
||||||
@ -12482,9 +12455,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.8.4",
|
"version": "4.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||||
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
|
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@ -13078,28 +13051,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/xml2js": {
|
|
||||||
"version": "0.4.23",
|
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
|
||||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"sax": ">=0.6.0",
|
|
||||||
"xmlbuilder": "~11.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xmlbuilder": {
|
|
||||||
"version": "11.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
|
||||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xmlchars": {
|
"node_modules/xmlchars": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
|
@ -42,13 +42,12 @@
|
|||||||
"@svgr/webpack": "^6.5.1",
|
"@svgr/webpack": "^6.5.1",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@types/jest": "^29.2.2",
|
"@types/jest": "^29.2.3",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/sharp": "^0.31.0",
|
"@types/sharp": "^0.31.0",
|
||||||
"chalk": "^5.1.2",
|
"chalk": "^5.1.2",
|
||||||
"eslint": "^8.27.0",
|
"eslint": "^8.27.0",
|
||||||
"eslint-config-next": "^13.0.3",
|
"eslint-config-next": "^13.0.3",
|
||||||
"favicons": "^7.0.2",
|
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
"jest-canvas-mock": "^2.4.0",
|
"jest-canvas-mock": "^2.4.0",
|
||||||
"jest-environment-jsdom": "^29.3.1",
|
"jest-environment-jsdom": "^29.3.1",
|
||||||
@ -57,12 +56,13 @@
|
|||||||
"prepend": "^1.0.2",
|
"prepend": "^1.0.2",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"sharp": "^0.31.2",
|
"sharp": "^0.31.2",
|
||||||
|
"sharp-ico": "^0.1.5",
|
||||||
"slugify": "^1.6.5",
|
"slugify": "^1.6.5",
|
||||||
"stylelint": "^14.14.1",
|
"stylelint": "^14.15.0",
|
||||||
"stylelint-config-prettier": "^9.0.4",
|
"stylelint-config-prettier": "^9.0.4",
|
||||||
"stylelint-prettier": "^2.0.0",
|
"stylelint-prettier": "^2.0.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.x"
|
"node": "16.x"
|
||||||
|
@ -5,12 +5,6 @@
|
|||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
>
|
>
|
||||||
<style>
|
<style>
|
||||||
#background {
|
|
||||||
fill: #e7eef4;
|
|
||||||
}
|
|
||||||
#logomark {
|
|
||||||
fill: #6b7f88;
|
|
||||||
}
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
#background {
|
#background {
|
||||||
fill: #161a1b;
|
fill: #161a1b;
|
||||||
@ -18,9 +12,10 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect id="background" width="512" height="512" />
|
<rect id="background" fill="#e7eef4" width="512" height="512" />
|
||||||
<path
|
<path
|
||||||
id="logomark"
|
id="logomark"
|
||||||
|
fill="#6b7f88"
|
||||||
d="M397,91 L421,115 L114,421 L91,398 L397,91 Z M397,182 L421,206 L205,421 L182,398 L397,182 Z M307,91 L330,115 L114,330 L91,307 L307,91 Z"
|
d="M397,91 L421,115 L114,421 L91,398 L397,91 Z M397,182 L421,206 L205,421 L182,398 L397,182 Z M307,91 L330,115 L114,330 L91,307 L307,91 Z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 541 B |
@ -1 +1 @@
|
|||||||
{"name":"matthias kretschmann","shortName":"mk","icons":[{"src":"/manifest/favicon-192.png","type":"image/png","sizes":"192x192"},{"src":"/manifest/favicon-512.png","type":"image/png","sizes":"512x512"}]}
|
{"name":"matthias kretschmann","short_name":"mk","display":"standalone","start_url":"/?homescreen=1","icons":[{"src":"/manifest/favicon-192.png","type":"image/png","sizes":"192x192"},{"src":"/manifest/favicon-512.png","type":"image/png","sizes":"512x512"}]}
|
@ -25,7 +25,9 @@ const outputMeta = `
|
|||||||
function createManifest(iconsizes: number[]) {
|
function createManifest(iconsizes: number[]) {
|
||||||
const manifest = {
|
const manifest = {
|
||||||
name: 'matthias kretschmann',
|
name: 'matthias kretschmann',
|
||||||
shortName: 'mk',
|
short_name: 'mk',
|
||||||
|
display: 'standalone',
|
||||||
|
start_url: '/?homescreen=1',
|
||||||
icons: iconsizes.map((size) => ({
|
icons: iconsizes.map((size) => ({
|
||||||
src: `/manifest/favicon-${size}.png`,
|
src: `/manifest/favicon-${size}.png`,
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
@ -38,13 +40,18 @@ function createManifest(iconsizes: number[]) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildFavicons() {
|
function nuke() {
|
||||||
try {
|
|
||||||
// Nuke all & create output folder first
|
|
||||||
fs.rmSync(outputManifest, { recursive: true, force: true })
|
fs.rmSync(outputManifest, { recursive: true, force: true })
|
||||||
fs.rmSync(`${outputWebRoot}/apple-touch-icon.png`, { force: true })
|
fs.rmSync(`${outputWebRoot}/apple-touch-icon.png`, { force: true })
|
||||||
fs.rmSync(`${outputWebRoot}/favicon.ico`, { force: true })
|
fs.rmSync(`${outputWebRoot}/favicon.ico`, { force: true })
|
||||||
|
fs.rmSync(`${outputWebRoot}/favicon.svg`, { force: true })
|
||||||
fs.mkdirSync(outputManifest, { recursive: true })
|
fs.mkdirSync(outputManifest, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildFavicons() {
|
||||||
|
try {
|
||||||
|
// Nuke all & create output folder first
|
||||||
|
nuke()
|
||||||
|
|
||||||
// copy over the svg, as it's handcrafted
|
// copy over the svg, as it's handcrafted
|
||||||
fs.copyFileSync(faviconSourceSvg, `${outputWebRoot}/favicon.svg`)
|
fs.copyFileSync(faviconSourceSvg, `${outputWebRoot}/favicon.svg`)
|
||||||
@ -55,6 +62,7 @@ async function buildFavicons() {
|
|||||||
let destination = `${outputManifest}/favicon-${size}.png`
|
let destination = `${outputManifest}/favicon-${size}.png`
|
||||||
if (size === 180) destination = `${outputWebRoot}/apple-touch-icon.png`
|
if (size === 180) destination = `${outputWebRoot}/apple-touch-icon.png`
|
||||||
|
|
||||||
|
// 32px size only used for favicon.ico
|
||||||
if (size === 32) {
|
if (size === 32) {
|
||||||
await ico.sharpsToIco(
|
await ico.sharpsToIco(
|
||||||
[sharp(faviconSource)],
|
[sharp(faviconSource)],
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from 'react'
|
|
||||||
import Icon from '../Icon'
|
import Icon from '../Icon'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
|
|
||||||
export const ThemeToggle = ({ dark }) => (
|
export const ThemeToggle = () => (
|
||||||
<span id="toggle" className={styles.checkboxContainer} aria-live="assertive">
|
<span id="toggle" className={styles.checkboxContainer} aria-live="assertive">
|
||||||
<Icon name="Sun" />
|
<Icon name="Sun" />
|
||||||
<span className={styles.checkboxFake} />
|
<span className={styles.checkboxFake} />
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import React from 'react'
|
import useDarkMode from '../../hooks/useDarkMode'
|
||||||
|
|
||||||
type Props = {
|
export const ThemeToggleInput = () => {
|
||||||
dark: boolean
|
const { isDarkMode, setIsDarkMode } = useDarkMode()
|
||||||
toggleDark: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ThemeToggleInput = ({ dark, toggleDark }: Props) => (
|
return (
|
||||||
<input
|
<input
|
||||||
onChange={() => toggleDark()}
|
onChange={() => setIsDarkMode(!isDarkMode)}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="toggle"
|
name="toggle"
|
||||||
value="toggle"
|
value="toggle"
|
||||||
aria-describedby="toggle"
|
aria-describedby="toggle"
|
||||||
checked={dark}
|
checked={isDarkMode === true}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { ThemeToggle } from './ThemeToggle'
|
|||||||
import { ThemeToggleInput } from './ThemeToggleInput'
|
import { ThemeToggleInput } from './ThemeToggleInput'
|
||||||
|
|
||||||
export default function ThemeSwitch() {
|
export default function ThemeSwitch() {
|
||||||
const { value, toggle, themeColor } = useDarkMode()
|
const { themeColor } = useDarkMode()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -20,8 +20,8 @@ export default function ThemeSwitch() {
|
|||||||
<aside className={styles.themeSwitch}>
|
<aside className={styles.themeSwitch}>
|
||||||
<label className={styles.checkbox}>
|
<label className={styles.checkbox}>
|
||||||
<span className={styles.label}>Toggle Night Mode</span>
|
<span className={styles.label}>Toggle Night Mode</span>
|
||||||
<ThemeToggleInput dark={value} toggleDark={toggle} />
|
<ThemeToggleInput />
|
||||||
<ThemeToggle dark={value} />
|
<ThemeToggle />
|
||||||
</label>
|
</label>
|
||||||
</aside>
|
</aside>
|
||||||
</>
|
</>
|
||||||
|
@ -2,7 +2,13 @@
|
|||||||
// adapted from
|
// adapted from
|
||||||
// https://github.com/daveschumaker/react-dark-mode-hook/blob/master/useDarkMode.js
|
// https://github.com/daveschumaker/react-dark-mode-hook/blob/master/useDarkMode.js
|
||||||
//
|
//
|
||||||
import { useState, useEffect, useCallback } from 'react'
|
import {
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useCallback,
|
||||||
|
Dispatch,
|
||||||
|
SetStateAction
|
||||||
|
} from 'react'
|
||||||
|
|
||||||
const isClient = typeof window === 'object'
|
const isClient = typeof window === 'object'
|
||||||
|
|
||||||
@ -24,37 +30,37 @@ function getDarkMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useDarkMode() {
|
export type UseDarkMode = {
|
||||||
const [darkMode, setDarkMode] = useState<boolean>()
|
isDarkMode: boolean
|
||||||
|
themeColor: string
|
||||||
|
setIsDarkMode: Dispatch<SetStateAction<boolean>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useDarkMode(): UseDarkMode {
|
||||||
|
const [isDarkMode, setIsDarkMode] = useState<boolean>(getDarkMode())
|
||||||
const [themeColor, setThemeColor] = useState<string>()
|
const [themeColor, setThemeColor] = useState<string>()
|
||||||
|
|
||||||
const toggleDarkMode = useCallback(() => {
|
const changeTheme = useCallback(() => {
|
||||||
setDarkMode(!darkMode)
|
if (isDarkMode) {
|
||||||
}, [darkMode])
|
document.documentElement.classList.add('dark')
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark')
|
||||||
|
}
|
||||||
|
setThemeColor(isDarkMode === true ? '#1d2224' : '#e7eef4')
|
||||||
|
}, [isDarkMode])
|
||||||
|
|
||||||
//
|
//
|
||||||
// Init
|
// Init
|
||||||
//
|
//
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prefersDark = getDarkMode()
|
changeTheme()
|
||||||
setDarkMode(prefersDark)
|
}, [changeTheme])
|
||||||
}, [])
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do things when darkMode changes
|
|
||||||
//
|
|
||||||
useEffect(() => {
|
|
||||||
const bodyClassList = document.querySelector('body').classList
|
|
||||||
bodyClassList.toggle('dark')
|
|
||||||
bodyClassList.toggle('light')
|
|
||||||
setThemeColor(darkMode === true ? '#1d2224' : '#e7eef4')
|
|
||||||
}, [darkMode])
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle system theme change events
|
// Handle system theme change events
|
||||||
//
|
//
|
||||||
const handleChange = useCallback(() => {
|
const handleChange = useCallback(() => {
|
||||||
setDarkMode(getDarkMode())
|
setIsDarkMode(getDarkMode())
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -74,5 +80,5 @@ export default function useDarkMode() {
|
|||||||
.removeEventListener('change', handleChange)
|
.removeEventListener('change', handleChange)
|
||||||
}, [handleChange])
|
}, [handleChange])
|
||||||
|
|
||||||
return { value: darkMode, toggle: toggleDarkMode, themeColor }
|
return { isDarkMode, setIsDarkMode, themeColor }
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,6 @@
|
|||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
>
|
>
|
||||||
<style>
|
<style>
|
||||||
#background {
|
|
||||||
fill: #e7eef4;
|
|
||||||
}
|
|
||||||
#logomark {
|
|
||||||
fill: #6b7f88;
|
|
||||||
}
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
#background {
|
#background {
|
||||||
fill: #161a1b;
|
fill: #161a1b;
|
||||||
@ -18,9 +12,10 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect id="background" width="512" height="512" />
|
<rect id="background" fill="#e7eef4" width="512" height="512" />
|
||||||
<path
|
<path
|
||||||
id="logomark"
|
id="logomark"
|
||||||
|
fill="#6b7f88"
|
||||||
d="M397,91 L421,115 L114,421 L91,398 L397,91 Z M397,182 L421,206 L205,421 L182,398 L397,182 Z M307,91 L330,115 L114,330 L91,307 L307,91 Z"
|
d="M397,91 L421,115 L114,421 L91,398 L397,91 Z M397,182 L421,206 L205,421 L182,398 L397,182 Z M307,91 L330,115 L114,330 L91,307 L307,91 Z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 541 B |
Loading…
Reference in New Issue
Block a user