mirror of
https://github.com/hazemKrimi/personal-website.git
synced 2026-05-01 18:00:26 +00:00
Fix FOUC
This commit is contained in:
@@ -35,6 +35,8 @@ const GlobalStyles = createGlobalStyle`
|
|||||||
html {
|
html {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
background: var(--background) !important;
|
||||||
|
color: var(--text) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, ol {
|
ul, ol {
|
||||||
@@ -43,8 +45,6 @@ const GlobalStyles = createGlobalStyle`
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0 0 100px;
|
margin: 0 0 100px;
|
||||||
background: var(--background);
|
|
||||||
color: var(--text);
|
|
||||||
transition: color 250ms ease-in-out, background 250ms ease-in-out;
|
transition: color 250ms ease-in-out, background 250ms ease-in-out;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
|
import Script from 'next/script';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
@@ -35,7 +36,80 @@ const App = ({ Component, pageProps }: AppProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Script
|
||||||
|
strategy='afterInteractive'
|
||||||
|
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS_KEY}`}
|
||||||
|
/>
|
||||||
|
<Script
|
||||||
|
id='analytics-init'
|
||||||
|
strategy='afterInteractive'
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
|
||||||
|
function gtag() {
|
||||||
|
dataLayer.push(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', ${process.env.GOOGLE_ANALYTICS_KEY});
|
||||||
|
`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Script
|
||||||
|
id='styles-init'
|
||||||
|
strategy='afterInteractive'
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `
|
||||||
|
function getInitialThemeMode() {
|
||||||
|
const persistedColorPreference = window.localStorage.getItem('mode');
|
||||||
|
const hasPersistedPreference = typeof persistedColorPreference === 'string';
|
||||||
|
|
||||||
|
if (hasPersistedPreference) {
|
||||||
|
return persistedColorPreference;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mql = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
const hasMediaQueryPreference = typeof mql.matches === 'boolean';
|
||||||
|
|
||||||
|
if (hasMediaQueryPreference) {
|
||||||
|
return mql.matches ? 'dark' : 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const mode = getInitialThemeMode();
|
||||||
|
const root = document.documentElement;
|
||||||
|
const lightFavicon = document.querySelector('link#light-favicon');
|
||||||
|
const darkFavicon = document.querySelector('link#dark-favicon');
|
||||||
|
|
||||||
|
root.style.setProperty('--mode', mode);
|
||||||
|
root.style.setProperty(
|
||||||
|
'--background',
|
||||||
|
mode === 'light' ? '#F9F9F9' : '#262626'
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
'--secondary-background',
|
||||||
|
mode === 'light' ? 'white' : '#2F2F2F'
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
'--text',
|
||||||
|
mode === 'light' ? 'black' : 'white'
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
'--text-inverted',
|
||||||
|
mode === 'light' ? 'white' : 'black'
|
||||||
|
);
|
||||||
|
document.head.append(mode === 'light' ? darkFavicon : lightFavicon);
|
||||||
|
})();
|
||||||
|
`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Head>
|
<Head>
|
||||||
|
<link rel='shortcut icon' href='light-favicon.png' id='light-favicon'></link>
|
||||||
|
<link rel='shortcut icon' href='dark-favicon.png' id='dark-favicon'></link>
|
||||||
<link rel='preconnect' href='https://fonts.gstatic.com' />
|
<link rel='preconnect' href='https://fonts.gstatic.com' />
|
||||||
<link
|
<link
|
||||||
href='https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap'
|
href='https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap'
|
||||||
|
|||||||
+3
-82
@@ -1,15 +1,15 @@
|
|||||||
import Document, { Html, Head, Main, NextScript } from 'next/document';
|
import Document, { DocumentContext } from 'next/document';
|
||||||
import { ServerStyleSheet } from 'styled-components';
|
import { ServerStyleSheet } from 'styled-components';
|
||||||
|
|
||||||
class Doc extends Document {
|
class Doc extends Document {
|
||||||
static async getInitialProps(ctx: any) {
|
static async getInitialProps(ctx: DocumentContext) {
|
||||||
const sheet = new ServerStyleSheet();
|
const sheet = new ServerStyleSheet();
|
||||||
const originalRenderPage = ctx.renderPage;
|
const originalRenderPage = ctx.renderPage;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ctx.renderPage = () =>
|
ctx.renderPage = () =>
|
||||||
originalRenderPage({
|
originalRenderPage({
|
||||||
enhanceApp: (App: any) => (props: any) => sheet.collectStyles(<App {...props} />)
|
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialProps = await Document.getInitialProps(ctx);
|
const initialProps = await Document.getInitialProps(ctx);
|
||||||
@@ -26,85 +26,6 @@ class Doc extends Document {
|
|||||||
sheet.seal();
|
sheet.seal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Html>
|
|
||||||
<Head>
|
|
||||||
<link rel='shortcut icon' href='light-favicon.png' id='light-favicon'></link>
|
|
||||||
<link rel='shortcut icon' href='dark-favicon.png' id='dark-favicon'></link>
|
|
||||||
<script async src='https://www.googletagmanager.com/gtag/js?id=G-FMD81GLKS3'></script>
|
|
||||||
<script
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: `
|
|
||||||
window.dataLayer = window.dataLayer || [];
|
|
||||||
|
|
||||||
function gtag() {
|
|
||||||
dataLayer.push(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtag('js', new Date());
|
|
||||||
gtag('config', ${process.env.GOOGLE_ANALYTICS_KEY});
|
|
||||||
`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: `
|
|
||||||
function getInitialThemeMode() {
|
|
||||||
const persistedColorPreference = window.localStorage.getItem('mode');
|
|
||||||
const hasPersistedPreference = typeof persistedColorPreference === 'string';
|
|
||||||
|
|
||||||
if (hasPersistedPreference) {
|
|
||||||
return persistedColorPreference;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mql = window.matchMedia('(prefers-color-scheme: dark)');
|
|
||||||
const hasMediaQueryPreference = typeof mql.matches === 'boolean';
|
|
||||||
|
|
||||||
if (hasMediaQueryPreference) {
|
|
||||||
return mql.matches ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
(() => {
|
|
||||||
const mode = getInitialThemeMode();
|
|
||||||
const root = document.documentElement;
|
|
||||||
const lightFavicon = document.querySelector('link#light-favicon');
|
|
||||||
const darkFavicon = document.querySelector('link#dark-favicon');
|
|
||||||
|
|
||||||
root.style.setProperty('--mode', mode);
|
|
||||||
root.style.setProperty(
|
|
||||||
'--background',
|
|
||||||
mode === 'light' ? '#F9F9F9' : '#262626'
|
|
||||||
);
|
|
||||||
root.style.setProperty(
|
|
||||||
'--secondary-background',
|
|
||||||
mode === 'light' ? 'white' : '#2F2F2F'
|
|
||||||
);
|
|
||||||
root.style.setProperty(
|
|
||||||
'--text',
|
|
||||||
mode === 'light' ? 'black' : 'white'
|
|
||||||
);
|
|
||||||
root.style.setProperty(
|
|
||||||
'--text-inverted',
|
|
||||||
mode === 'light' ? 'white' : 'black'
|
|
||||||
);
|
|
||||||
document.head.append(mode === 'light' ? darkFavicon : lightFavicon);
|
|
||||||
})();
|
|
||||||
`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Head>
|
|
||||||
<body>
|
|
||||||
<Main />
|
|
||||||
<NextScript />
|
|
||||||
</body>
|
|
||||||
</Html>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Doc;
|
export default Doc;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FC, useEffect, useRef } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { getPortfolioPorjectsSlugs, getPortfolioProjectdata } from '../../utils/portfolio';
|
import { getPortfolioPorjectsSlugs, getPortfolioProjectdata } from '../../utils/portfolio';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
|
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
|
||||||
@@ -21,7 +21,6 @@ interface Props {
|
|||||||
|
|
||||||
const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const metaRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
@@ -58,7 +57,7 @@ const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
|||||||
<title>{frontMatter.title} | Hazem Krimi</title>
|
<title>{frontMatter.title} | Hazem Krimi</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<div className='meta' ref={metaRef}>
|
<div className='meta'>
|
||||||
<div className='back' onClick={() => router.back()}>
|
<div className='back' onClick={() => router.back()}>
|
||||||
<IconButton icon='/icons/arrow-left.svg' />
|
<IconButton icon='/icons/arrow-left.svg' />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
|
|||||||
+13
-1
@@ -11,13 +11,25 @@ export const Wrapper = styled.div`
|
|||||||
row-gap: 1rem;
|
row-gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
p,
|
||||||
|
span,
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
.meta {
|
.meta {
|
||||||
.back {
|
.back {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #3f9aee;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: ${({ theme }) => theme.colors.blue} !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
|
|||||||
@@ -11,13 +11,25 @@ export const Wrapper = styled.div`
|
|||||||
row-gap: 1rem;
|
row-gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
p,
|
||||||
|
span,
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
.meta {
|
.meta {
|
||||||
.back {
|
.back {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #3f9aee;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: ${({ theme }) => theme.colors.blue} !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
|
|||||||
+20
-30
@@ -1,32 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": [
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"dom",
|
"allowJs": true,
|
||||||
"dom.iterable",
|
"skipLibCheck": true,
|
||||||
"esnext"
|
"esModuleInterop": true,
|
||||||
],
|
"allowSyntheticDefaultImports": true,
|
||||||
"allowJs": true,
|
"strict": true,
|
||||||
"skipLibCheck": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"esModuleInterop": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"module": "esnext",
|
||||||
"strict": true,
|
"moduleResolution": "node",
|
||||||
"forceConsistentCasingInFileNames": true,
|
"resolveJsonModule": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"isolatedModules": true,
|
||||||
"module": "esnext",
|
"noEmit": true,
|
||||||
"moduleResolution": "node",
|
"incremental": true,
|
||||||
"resolveJsonModule": true,
|
"jsx": "preserve"
|
||||||
"isolatedModules": true,
|
},
|
||||||
"noEmit": true,
|
"exclude": ["node_modules"],
|
||||||
"jsx": "preserve",
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||||
"incremental": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"next-env.d.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"**/*.tsx"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user