# Dark Mode

### 1. Project Setup

typescript 기반으로 프로젝트를 세팅하고 styled-component 를 설치합니다.

```javascript
$ npx create-react-app theme-exam --template typescript
$ cd theme-exam 
$ npm i -S styled-components
```

### 2. Theme 스타일 추가

**Dark, Light** 두 가지 테마의 스타일을 추가합니다.

```javascript
// src/interfaces/theme.ts

export interface Theme {
    color: Color
}

export interface Color {
    [key: string]: string
}
```

**Dark Style**

```javascript
// src/themes/dark.ts

import { Theme } from '../interfaces/theme'

const Dark: Theme = {
    color: {
        background: "#202020",
        buttonBackground: '#3a3a3a',
        buttonColor: '#fed356'
    }
}

export default Dark
```

**Light Style**

```javascript
// src/themes/light.ts 

import { Theme } from '../interfaces/theme'

const light: Theme = {
    color: {
        background: "#fff",
        buttonBackground: '#fff',
        buttonColor: '#2161f2'
    }
}

export default light
```

### 3. ThemeProvider

Dark, Light 두 가지 테마의 스타일을 다루기 위해서 styled-components 의 **ThemeProvider** 를 이용합니다.\
state 에 따라 다른 theme 에 대한 스타일을 넣어줍니다.

```javascript
// src/App.tsx

import React, { useState } from 'react';
import styled, { ThemeProvider } from 'styled-components'
import light from './themes/light'
import dark from './themes/dark'

const App: React.FC = () => {
  const [isDark, setIsDark] = useState<boolean>(false)

  return (
    <ThemeProvider theme={isDark ? dark : light}>
    </ThemeProvider>
  );
}

export default App;
```

### 4. Theme 적용

ThemeProvider 에 theme props 을 이용하면 모든 styled-components 를 사용하는 곳에서 theme props 를 주입받을 수 있습니다.&#x20;

```javascript
// src/App.tsx

import React, { useState } from 'react';
import styled, { ThemeProvider } from 'styled-components'
import GlobalStyles from './global-styles'
import light from './themes/light'
import dark from './themes/dark'

const Container = styled.div`
  width: 100%;
  height: 100vh;
  display: flex;
  flex-flow: column;
  align-items: center;
  justify-content: center;
  background-color: ${({ theme: { color: { background } } }) => background};
`

const Button = styled.button`
  margin-top: 20px;
  padding: 5px 20px;
  border-radius: 15px;
  
  ${({ theme: { color: { buttonBackground, buttonColor } } }) => `
    background-color: ${buttonBackground};
    color: ${buttonColor};
    border: 1px solid ${buttonColor}
  `};
`

const App: React.FC = () => {
  const [isDark, setIsDark] = useState<boolean>(false)

  return (
    <ThemeProvider theme={isDark ? dark : light}>
      <Container>
        <Button onClick={() => setIsDark(!isDark)}>{isDark ? 'Light' : 'Dark'}</Button>
      </Container>
    </ThemeProvider>
  );
}

export default App;
```

![](/files/-LwgQadtmsDcuwp0f7QX)

### 5. SVG 추가

태양과 달 svg 를 추가합니다.

```markup
//src/assets/moon.svg

<svg width="128" height="128" style="enable-background:new 0 0 128 128;">
  <path d="M105.87,14.99c-3.74-3.39-7.91-6.38-12.42-8.89c-0.87-0.49-2-0.35-2.71,0.33 c-0.71,0.68-0.83,1.73-0.29,2.53c15.63,22.93,12.29,52.52-8.11,71.97c-11.9,11.35-27.85,17.6-44.91,17.6 c-11.39,0-22.54-2.86-32.24-8.27c-0.87-0.49-2-0.36-2.71,0.33c-0.71,0.68-0.83,1.72-0.28,2.53c2.81,4.12,6.12,7.93,9.86,11.32 c12.61,11.45,29.27,17.76,46.9,17.76c18.27,0,35.34-6.7,48.09-18.86c12.53-11.94,19.31-27.71,19.09-44.4 C125.92,42.25,118.72,26.64,105.87,14.99z" style="fill:#FCC21B;"/>
</svg>
```

