styled components 에서 반응형 디자인을 간편하게 구현하는 방법!
Default Theme에 사용할 타입을 정한다.
// style.d.ts
// Default Theme 타입정의
interface Sizes {
mobile: number
tablet: number
desktop: number
}
type BackQuoteArgs = [TemplateStringsArray]
// 반응형 css Props을 만들어주는 object를 선언함
interface Media {
mobile: (...args: BackQuoteArgs) => CSSProp | undefined
tablet: (...args: BackQuoteArgs) => CSSProp | undefined
desktop: (...args: BackQuoteArgs) => CSSProp | undefined
}
interface Color {
default: string;
dark?: string;
light?: string
}
interface Colors {
[key: string]: Color
}
// styled-components DefaultTheme을 선언함
declare module 'styled-components' {
export interface DefaultTheme {
sizes: Sizes
media: Media,
borderRadius: string,
typography: string,
color: Colors,
}
}
const sizes:Sizes ={
mobile: 320,
tablet: 786,
desktop: 1024
}
const media:Media = {
mobile: (...args: BackQuoteArgs) => undefined,
tablet: (...args: BackQuoteArgs) => undefined,
desktop: (...args: BackQuoteArgs) => undefined
}
/*
*sizes key을 받아서 [moblie, tablet, desktop]
* reduce로 합쳐서 함수를 만들어주는 방법으로 재정의
* media 오브젝트를 초기값으로 주고
* label에 따라 min-width 를 바꾸고
* 입력받은 배열을 {안으로 넣음!}
*/
Object.keys(sizes).reduce((acc,label) => {
switch(label) {
case 'mobile' :
acc.mobile = (...args) => css`@media screen and (min-width: ${sizes.mobile}px){
${args}
}`
break;
case 'tablet' :
acc.tablet = (...args) => css`@media screen and (min-width: ${sizes.tablet}px){
${args}
}`
break;
case 'desktop' :
acc.desktop = (...args) => css`@media screen and (min-width: ${sizes.desktop}px){
${args}
}`
break;
}
return acc
},media)
export const 테마: DefaultTheme = {
sizes,
borderRadius: '4px',
media,
color: {
primary: {
default: '#12121'
},
secondary: {
default: '#31313'
}
}
// ... 중략
}
<ThemeProvider theme={테마} />
// components
import React from 'react';
import styled from s'styled-components'
const Rect = styled.div`
width: 50px;
${({theme: {media}) => media.desktop`
width: 100px
`}
${({theme: {media}) => media.tablet`
width: 80px
`}
`
styled components로 반응형 설계하는 여러방법 중 한가지를 토이프로젝트로 구현해봤다. 부트스트랩처럼 ㅣㄴㅇ