added language toggle feature

This commit is contained in:
Kim, Jimin 2021-05-19 13:38:10 +09:00
parent 255d3939e3
commit 6c1de6bbbd
3 changed files with 131 additions and 65 deletions

View file

@ -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,45 +189,57 @@ 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
}} }}
> >
<GlobalStyle /> <LanguageContext.Provider value={languageState}>
<Router> <GlobalStyle />
<Navbar /> <Router>
<div id="content"> <Navbar />
{isLoading ? ( <div id="content">
<Spinner {isLoading ? (
size={200} <Spinner
color={ size={200}
currentTheme.mode == "light" color={
? theming.light.color1 currentTheme.mode == "light"
: theming.dark.color1 ? theming.light.color1
} : theming.dark.color1
/> }
) : (
<Switch>
<Route
exact
path="/"
component={() => (
<Home howMany={4} title="Home" />
)}
/> />
<Route ) : (
exact <Switch>
path="/archives" <Route
component={() => <Home title="Archives" />} exact
/> path="/"
<Route component={() => (
exact <Home howMany={4} title="Home" />
path="/portfolio" )}
component={Portfolio} />
/> <Route
<Route exact path="/404" component={NotFound} /> exact
<Route exact path="/:path*" component={Page} /> path="/archives"
</Switch> component={() => (
)} <Home title="Archives" />
</div> )}
<Footer /> />
</Router> <Route
exact
path="/portfolio"
component={Portfolio}
/>
<Route
exact
path="/404"
component={NotFound}
/>
<Route
exact
path="/:path*"
component={Page}
/>
</Switch>
)}
</div>
<Footer />
</Router>
</LanguageContext.Provider>
</ThemeProvider> </ThemeProvider>
</HelmetProvider> </HelmetProvider>
) )

View 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: () => {},
})

View file

@ -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>
<StyledThemeButton data-tip data-for="language"> {({ language, toggleLanguage }) => (
<FontAwesomeIcon icon={faLanguage} /> <>
</StyledThemeButton> <StyledThemeButton
<ReactTooltip id="language" type="dark" effect="solid"> data-tip
<span>Change to Korean/English</span> data-for="language"
</ReactTooltip> onClick={toggleLanguage}
</> language={language}
>
<FontAwesomeIcon icon={faLanguage} />
</StyledThemeButton>
<ReactTooltip id="language" type="dark" effect="solid">
<span>Using {languageName(language)} language</span>
</ReactTooltip>
</>
)}
</LanguageContext.Consumer>
) )
} }