```markup
//src/assets/sun.svg

<svg width="128" height="128" style="enable-background:new 0 0 128 128;">
    <g>
        <path d="M64,30.34c-18.59,0-33.66,15.07-33.66,33.65c0,18.59,15.07,33.66,33.66,33.66 c18.59,0,33.66-15.07,33.66-33.66C97.66,45.41,82.59,30.34,64,30.34z" style="fill:#FCC21B;" />
        <path d="M56.76,24.21L56.76,24.21h14.49c0.67,0,1.29-0.33,1.68-0.88c0.38-0.54,0.47-1.25,0.24-1.88 L65.92,1.83c-0.3-0.81-1.06-1.34-1.92-1.34s-1.62,0.54-1.92,1.34l-7.25,19.63c-0.23,0.63-0.14,1.33,0.24,1.88 C55.46,23.89,56.09,24.21,56.76,24.21z" style="fill:#FCC21B;" />
        <path d="M97.26,40.99c0.38,0.39,0.91,0.6,1.44,0.6c0.12,0,0.24-0.01,0.36-0.03c0.66-0.12,1.21-0.55,1.5-1.16 l8.76-19.01c0.36-0.78,0.19-1.69-0.41-2.3c-0.61-0.61-1.53-0.77-2.31-0.42L87.6,27.44c-0.61,0.28-1.04,0.84-1.16,1.5 c-0.12,0.66,0.1,1.33,0.56,1.81L97.26,40.99z" style="fill:#FCC21B;" />
        <path d="M126.18,62.08l-19.64-7.24c-0.63-0.23-1.33-0.14-1.88,0.24c-0.55,0.38-0.87,1-0.87,1.67l0.01,14.49 c0,0.67,0.33,1.3,0.88,1.68c0.35,0.23,0.76,0.36,1.17,0.36c0.24,0,0.48-0.04,0.71-0.13l19.64-7.24c0.8-0.29,1.34-1.06,1.34-1.93 C127.52,63.14,126.99,62.38,126.18,62.08z" style="fill:#FCC21B;" />
        <path d="M100.56,87.6c-0.28-0.61-0.84-1.04-1.5-1.16c-0.66-0.11-1.34,0.1-1.8,0.57L87.01,97.26 c-0.47,0.47-0.69,1.15-0.57,1.81c0.12,0.65,0.55,1.22,1.16,1.5l19.01,8.76c0.27,0.13,0.56,0.18,0.86,0.18 c0.53,0,1.05-0.21,1.44-0.6c0.61-0.61,0.77-1.52,0.41-2.3L100.56,87.6z" style="fill:#FCC21B;" />
        <path d="M71.24,103.78L71.24,103.78l-14.49,0.01c-0.67,0-1.29,0.33-1.67,0.88 c-0.38,0.55-0.47,1.25-0.25,1.87l7.25,19.64c0.3,0.8,1.06,1.34,1.92,1.34s1.62-0.54,1.92-1.34l7.25-19.64 c0.23-0.63,0.14-1.33-0.24-1.88C72.54,104.11,71.92,103.78,71.24,103.78z" style="fill:#FCC21B;" />
        <path d="M30.74,87.01c-0.47-0.47-1.14-0.68-1.8-0.57c-0.66,0.12-1.22,0.55-1.5,1.16l-8.76,19.01 c-0.36,0.78-0.19,1.7,0.42,2.3c0.39,0.39,0.91,0.6,1.44,0.6c0.29,0,0.58-0.06,0.86-0.19l19.01-8.77c0.61-0.28,1.04-0.84,1.16-1.5 c0.12-0.66-0.1-1.33-0.57-1.8L30.74,87.01z" style="fill:#FCC21B;" />
        <path d="M22.17,73.29c0.41,0,0.82-0.13,1.17-0.37c0.55-0.38,0.88-1.01,0.88-1.68l-0.01-14.49 c0-0.67-0.33-1.29-0.88-1.68c-0.55-0.38-1.25-0.47-1.87-0.24L1.82,62.08c-0.8,0.29-1.34,1.06-1.34,1.92c0,0.85,0.53,1.62,1.34,1.92 l19.65,7.24C21.7,73.25,21.93,73.29,22.17,73.29z" style="fill:#FCC21B;" />
        <path d="M27.45,40.4c0.28,0.61,0.84,1.04,1.5,1.16c0.12,0.02,0.24,0.03,0.36,0.03c0.54,0,1.06-0.21,1.45-0.6 L41,30.74c0.47-0.48,0.68-1.15,0.56-1.81c-0.12-0.65-0.55-1.21-1.16-1.49l-19.02-8.76c-0.78-0.36-1.69-0.19-2.3,0.42 c-0.61,0.61-0.77,1.52-0.41,2.3L27.45,40.4z" style="fill:#FCC21B;" />
    </g>
</svg>
```

```javascript
// src/App.tsx

import React, { useState } from 'react';
import styled, { ThemeProvider } from 'styled-components'
import GlobalStyles from './global-styles'
import light from './themes/light'
import dark from './themes/dark'
import { ReactComponent as Sun } from './assets/sun.svg';
import { ReactComponent as Moon } from './assets/moon.svg';

const Container = styled.div`
  width: 100%;
  height: 100vh;
  display: flex;
  flex-flow: column;
  align-items: center;
  justify-content: center;
  background-color: ${({ theme: { color: { background } } }) => background};
`

const Button = styled.button`
  margin-top: 20px;
  padding: 5px 20px;
  border-radius: 15px;
  
  ${({ theme: { color: { buttonBackground, buttonColor } } }) => `
    background-color: ${buttonBackground};
    color: ${buttonColor};
    border: 1px solid ${buttonColor}
  `};
`

const App: React.FC = () => {
  const [isDark, setIsDark] = useState<boolean>(false)

  return (
    <ThemeProvider theme={isDark ? dark : light}>
      <GlobalStyles />
      <Container>
        {isDark ? <Sun /> : <Moon />}
        <Button onClick={() => setIsDark(!isDark)}>{isDark ? 'Light' : 'Dark'}</Button>
      </Container>
    </ThemeProvider>
  );
}

export default App;
```

![](/files/-LwgRKjF6HZThWyKyE4x)


---

# 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://simplereact.gitbook.io/simplereact/dark-mode.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.
