티스토리 뷰

 

TS + CRA 로 작업하면서 styled-component 를 쓰게됐다. CSS-in-JS 이기 때문에 props를 활용하기 좋다(조건부 스타일링). 하지만 하나의 컴포넌트에 props를 내려주는 식으로 진행하기 때문에 TS에서는 해당 props에 대한 정의가 필요하다. 
*CSS-in-JS는 스타일 정의를 CSS파일이 아닌 JS로 작성된 컴포넌트에 바로 삽입하는 스타일 기법

초기 세팅

yarn add styled-components @types/styled-components styled-normalize

 

📌 styled-normalize: 브라우저마다 다르게 보이는 css를 초기화

코드 분리

styled-components 를 사용할 때 테마/전역스타일 코드 분리 

styled-components의 타입을 지정하기 위한 styled.d.ts 파일을 추가로 생성

  • 스타일 테마 모음: src/styles/theme.ts
  • 스타일-타입정의 모음: src/styles/styled.d.ts
  • 전역-스타일 모음: src/styles/global-style.ts

styled.d.ts (global style type 작성)

styled-components 의 타입정의를 불러와 내가 사용할 신규 타입정의 추가 & 확장하기

// import original module declarations
import 'styled-components'

// and extend them!
declare module 'styled-components' {
  // 우리가 아는 타입지정을 여기서 다해주고 불러서 쓰기
  // 1. 인터페이스 지정
  export interface 인테페이스명 지정 {
    속성1 : 타입지정;
  }
  // 2. 타입 속성 지정
  export type // 타입 지정

  // ThemeProvider theme에 적용할 타입으로, theme의 속성과 동일하게 작성
  export interface DefaultTheme {
    dark: {
      mainBackground: string;
      // neutral color
      title: string;
      primaryText: string;
      secondaryText: string;
      disable: string;
      border: string;
      divider: string;
      background: string;
      tableHeader: string;
    };
    light: {
      mainBackground: string;
      // neutral color
      title: string;
      primaryText: string;
      secondaryText: string;
      disable: string;
      border: string;
      divider: string;
      background: string;
      tableHeader: string;
      // point-color
      // point-color
    };
    response: {};
  }
}

📌 defaultTheme 인터페이스는 node_modules/@types/styled-components/ts3.7/index.d.ts에 정의되어 있다.

해당 인터페이스를 확장하는 개념이다.

Parsing error: Only declares and type imports are allowed inside declare module

위와 같은 에러 메세지가 뜬다면 루트 디렉토리에 .eslintignore 에 /src/assets/styles/styled.d.ts 를 추가한다.

global style 작성

// src/assets/styles/global-styles.ts
import { createGlobalStyle } from "styled-components";
import { normalize } from "styled-normalize";

// 위에서 받은 `normalize`로 기본 css가 초기화 합니다.
const GlobalStyle = createGlobalStyle`
  ${normalize}

  html,
  body {
    overflow: hidden;
  }

  * {
    box-sizing: border-box;
  }
`;

export default GlobalStyle;

스타일 작성하기

1) 단일 props 사용시: styled.div<인터페이스명> 

//styled-components 1개 props 타입지정 
// styled.div<{프롭스명: 타입지정}>
const Warpper = styled.div<{isValid: boolean}>`
 color: ${(props) => (props.isValid ? "blue" : "red")}
`

2) 다수 props 사용시: interface 작성

: 인터페이스로 분리하여 타입지정하는 것 이외에 사용법은 동일하다. 

interface Wrapper extends 상속타입 {
 isActive: boolean;
 age: number;
 프롭스명: 타입지정;
}
// styled-components에 interface 타입 지정하기
const Wrapper = styled.div<Wrapper>`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
  background-color: ${(props) => (props.isActive ? 'red' : 'gray')};
`

3) 상속 컴포넌트에 타입 지정

3-1. interface 상속받기 

// 상속컴포넌트의 타입 상속받기
interface Container {
  isActive: boolean;
  age: number;
  프롭스명: 타입지정;
}

// 상속받은 컴포넌트에 타입 추가하기
const Container = styled(상속받을 컴포넌트명)<Container>`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
  background-color: ${(props) => (props.isActive ? 'red' : 'gray')};
`;

3-2. 단일 props 타입지정하기

// 기존 방식과 동일하게 사용
const Container = styled(상속받을 컴포넌트명)< { age : number } >`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
`;

// 위 방식에 문제가 있을경우 아래와 같이 사용.. 하나 복잡!
const Container = styled(({ age, ...parentProps }) => (
  <상속받을컴포명 {...parentProps} />
))<{
  age: number;
}>`
  color: ${(props) => (props.active ? 'red' : 'blue')};
`;
  • 상속 컴포넌트 명을 콜백함수로 전달
  • 매개변수는 신규 타입: age와, 부모의 타입: parentProps 을 전개 연산자(...parentProps)로 지정
  • 신규타입은 제네릭으로 기존과 동일하게 전달 

미디어 템플릿 적용

디바이스의 폭을 기준으로 나누어 작업(상황에 따라 높이 적용)

const customMediaQuery = (maxWidth: number):string => {
  // 최대폭을 입력하면. 문자열을 밷는다!
  return `@media (max-width: ${maxWidth}px)`;
}
// 각 디바이스에 따라 최대폭 값을 변수화
const media = {
  custom: customMediaQuery,
  desktop: customMediaQuery(922),
  tablet: customMediaQuery(768),
  phone: customMediaQuery(576),
};

const Content = styled.div`
  height: 3em;
  width: 3em;
  background: papayawhip;

  ${media.desktop} { 
    background: dodgerblue;
  }
  ${media.tablet} {
    background: mediumseagreen;
  }
  ${media.phone} {
    background: palevioletred;
  }
`;

${media.desktop} { color: red;} === @media (max-width: 922px) {color:red}

 

all ref: https://styled-components.com/docs/api#typescript

 

styled-components: API Reference

API Reference of styled-components

styled-components.com

https://velog.io/@hwang-eunji/styled-component-typescript

 

Styled-component #3 with typescript

오늘은 글로벌 스타일 적용하고, 스타일 컴포넌트에 타입 적용하는 방법을 해보겠돠.하루에 아조조~금씩🔨 야금야금🔨npm i styled-componentnpm i -D @types/styled-componentsstyled-components를 사용할때 보통

velog.io

https://blog.agney.dev/styled-components-&-typescript/

 

The Mindless - Boy with Silver Wings

Styled Components happens to be one of my favorite CSS in JS libraries all time and have been part of almost all of my ReactJS projects. As I’m transitioning most of my projects to include TypeScript, there are things I stumbled along, but there are thin

blog.agney.dev

 

댓글