티스토리 뷰
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
https://velog.io/@hwang-eunji/styled-component-typescript
https://blog.agney.dev/styled-components-&-typescript/
'Frontend > TypeScript' 카테고리의 다른 글
[Typescript] React.FC를 사용하지 않아야 하는 이유(+ 리액트 컴포넌트 네임 스페이스 패턴) (0) | 2023.03.26 |
---|---|
[TypeScript | hooks] useRef 사용법( ref 객체 타입) (0) | 2023.03.05 |
[TypeScript] 타입스크립트 자동완성과 DT, TS (0) | 2023.01.14 |
[TypeScript] Promise와 Awaited 분석 (0) | 2023.01.09 |
[TypeScript] Required, Record, NonNullable 타입 (0) | 2023.01.02 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- reactAPI
- 항해99프론트
- nvm 설치순서
- 타입스크립트 DT
- ~ ^
- float 레이아웃
- 원티드 3월 프론트엔드 챌린지
- 형제 요소 선택자
- grid flex
- 틸드와 캐럿
- 부트캠프항해
- && 셸 명령어
- aspect-ratio
- 타입스크립트 장점
- 원티드 프리온보딩 FE 챌린지
- Prittier
- 원티드 프리온보딩 프론트엔드 챌린지 3일차
- nvm경로 오류
- 항해99프론트후기
- getStaticPaths
- 원티드 FE 프리온보딩 챌린지
- 프리렌더링확인법
- fs모듈 넥스트
- is()
- 항해99추천비추천
- D 플래그
- tilde caret
- getServerSideProps
- text input pattern
- 프리온보딩 프론트엔드 챌린지 3월
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함