Theming
Create a declarations file
디자인 시스템의 근간을 마련하는데 활용. 잘 정의하면 다크 모드 등에 대응하기 쉬움. 눈에 보이는 단편적인 정보를 넘어서, “의미”에 집중할 수 있게 됨.
// Set Default Theme
const defaultTheme = {
colors: {
background: '#FFF',
text: '#000',
primary: '#F00',
secondary: '#00F',
},
};
export default defaultTheme;
// Theme Type Define
import defaultTheme from "./defaultTheme";
type Theme = typeof defaultTheme
export default Theme;
`typeof를 이용하여 type을 추출`
// Set Dark Theme
import Theme from "./Theme";
const darkTheme : Theme = {
colors: {
background: '#FFF',
text: '#000',
primary: '#F00',
secondary: '#00F',
},
};
export default darkTheme;
// App.tsx
import { ThemeProvider } from 'styled-components';
import { Reset } from 'styled-reset';
import defaultTheme from './styles/defaultTheme';
import GlobalStyle from './styles/GlobalStyle';
export default function App() {
return (
<ThemeProvider theme={defaultTheme}>
<Reset />
<GlobalStyle />
<Greeting />
</ThemeProvider>
);
}
//props.theme 사용
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
background: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};
}
a {
color: ${(props) => props.theme.colors.text};
}
button,
input,
select,
textarea {
background: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};
}
`;
export default GlobalStyle;
//styled.d.ts
import 'styled-components';
declare module 'styled-components' {
export interface DefaultTheme extends Theme {
colors: {
background: string;
text: string;
primary: string;
secondary: string;
}
}
}
타입을 정의하고 defaultTheme을 맞추는 게 불편하니, 반대로 defaultTheme에서 타입을 추출
import defaultTheme from './defaultTheme';
type Theme = typeof defaultTheme;
export default Theme;
// 위에서 typeof를 통해 추출한 타입을 styled.d.ts에 적용
import 'styled-components';
import Theme from './Theme';
declare module 'styled-components' {
export interface DefaultTheme extends Theme {}
}
다크 모드 적용
import { useDarkMode } from 'usehooks-ts';
import { ThemeProvider } from 'styled-components';
import { Reset } from 'styled-reset';
import defaultTheme from './styles/defaultTheme';
import darkTheme from './styles/darkTheme';
import GlobalStyle from './styles/GlobalStyle';
import Greeting from './components/Greeting';
import Button from './components/Button';
export default function App() {
const { isDarkMode, toggle } = useDarkMode();
const theme = isDarkMode ? darkTheme : defaultTheme;
return (
<ThemeProvider theme={theme}>
<Reset />
<GlobalStyle />
<Greeting />
<Button onClick={toggle}>
Dark Theme Toggle
</Button>
</ThemeProvider>
);
}
Jest 테스트 쪽에서 “window.matchMedia” 문제 발생.
Mocking methods which are not implemented in JSDOM
src/setupTests.ts
파일에 공식 문서에 나온 코드를 넣으면 해결된다.
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
참고
Last updated