Adapt theme to app directory

This commit is contained in:
2023-07-22 13:02:59 +04:00
parent 43994c237c
commit 5335701b76
2 changed files with 192 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
'use client'
import * as React from 'react'
import PropTypes from 'prop-types'
import createCache from '@emotion/cache'
import {useServerInsertedHTML} from 'next/navigation'
import {CacheProvider as DefaultCacheProvider} from '@emotion/react'
export default function NextAppDirEmotionCacheProvider(props) {
const {options, CacheProvider = DefaultCacheProvider, children} = props
const [registry] = React.useState(() => {
const cache = createCache(options)
cache.compat = true
const prevInsert = cache.insert
let inserted = []
cache.insert = (...args) => {
const [selector, serialized] = args
if (cache.inserted[serialized.name] === undefined) {
inserted.push({
name: serialized.name,
isGlobal: selector === '',
})
}
return prevInsert(...args)
}
const flush = () => {
const prevInserted = inserted
inserted = []
return prevInserted
}
return {cache, flush}
})
useServerInsertedHTML(() => {
const inserted = registry.flush()
if (inserted.length === 0) {
return null
}
let styles = ''
let dataEmotionAttribute = registry.cache.key
const globals = []
for (const {name, isGlobal} of inserted) {
const style = registry.cache.inserted[name]
if (typeof style !== 'boolean') {
if (isGlobal) {
globals.push({name, style})
} else {
styles += style
dataEmotionAttribute += ` ${name}`
}
}
}
return (
<>
{globals.map(({name, style}) => (
<style
key={name}
dangerouslySetInnerHTML={{__html: style}}
data-emotion={`${registry.cache.key}-global ${name}`}
/>
))}
{styles !== '' && (
<style
dangerouslySetInnerHTML={{__html: styles}}
data-emotion={dataEmotionAttribute}
/>
)}
</>
)
})
return <CacheProvider value={registry.cache}>{children}</CacheProvider>
}
NextAppDirEmotionCacheProvider.propTypes = {
options: PropTypes.object.isRequired,
CacheProvider: PropTypes.func,
children: PropTypes.node.isRequired
}
+104
View File
@@ -0,0 +1,104 @@
'use client'
import PropTypes from 'prop-types'
import {useState, useMemo, useEffect, createContext} from 'react'
import {createTheme, ThemeProvider} from '@mui/material/styles'
import CssBaseline from '@mui/material/CssBaseline'
import {grey, green, red, yellow} from '@mui/material/colors'
import '@fontsource/roboto/300.css'
import '@fontsource/roboto/400.css'
import '@fontsource/roboto/500.css'
import '@fontsource/roboto/700.css'
import '../styles/nprogress.css'
import ChanjeTem from '../components/chanje-tem'
import NextAppDirEmotionCacheProvider from './emotion-cache-provider'
export const ColorModeContext = createContext({toggleColorMode: () => {}})
const getDesignTokens = mode => ({
palette: {
mode,
...(mode === 'light'
? {
primary: green,
secondary: red,
divider: green[200],
info: {
main: grey[900]
},
text: {
primary: grey[900],
secondary: grey[800],
},
}
: {
primary: {
main: yellow[500],
contrastText: '#000'
},
secondary: red,
info: {
main: '#fff'
},
divider: green[700],
background: {
default: '#082211',
paper: '#082211',
},
text: {
primary: '#fff',
secondary: grey[100],
},
}),
},
})
export default function ThemeRegistry(props) {
const [mode, setMode] = useState('light')
const colorMode = useMemo(
() => ({
toggleColorMode: () => {
setMode(prevMode =>
prevMode === 'light' ? 'dark' : 'light',
)
},
}),
[],
)
const theme = useMemo(() => createTheme(getDesignTokens(mode)), [mode])
const {children} = props
useEffect(() => {
const vyeLokalMod = localStorage.getItem('oki-dark')
const lokalMod = localStorage.getItem('oki-tem')
if (lokalMod === 'dark' || (vyeLokalMod && vyeLokalMod === 'true')) {
setMode('dark')
} else {
setMode('light')
}
if (lokalMod && vyeLokalMod) {
localStorage.removeItem('oki-dark')
}
}, [])
return (
<NextAppDirEmotionCacheProvider options={{key: 'mui'}}>
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<CssBaseline enableColorScheme />
<ChanjeTem />
{children}
</ThemeProvider>
</ColorModeContext.Provider>
</NextAppDirEmotionCacheProvider>
)
}
ThemeRegistry.propTypes = {
children: PropTypes.node.isRequired
}