이 포스트는 Udemy 사이트에 올라 온 Tom Phillips의 "React styled-components v5 (2021 edition)" 강의를 듣고 정리한 것입니다.
🔗링크
https://www.udemy.com/course/react-styled-components/
일단 토글 버튼 만들기🌀
👩💻 전체 코드
import styled from "styled-components";
const ToggleWrapper = styled.div`
width: 50px;
min-width: 50px;
height: 25px;
border-radius: 25px;
border: 1px solid #666;
margin: auto;
display: flex;
background-image: linear-gradient(
to bottom,
${(props) => props.theme.primaryColor},
${(props) => props.theme.secondaryColor}
);
`;
const Notch = styled.div`
height: 21px;
width: 21px;
border: 1px solid #666;
margin-top: 1px;
background: white;
border-radius: 50%;
transform: translate(${(props) => (props.isActive ? "26px" : "1px")});
transition: transform 0.1s linear;
`;
export function Toggle({ isActive }) {
return (
<ToggleWrapper>
<Notch isActive={isActive} />
</ToggleWrapper>
);
}
💻 현재 상태
theme이 커질테니 themes 폴더를 따로 만들어서 분리해내기 🌀
📂 src > themes > light.js
const theme = {
id: "light",
primaryColor: "#f8049c",
secondaryColor: " #fdd54f",
};
export default theme;
📂 src > themes > dark.js
const theme = {
id: "dark",
primaryColor: "black",
secondaryColor: " midnightblue",
};
export default theme;
📂 src > components > App.js
import { useState } from "react";
import LogIn from "components/pages/LogIn";
import Home from "components/pages/Home";
import { createGlobalStyle, ThemeProvider } from "styled-components";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import LightTheme from "themes/light";
import DarkTheme from "themes/dark";
const GlobalStyle = createGlobalStyle`
body{
background-color: white;
color:black;
min-height:100vh;
margin:0;
font-family: 'Kaushan Script', cursive;
}
`;
function App() {
const [theme, setTheme] = useState(LightTheme);
return (
<ThemeProvider
theme={{
...theme,
setTheme: () => {
setTheme((theme) =>
theme.id === "light" ? DarkTheme : LightTheme
);
},
}}
>
<GlobalStyle />
<BrowserRouter>
<Switch>
<Route path="/login">
<LogIn />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</BrowserRouter>
</ThemeProvider>
);
}
export default App;
본격적으로 토글 기능 만들기 🌀
📂 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: white;
@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: black;
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: black;
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>
);
}
📂 src > components > common > Toggle.js
import styled from "styled-components";
const ToggleWrapper = styled.div`
width: 50px;
min-width: 50px;
height: 25px;
border-radius: 25px;
border: 1px solid #666;
margin: auto;
display: flex;
background-image: linear-gradient(
to bottom,
${(props) => props.theme.primaryColor},
${(props) => props.theme.secondaryColor}
);
`;
const Notch = styled.div`
height: 21px;
width: 21px;
border: 1px solid #666;
margin-top: 1px;
background: white;
border-radius: 50%;
transform: translate(${(props) => (props.isActive ? "26px" : "1px")});
transition: transform 0.1s linear;
`;
export function Toggle({ isActive, onToggle }) {
return (
<ToggleWrapper onClick={onToggle}>
<Notch isActive={isActive} />
</ToggleWrapper>
);
}
'styled-components' 카테고리의 다른 글
ThemeProvider 사용하기 (3) - 토글해서 GlobalStyle 바꾸기 (0) | 2021.05.18 |
---|---|
ThemeProvider 사용하기(1) - 기본 문법 (0) | 2021.05.18 |
styled-components로 Spinner 만들기 (feat. keyframes helper) (0) | 2021.05.18 |
번외) react-router-dom의 Link를 styled-components로 꾸미기(feat.useLocation) (하지만 난 NavLink가 좋다) (0) | 2021.05.17 |
번외) react-router-dom (0) | 2021.05.17 |