styled-components의 공식문서를 보면 테마 구성을 위한 요소로 ThemeProvider 제공
import styled, { ThemeProvider } from 'styled-components'
const Box = styled.div`
font-size: 1em;
color: ${props => props.theme.color};
`
// 방식2
const theme = {
color: "mediumseagreen",
}
render(
<ThemeProvider theme={{ color: 'mediumseagreen' }}> // 방식1
<ThemeProvider theme={theme}> // 방식2
<Box>I'm mediumseagreen!</Box>
</ThemeProvider>
)
ThemeProvider 의 props로 theme를 전달해주면 그 아래에 있는 모든 component들은 styled 를 사용해 스타일을 정의할 때 이 theme 값을 사용할 수 있다.
theme.js
import styled from "styled-components";
// 반응형 디자인을 위한 픽셀 컨버팅 함수
const pixelToRem = (size) => `${size / 16}rem`;
// font size를 객체로 반환해주자.
const fontSizes = {
title: pixelToRem(60),
subtitle: pixelToRem(30),
paragraph: pixelToRem(18),
};
// 자주 사용하는 색을 객체로 만들자.
const colors = {
black: "#000000",
grey: "#999999",
green: "#3cb46e",
blue: "#000080",
};
// 자주 사용하는 스타일 속성을 theme으로 만들어보자.
const common = {
flexCenter: `
display: flex;
justify-contents: center;
align-items: center;
`,
flexCenterColumn: `
display: flex;
flex-direction: column;
justify-contents: center;
align-items: center;
`,
};
// theme 객체에 감싸서 반환한다.
const theme = {
fontSizes,
colors,
common,
};
export default theme;
App.js
import React from "react";
import styled, { ThemeProvider } from "styled-components";
import theme from "./theme";
const Container = styled.div`
width: 100vw;
height: 100vh;
${({ theme }) => theme.common.flexCenterColumn};
`;
const Title = styled.h1`
font-size: ${({ theme }) => theme.fontSizes.title};
color: ${({ theme }) => theme.colors.grey};
`;
const Subtitle = styled.h2`
font-size: ${({ theme }) => theme.fontSizes.subtitle};
color: ${({ theme }) => theme.colors.green};
`;
const Paragraph = styled.p`
font-size: ${({ theme }) => theme.fontSizes.Paragraph};
color: ${({ theme }) => theme.colors.blue};
`;
const App = () => {
return (
<div>
<ThemeProvider theme={theme}>
<Container>
<Title>Hello</Title>
<Subtitle>Welcome to styled-component's world</Subtitle>
<Paragraph>ThemeProvider에 대해서 배워볼까요?</Paragraph>
</Container>
</ThemeProvider>
</div>
);
};
export default ThemeProviderPrac;
===============================================
다크모드 구현하기
theme.js
export const lightTheme = {
bgColor: '#fff',
textColor: '#222',
accentColor: '#12cbef',
};
export const darkTheme = {
bgColor: '#282c35',
textColor: '#fff',
accentColor: '#ffe246',
};
export const theme = {
lightTheme,
darkTheme,
};
export default theme;
App.js
import React from 'react';
import styled, { createGlobalStyle, ThemeProvider } from 'styled-components';
import { darkTheme, lightTheme } from './theme';
const GlobalStyle = createGlobalStyle`
body {
background-color: ${(props) => props.theme.bgColor};
color:${(props) => props.theme.textColor}
}
`;
function App() {
const [isDarkMode, setIsDarkMode] = useState(false);
// 2. 버튼클릭으로 isDarkMode true<->false
const toggleDarkMode = () => {
setIsDarkMode((prev) => !prev);
};
return (
<>// 3. 변화한 isDarkMode 값에 따라 theme 결정
<ThemeProvider theme={isDarkMode ? darkTheme : lightTheme}>
<GlobalStyle />
<Home isDarkMode={isDarkMode} toggleDarkMode={toggleDarkMode} />
</ThemeProvider>
</>
);
}
export default App;
Home.js
import React from 'react';
import styled from 'styled-components';
import { BsFillSunFill, BsFillMoonFill } from 'react-icons/bs';
...
// 4. theme 적용
const Header = styled.div`
box-shadow: ${(props) => props.theme.boxShadow};
border-bottom: ${(props) => props.theme.border};
`;
function Home({ isDarkMode, toggleDarkMode }) {
return (
<>
<header>
<HeaderLogo className="header__logo">HEO.D.K</HeaderLogo>
// 1. 버튼클릭
<button
type="button"
onClick={toggleDarkMode}
isDarkMode={isDarkMode}
>
// 5. 변화한 isDarkMode 값에 따라 아이콘 결정
{isDarkMode ? <BsFillSunFill /> : <BsFillMoonFill />}
</button>
</header>
<article>
<p>다크모드/라이트 모드</p>
</article>
</>
);
}
export default Home;
===============================================
추가할 내용 : 로컬스토리지 사용해서 이전 다크/라이트모드 저장