단순히 페이지에서 다크모드를 구현하는 것은 굉장히 쉽다. 하지만 프론트엔드에게는 재사용성을 고려한 Component를 만드는 것이 굉장히 중요하지 않은가?😎
Toggle Component를 TypeScript환경에서 만들어보았다.
대부분 구글링으로 정보를 찾아본 것으로 이것이 정석이 아닐 수 있다.
Toggle버튼은
가상요소(::before, ::after)
를 활용했고,
ThemeProvider와 useState로 Props
로 테마가 변하도록 구현해보았다.
DarkmodeBtn.tsx
파일을 만든다.
input
을 만들고 type="checkbox"
로 만들고, styled-component로 CSS를 넣어주었다. 체크박스 자체는 뒤에 가리도록 트릭을 사용했다.
const Checkbox = styled.input`
width: 5rem;
height: 2rem;
background: white;
border-radius: 2em;
`
function DarkmodeBtn() {
return (
<Container>
<CheckboxLabel>Theme</CheckboxLabel>
<Checkbox type="checkbox" id="toggle" />
</Container>
);
}
export default DarkmodeBtn;
const Checkbox = styled.input`
width: 5rem;
height: 2rem;
background: white;
border-radius: 2em;
&::before {
content: "";
text-align: center;
line-height: 50px;
width: 100px;
height: 50px;
display: block;
position: absolute;
border-radius: 30px;
background-color: white;
box-shadow: 0 0 16px 3px rgba(0 0 0 / 15%);
transition: all 0.2s ease-in;
cursor: pointer;
}
&::after {
content: "";
display: block;
position: relative;
width: 40px;
height: 40px;
top: 5px;
left: 5px;
border-radius: 50%;
background: #2f3640;
transition: all 0.2s ease-in;
}
&:checked {
&::before {
background-color: #585d6d;
}
&::after {
background-color: white;
left: calc(100% - 25px);
}
}
`
그럼 이러한 결과물이 나올 것이다. 색상이나 크기는 원하는대로 정해주면 된다.
App.tsx
에서 ThemeProvider
를 통해 테마를 결정해주고, useState
상태 정해주는 "ToggleTheme함수"를 Props
로 전달해주자.import { ThemeProvider, createGlobalStyle } from "styled-components";
function App() {
const [theme, setTheme] = useState<boolean>(false);
// 타입스크립트에게 useState는 boolean이라는 것을 알려준다.
const ToggleTheme = () => {
setTheme((prev) => !prev);
};
return (
<>
<ThemeProvider theme={theme ? darktheme : lighttheme}>
<GlobalStyle />
<DarkmodeBtn toggleTheme={ToggleTheme} />
//
<Router />
</ThemeProvider>
</>
);
}
export default App;
DarkmodeBtn.tsx
로 돌아와서interface IToggleProps {
toggleTheme: () => void;
}
// Props 타입은 함수라는걸 알려줌.
function DarkmodeBtn({ toggleTheme }: IToggleProps) {
return (
<Container>
<CheckboxLabel></CheckboxLabel>
<Checkbox type="checkbox" id="toggle" onClick={() => toggleTheme()} />
</Container>
);
}
checkbox가 체크되면 lighttheme가 실행이 되고, 체크가 해제되면 darktheme가 실행된다. 거꾸로 만들었어야했는데...ㅋㅋ
아직 초보자
여서, 검색하면서 만드는데 5시간 정도 걸렸다. 아마 방법이 이상할 수도 있다고 생각한다. 이상한 곳이 있으면 문의바란다.