그래도..! 기록을 남겨 두려고 한다.
npm install styled-component
npm install @types/styled-components
// styles/styled.d.ts
// theme 의 type을 지정 해 준다.
import "styled-components";
import { Theme } from "./theme";
declare module "styled-components" {
export interface DefaultTheme extends Theme {
colors: {
grey: string;
lightgrey: string;
darkGrey: string;
black: string;
white: string;
darkWhite: string;
indigo: string;
...
}
}
// styles/theme.ts
import media from "./media"; // 뒤에서 추가 해 줄 media
const colors = {
grey: "#6c757f",
lightgrey: "#606060",
darkGrey: "#343638",
black: "#222222",
white: "#ffffff",
darkWhite: "#d5d5d5",
indigo: "#172d4c",
...
};
export const myTheme = {
colors,
media, // media 도 추가
}
export type Theme = typeof myTheme;
styled-reset 패키지를 설치 하면 global reset 할 수 있다.
npm i styled-reset
물론 선택적인 요소다.
// styles/global-styles.ts
// global style 을 작성 해 주면 된다.
import { createGlobalStyle } from "styled-components";
export const GlobalStyle = createGlobalStyle`
${reset}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
line-height: 1.5;
}
html {
font-size: 62.5%;
color: #222222;
}
ul {
list-style: none;
margin: 0;
}
...
`;
// 위 처럼 할 수도 있고 당연하게도 global 에서 theme 에서 뿌린 스타일을 가져다 쓸 수도 있다.
// 물론 global이 themeprovider 안으로 들어와야 한다.
export const GlobalStyle = createGlobalStyle`
${reset}
* {
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
${({ theme }) => {
return css`
body {
font-family: ${theme.fonts.family};
font-size: ${theme.fonts.size.small};
line-height: 1.4;
}
h1 {
font-size: ${theme.fonts.size.large};
font-weight: ${theme.fonts.weight.bold};
color: ${theme.colors.black};
margin: 1.6rem;
}
...
...
`;
}}
`;
// index.tsx
// 원하는 최상위 root 에 global style을 얹어준다.
// 또한 위에서 다룬 theme 을 ThemeProvider 를 통해 전역에 뿌린다.
import { GlobalStyle } from "./styles/global-style";
ReactDOM.render(
<React.StrictMode>
// theme 아래 넣거나... 위에 넣거나...
<GlobalStyle />
<ThemeProvider theme={myTheme}>
<App />
</ThemeProvider>
</React.StrictMode>,
document.getElementById("root")
);
// styles/media.ts
import { css, CSSProp } from "styled-components";
interface MediaQueryProps {
tablet: number;
laptop: number;
desktop: number;
}
const sizes: MediaQueryProps = {
tablet: 768,
laptop: 992,
desktop: 2560,
};
type BackQuoteArgs = string[];
const media = {
tablet: (
literals: TemplateStringsArray,
...args: BackQuoteArgs
): CSSProp =>
css`
@media only screen and (max-width: ${sizes.tablet_max}px) {
${css(literals, ...args)}
}
`,
laptop: (literals: TemplateStringsArray, ...args: BackQuoteArgs): CSSProp =>
css`
@media only screen and (max-width: ${sizes.laptop}px) {
${css(literals, ...args)}
}
`,
desktop: (literals: TemplateStringsArray, ...args: BackQuoteArgs): CSSProp =>
css`
@media only screen and (max-width: ${sizes.desktop}px) {
${css(literals, ...args)}
}
`,
} as Record<
keyof typeof sizes,
(literals: TemplateStringsArray, ...args: BackQuoteArgs) => CSSProp
>;
export default media;
Record는 두개의 generic type 을 받을 수 있다.
type Record<K extends keyof any, T> = { [P in K]: T; };
프로퍼티 key 값을 K 타입으로, value 를 T 타입으로 만들어 준다.
Record stackoverflow
1) 기본
import styled, { css } from "styled-components";
const container = styled.div`
width: 100%;
${({ theme }) => {
return css`
color: ${theme.colors.darkGrey};
`;
}}
`;
2) 하나의 prop
const ContentTitle = styled.a<{ isUnderLine?: boolean }>`
&:hover {
text-decoration: ${(props) => (props.isUnderLine ? "underline" : "none")};
}
`;
3) media query와 다수의 props
interface NavbarDropDownProps {
readonly isToggle: boolean;
readonly isHover: boolean;
}
const NavbarDropDown = styled.div<NavbarDropDownProps>`
${({ isToggle, isHover, theme }) => theme.media.laptop`
height: ${ isToggle ? "100%" : "0%" };
transition: ${ isHover ? "height 0.35s ease-out" : "none" };
`}
`;