# Styled-Components

## Styled-Components란

React에서 사용되는 CSS-in-JS 라이브러리

### Install

```bash
npm i styled-components
npm i -D @types/styled-components @swc/plugin-styled-components
```

#### `.swcrc`

> Babel Plugin을 SWC에서 쓸 수 있도록 포팅한 것도 함께 설치하자(SSR 지원 등을 위한 공식 권장사항).

```typescript
{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": true,
            "ssr": true
          }
        ]
      ]
    }
  }
}
```

### Usage

> HTML 요소 이름을 추가한 다음 백틱(\`) 기호로 감싼 영역에 CSS 코드를 작성하면 CSS 스타일이 반영된 React 컴포넌트를 만들어낸다.

```typescript
import styeld from 'styled-components'

const StyledH2 = styled.h2`
  color: #0066ff;
  font-size: 1.5rem;
`
```

### 동작 원리

백틱을 이용한 `Tagged Template literals` 문법을 사용하여 스타일을 생성한다.

#### **Tagged Template Literals 문법이란?**

[Template Literals(\`)](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) 과 함께 사용되는 함수로, 함수 앞에 백틱을 이용해 문자열과 ${}로 감싼 js 코드를 작성하면 해당 함수의 인자로 전달되어 호출된다.

* 첫 번째 인자로 \`\`(백틱)으로 묶인 문자 값의 배열이 전달된다.
* 두 번째 인자부터는  ${}(템플릿 스트링)으로 감싼 JS 표현식의 결과 값이 사용한 순서대로 전달된다.

```typescript
const result = styledTag`
 태그
 ${1 + 9}
 템플릿
 ${'불타는' + '청춘'}
 리터럴
 ${ true && 'return True'}
`

const styledTag = (strings, ...expressions) => {
  console.log(strings);
  // ["  태그  ","  템플릿  ","  리터럴  "]
  
  console.log(expressions);
  // "[10, '불타는 청춘', 'return True']  
}
```

아래 코드는 실제로 스타일드 컴포넌트의 내부 동작 코드가 아니고, 태그드 리터럴 템플릿을 어떻게 사용하는지에 대한 예시 코드이다.

스타일드 컴포넌트는 태그드 탬플릿 리터럴을 사용해서 스타일이 포함된 컴포넌트 객체를 만들고 렌더링 될 때 컴포넌트에 동적으로 생성된 클래스를 부여하고 해당 스타일을 \<style> 태그에 추가한다.

```javascript
styleTag('h1')`
  color: #0066ff;
  background: #fff;
`
// 위 아래는 같음
styleTag('h1')([
  color: #0066ff;
  background: #fff;
})

function styleTag(element) {
  const styleEl = document.createElement(element)
  
  return function(cssText) { // 함수를 반환하는 고차함수
    const cssStyles = cssText.toString().split(';');
    const cssKeyValues = cssStyles.map(style => style.trim().split(':');               cssKeyValues.forEach([key, value]) => {
      if (key && value) {
        styleEl.style[key] = value;
      }
    }
    return styleEl
  }
}
```

### 컴포넌트 커스텀

* 컴포넌트를 커스텀하는 것도 가능하다.&#x20;
* `styled`가 동적으로 클래스를 생성하기 떄문에 이 커스텀 클래스를 커스텀할 컴포넌트와 연결 해주어야 한다.
* 커스텀하는 컴포넌트는 className props를 추가하고 커스텀 할 요소에 지정해주어야 한다.\
  (보통은 가장 바깥에 걸어둠)

```typescript
const Button = styled(Component)`
  //...
`;

export defaulft Componet(className) {
  return <StyledComponent className={className} />
}
```

### props

> 조건부 스타일을 지정할 때 활용

```typescript
import styled, { css } from 'styled-components';

type ParagraphProps = {
  active?: boolean;
}

const Paragraph = styled.p<ParagraphProps>`
  color: ${(props) => (props.active ? '#F00' : '#888')};
  ${(props) => props.active && css`
    font-weight: bold;
  `}
`;

// 동일

const Paragraph = styled.p<ParagraphProps>`
  ${({ active }) => css`
    color: ${active ? '#f00' : '#888'}; 
    font-weight: ${active ? 'bold' : 'normal'
  `}
`;
```

### [attrs](https://styled-components.com/docs/basics#attaching-additional-props)

> 스타일드 컴포넌트에 추가 속성을 지정할 수 있는 props

기본 속성을 추가할 수 있음. 불필요하게 반복되는 속성을 처리할 때 유용한데, 버튼 등을 만들 때 적극 활용함.

```typescript
import styled from 'styled-components';

export const Button = styled.button.attrs({
  type: 'button',
})`
  border: 1px solid #888;
  background: transparent;
  cursor: pointer;
`;
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_road/week-8/styled-components.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
