added language toggle feature
This commit is contained in:
parent
255d3939e3
commit
6c1de6bbbd
3 changed files with 131 additions and 65 deletions
|
@ -5,7 +5,7 @@ import storage from "local-storage-fallback"
|
||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
import theme from "styled-theming"
|
import theme from "styled-theming"
|
||||||
import Spinner from "./components/Spinner"
|
import Spinner from "./components/Spinner"
|
||||||
|
import LanguageContext from "./LanguageContext"
|
||||||
import theming from "./theming"
|
import theming from "./theming"
|
||||||
|
|
||||||
import Navbar from "./components/Navbar"
|
import Navbar from "./components/Navbar"
|
||||||
|
@ -125,16 +125,9 @@ blockquote {
|
||||||
`
|
`
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [currentTheme, _setTheme] = useState(() => {
|
/**
|
||||||
const savedTheme = storage.getItem("theme")
|
* Loading
|
||||||
return savedTheme ? JSON.parse(savedTheme) : { mode: "dark" }
|
*/
|
||||||
})
|
|
||||||
|
|
||||||
// save theme when theme is changed
|
|
||||||
useEffect(() => {
|
|
||||||
storage.setItem("theme", JSON.stringify(currentTheme))
|
|
||||||
}, [currentTheme])
|
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState(true)
|
const [isLoading, setLoading] = useState(true)
|
||||||
|
|
||||||
// show loading screen until all fonts are loaded.
|
// show loading screen until all fonts are loaded.
|
||||||
|
@ -151,6 +144,42 @@ function App() {
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme
|
||||||
|
*/
|
||||||
|
const [currentTheme, _setTheme] = useState(() => {
|
||||||
|
const savedTheme = storage.getItem("theme")
|
||||||
|
return savedTheme ? JSON.parse(savedTheme) : { mode: "dark" }
|
||||||
|
})
|
||||||
|
|
||||||
|
// save theme when it is changed
|
||||||
|
useEffect(() => {
|
||||||
|
storage.setItem("theme", JSON.stringify(currentTheme))
|
||||||
|
}, [currentTheme])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language
|
||||||
|
*/
|
||||||
|
|
||||||
|
const [currentLanguage, _setLanguage] = useState(
|
||||||
|
storage.getItem("lang") || "en" // get language from storage and set to "en" if not set already
|
||||||
|
)
|
||||||
|
|
||||||
|
// save language when it is changed
|
||||||
|
useEffect(() => {
|
||||||
|
storage.setItem("lang", currentLanguage)
|
||||||
|
}, [currentLanguage])
|
||||||
|
|
||||||
|
const languageState = {
|
||||||
|
language: currentLanguage,
|
||||||
|
toggleLanguage: () => {
|
||||||
|
// cycle through languages
|
||||||
|
let setLanguageTo = "en"
|
||||||
|
if (currentLanguage == "en") setLanguageTo = "kr"
|
||||||
|
_setLanguage(setLanguageTo)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HelmetProvider>
|
<HelmetProvider>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
|
@ -160,6 +189,7 @@ function App() {
|
||||||
setTheme: ({ setTheme, ...theme }) => _setTheme(theme), // make setTheme function available in other components
|
setTheme: ({ setTheme, ...theme }) => _setTheme(theme), // make setTheme function available in other components
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<LanguageContext.Provider value={languageState}>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<Router>
|
<Router>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
@ -185,20 +215,31 @@ function App() {
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/archives"
|
path="/archives"
|
||||||
component={() => <Home title="Archives" />}
|
component={() => (
|
||||||
|
<Home title="Archives" />
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/portfolio"
|
path="/portfolio"
|
||||||
component={Portfolio}
|
component={Portfolio}
|
||||||
/>
|
/>
|
||||||
<Route exact path="/404" component={NotFound} />
|
<Route
|
||||||
<Route exact path="/:path*" component={Page} />
|
exact
|
||||||
|
path="/404"
|
||||||
|
component={NotFound}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/:path*"
|
||||||
|
component={Page}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Router>
|
</Router>
|
||||||
|
</LanguageContext.Provider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</HelmetProvider>
|
</HelmetProvider>
|
||||||
)
|
)
|
||||||
|
|
11
source/src/LanguageContext.ts
Normal file
11
source/src/LanguageContext.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* go to App.tsx and search for `languageState` to see the actual values
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createContext } from "react"
|
||||||
|
|
||||||
|
export default createContext({
|
||||||
|
language: "",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
toggleLanguage: () => {},
|
||||||
|
})
|
|
@ -1,34 +1,48 @@
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faLanguage } from "@fortawesome/free-solid-svg-icons"
|
import { faLanguage } from "@fortawesome/free-solid-svg-icons"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import theme from "styled-theming"
|
|
||||||
|
|
||||||
import ReactTooltip from "react-tooltip"
|
import ReactTooltip from "react-tooltip"
|
||||||
|
|
||||||
|
import LanguageContext from "../LanguageContext"
|
||||||
import theming from "../theming"
|
import theming from "../theming"
|
||||||
|
|
||||||
const StyledThemeButton = styled.div`
|
const StyledThemeButton = styled.div<{ language: string }>`
|
||||||
${theming.styles.navbarButtonStyle}
|
${theming.styles.navbarButtonStyle}
|
||||||
transition: transform 0.2s linear;
|
transition: transform 0.2s linear;
|
||||||
/* ${theme("mode", {
|
${(props) =>
|
||||||
light: "",
|
props.language == "en"
|
||||||
dark: "transform: scaleX(-1);\
|
? ""
|
||||||
|
: "transform: scaleX(-1);\
|
||||||
-moz-transform: scaleX(-1);\
|
-moz-transform: scaleX(-1);\
|
||||||
-webkit-transform: scaleX(-1);\
|
-webkit-transform: scaleX(-1);\
|
||||||
-ms-transform: scaleX(-1);",
|
-ms-transform: scaleX(-1);"};
|
||||||
})}; */
|
|
||||||
`
|
`
|
||||||
|
|
||||||
function LanguageToggleButton() {
|
function LanguageToggleButton() {
|
||||||
|
function languageName(language) {
|
||||||
|
let name = "English"
|
||||||
|
if (language == "kr") name = "Korean"
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<LanguageContext.Consumer>
|
||||||
|
{({ language, toggleLanguage }) => (
|
||||||
<>
|
<>
|
||||||
<StyledThemeButton data-tip data-for="language">
|
<StyledThemeButton
|
||||||
|
data-tip
|
||||||
|
data-for="language"
|
||||||
|
onClick={toggleLanguage}
|
||||||
|
language={language}
|
||||||
|
>
|
||||||
<FontAwesomeIcon icon={faLanguage} />
|
<FontAwesomeIcon icon={faLanguage} />
|
||||||
</StyledThemeButton>
|
</StyledThemeButton>
|
||||||
<ReactTooltip id="language" type="dark" effect="solid">
|
<ReactTooltip id="language" type="dark" effect="solid">
|
||||||
<span>Change to Korean/English</span>
|
<span>Using {languageName(language)} language</span>
|
||||||
</ReactTooltip>
|
</ReactTooltip>
|
||||||
</>
|
</>
|
||||||
|
)}
|
||||||
|
</LanguageContext.Consumer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue