An opinionated guide on how to theme your react application with SCSS and Redux.
Steps to follow
Create a new app with create-react-app
npx create-react-app myapp
Add structure to your app:
... src store theme theme.slice.js theme.actions.js rootReducer styles _themes.scss _themify.scss components layout layout.jsx layout.scss page home home.jsx about about.jsx App.js ...
Add these packages to the app
npm i @reduxjs/toolkit redux node-sass react-router-dom react-redux --save
Create the theme slice
// theme.slice.js import { createSlice } from '@reduxjs/toolkit' import { uiActions } from './ui.actions' export const uiSlice = createSlice({ name: 'ui', initialState: 'light-theme', reducers: uiActions }) export const { toggleTheme } = uiSlice.actions export default uiSlice.reducer
Create the theme action
// theme.action.js export const uiActions = { toggleTheme: state => { console.log(state); return state === 'dark-theme' ? 'light-theme' : 'dark-theme'; } };
Create the reducer
// rootReducer.js import { configureStore } from '@reduxjs/toolkit' import uiReducer from './ui/ui.slice' export default configureStore({ reducer: { ui: uiReducer, } })
Create your theme map
// themes.scss $themes: ( light: ( bg: #f5fcff, fg: #002433, ), dark: ( bg: #004966, fg: #f5fcff, ), );
Create the themify @mixin
// themify.scss @import 'themes'; @mixin themify($property, $key, $themes: $themes) { // Iterate over the themes @each $theme, $colors in $themes { // Create a selector &.#{$theme}-theme, .#{$theme}-theme & { // Output the declaration #{$property}: map-get($colors, $key); } } }
Create the layout component
// layout.jsx import { useSelector, useDispatch } from "react-redux"; import { toggleTheme } from "../../store/ui/ui.slice"; import './layout.scss'; export default function Layout(props) { const theme = useSelector(state => state.ui); const dispatch = useDispatch(); return ( <> <header className={`${theme} container`}> <Header /> <button onClick={() => dispatch(toggleTheme())}>Toggle Theme</button> </header> <div className={`${theme} container`}> {props.children} </div> </> ) }
Apply styles to the layout
// layout.scss @import "../../assets/style/themify"; header { @include themify('background', 'body-bg'); }
Now create your pages
// home.jsx import { Layout } from "../../components/layout/layout"; export default function Home() { return ( <Layout> <section> Home Page </section> </Layout> ) }
// about.jsx import { Layout } from "../../components/layout/layout"; export default function About() { return ( <Layout> <section> About Page </section> </Layout> ) }
Create routes for the application
// App.js import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import Home from './pages/home/home'; import About from './pages/about/about'; function App() { return ( <Router> <Switch> <Route exact path='/' component={Home} /> <Route exact path='/tasks' component={About} /> </Switch> </Router> ); } export default App;
The output:
Run the output on codepen.
Thanks.
Top comments (0)