본문 바로가기

styled-components

ThemeProvider 사용하기 (3) - 토글해서 GlobalStyle 바꾸기

이 포스트는 Udemy 사이트에 올라 온 Tom Phillips의 "React styled-components v5 (2021 edition)" 강의를 듣고 정리한 것입니다.

 

🔗링크

https://www.udemy.com/course/react-styled-components/

 

React styled components v5 (2021 edition)

Ditch CSS stylesheets! Learn CSS in JS to quickly and cleanly style React components with the styled components library

www.udemy.com

 

 

 

 

 

 

1. 밝은 배경과 어두운 배경 각각에 사용할 배경색과 폰트색을 설정한다.

 

📂 src > themes > light.js

const theme = {
	id: "light",
	primaryColor: "#f8049c",
	secondaryColor: " #fdd54f",
	bodyBackgroundColor: "white",
	bodyFontColor: "black",
};

export default theme;

 

📂 src > themes > dark.js

const theme = {
	id: "dark",
	primaryColor: "black",
	secondaryColor: " midnightblue",
	bodyBackgroundColor: "black",
	bodyFontColor: "white",
};

export default theme;

 

 

 

 

 

2. GlobalStyle의 배경색과 폰트색을 theme에 따라 바뀌게 한다.

📂 src > components > App.js

const GlobalStyle = createGlobalStyle`
	body{
		background-color: ${(props) => props.theme.bodyBackgroundColor};
		color:${(props) => props.theme.bodyFontColor};
		min-height:100vh;
		margin:0;
		font-family: 'Kaushan Script', cursive;
	}
`;

 

 

 

 

 

 

3. 추가로 헤더에 있는 메뉴들 색도 다 theme에 맞게 바뀌게 한다.

 

📂 src > components > common > Header.js

import { useState, useContext } from "react";
import styled, { ThemeContext } from "styled-components";
import { Link as ReactRouterDomLink, useLocation } from "react-router-dom";
import { Toggle } from "./Toggle";

const HeaderWrapper = styled.header`
	box-sizing: border-box;
	display: flex;
	height: 60px;
	width: 100%;
	padding: 0 16px;
	position: fixed;
	top: 0;
	background-image: linear-gradient(
		to right,
		${(props) => props.theme.primaryColor},
		${(props) => props.theme.secondaryColor}
	);
	border-bottom: 3px solid #fdd54f;
`;

const Menu = styled.nav`
	display: ${(props) => (props.open ? "block" : "none")};
	font-family: "Open Sans";
	position: absolute;
	width: 100%;
	top: 60px;
	left: 0;
	padding: 8px;
	box-sizing: border-box;
	border-bottom: 3px solid ${(props) => props.theme.secondaryColor};
	background: ${(props) => props.theme.bodyBackgroundColor};

	@media (min-width: 768px) {
		display: flex;
		margin: auto 0 auto auto;
		background: none;
		position: relative;
		top: initial;
		left: initial;
		width: initial;
		border-bottom: none;
	}
`;

const Link = ({ isActive, children, ...props }) => {
	return <ReactRouterDomLink {...props}>{children}</ReactRouterDomLink>;
};

const StyledLink = styled(Link)`
	box-sizing: border-box;
	display: block;
	padding: 4px 8px;
	margin: 0 auto;
	text-align: center;
	color: ${(props) => props.theme.bodyFontColor};
	font-weight: ${(props) => (props.isActive ? "bold" : "normal")};
`;

const MobileMenuIcon = styled.div`
	margin: auto 0 auto auto;
	width: 25px;
	min-width: 25px;
	padding: 5px;

	> div {
		height: 3px;
		background: ${(props) => props.theme.bodyFontColor};
		margin: 5px 0;
		width: 100%;
	}

	@media (min-width: 768px) {
		display: none;
	}
`;

export default function Header() {
	const { pathname } = useLocation();
	const [menuOpen, setMenuOpen] = useState(false);
	const { id, setTheme } = useContext(ThemeContext);

	return (
		<HeaderWrapper>
			<MobileMenuIcon onClick={() => setMenuOpen(!menuOpen)}>
				<div />
				<div />
				<div />
			</MobileMenuIcon>
			<Menu open={menuOpen}>
				<StyledLink to="/" isActive={pathname === "/"}>
					Home
				</StyledLink>
				<StyledLink to="/login" isActive={pathname === "/login"}>
					LogIn
				</StyledLink>
				<Toggle isActive={id === "dark"} onToggle={setTheme} />
			</Menu>
		</HeaderWrapper>
	);
}