0%

React cra 프로젝트에 ant 디자인 적용 및 dark테마 적용

들어가기

React의 CRA를 사용해서 프로젝트를 생성하고, ant 디자인을 적용하고, dark 테마를 적용하는 예제를 진행하겠다.

주요한 내용은 아래 블로그 글을 참고했으며, 자세한 내용은 아래 링크를 참고하길 바란다.

https://jfelix.info/blog/dynamic-themes-in-ant-design-how-to-change-between-light-and-dark-theme

본인은 less 및 gulp에 대한 이해가 없다.

이 글의 목적은 대략적 맥락(ant 디자인의 동적 테마 변경에 관련)과 빠른 프로젝트 구축을 위한 글이다.

주의사항

node 버전 14이상에서 예제를 진행해야 한다.

본인은 webstorm 개발툴을 사용했다.(vscode를 사용해도 전혀 문제 없을 것이다.)

리액트 프로젝트 생성 및 Ant 디자인 적용

아래 명령으로 리액트 프로젝트를 생성한다.

1
npx create-react-app antd-swith-theme

react-cra-antd-darktheme%20efa153b7e9b7443c9b838c30ff14e9e1/Untitled.png

아래 명령으로 ant디자인과 ant디자인에 사용하는 icon 을 설치한다.

1
2
npm i atnd
npm install --save @ant-design/icons

react-cra-antd-darktheme%20efa153b7e9b7443c9b838c30ff14e9e1/Untitled%201.png

위 처럼 설치된 내용을 확인 할 수 있다.

ant 디자인을 사용하기 위한 준비는 완료 되었다.

Ant 디자인의 light, dark테마 switch 기능 추가하기

프로젝트의 src 폴더 아래 themes 폴더를 생성하고 그 아래 dark-theme.less, light-thmes.less 파일을 생성한다.

react-cra-antd-darktheme%20efa153b7e9b7443c9b838c30ff14e9e1/Untitled%202.png

dark-theme.less 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@import "~antd/lib/style/color/colorPalette.less";
@import "~antd/dist/antd.less";
@import "~antd/lib/style/themes/dark.less";

// These are shared variables that can be extracted to their own file
@primary-color: #00adb5;
@border-radius-base: 4px;

@component-background: #303030;
@body-background: #303030;
@popover-background: #303030;
@border-color-base: #6f6c6c;
@border-color-split: #424242;
@table-header-sort-active-bg: #424242;
@card-skeleton-bg: #424242;
@skeleton-color: #424242;
@table-header-sort-active-bg: #424242;

light-theme.less파일

1
2
3
4
5
6
7
@import "~antd/lib/style/color/colorPalette.less";
@import "~antd/dist/antd.less";
@import "~antd/lib/style/themes/default.less";

// These are shared variables that can be extracted to their own file
@primary-color: #00adb5;
@border-radius-base: 4px;

여기서 잠깐 위 두 파일을 기준으로 ant 디자인의 테마 변경을 위한 맥락을 설명하겠다.

당연히 dark-theme.less 파일은 dark 모드를 사용할 때 적용할 스타일 정보를 저장한다.

light-theme.less 파일은 light 모드를 사용할 때 적용할 스타일을 저장한다.

프로젝트 root 경로에 gulpfile.js 파일을 생성하자.

gulpfile.js

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
const gulp = require('gulp')
const gulpless = require('gulp-less')
const postcss = require('gulp-postcss')
const debug = require('gulp-debug')
var csso = require('gulp-csso')
const autoprefixer = require('autoprefixer')
const NpmImportPlugin = require('less-plugin-npm-import')

gulp.task('less', function () {
const plugins = [autoprefixer()]

return gulp
.src('src/themes/*-theme.less')
.pipe(debug({title: 'Less files:'}))
.pipe(
gulpless({
javascriptEnabled: true,
plugins: [new NpmImportPlugin({prefix: '~'})],
}),
)
.pipe(postcss(plugins))
.pipe(
csso({
debug: true,
}),
)
.pipe(gulp.dest('./public'))
})

gulp라는 프론트엔드 task runner를 이용해서 gulpfile.js 를 실행시킨다.

gulpfile.js는 dark-theme.less, light-theme.less파일을 로드해서 css파일로 변환해서, public 폴더에 저장한다.

그리고 react-css-theme-switcher 라는 것을 사용해서 react에서 dark-theme.css와 light-theme.css 파일을 선택적으로 로드해서 사용한다.

glup 관련 의존성을 추가한다.

1
yarn add -D gulp gulp-less gulp-postcss gulp-debug gulp-csso autoprefixer less-plugin-npm-import

그리고 아래 postcss 도 추가한다.(내가 참고한 블로그에는 없지만, 본인의 경우 아래 의존성이 추가적으로 필요했다.)

1
npm i -D postcss

아래 명령으로 gulp를 이용해서 gulpfile.js 파일을 실행시킨다.

1
npx gulp less

public 폴더에 dark-theme.css, light-theme.css 파일이 gulp를 통해서 생성이 되었다.

만약 dark-theme.less, light-theme.less 파일을 본인의 입맛에 맞게 수정했다면, 위 npx gulp less 파일을 실행시켜, 새롭게 dark-theme.css, light-theme.css 파일을 재 생성 해 주어야 한다.

react-cra-antd-darktheme%20efa153b7e9b7443c9b838c30ff14e9e1/Untitled%203.png

다음은 react 에서 동적으로 css 파일을 변경해서 테마를 변경시켜주는 react-css-theme-switcher 를 설치하자.

1
yarn add react-css-theme-switcher

react에서 react-css-theme-switcher를 사옹해서 테마 변경하는 코드 작성

아래 코드에서는 react-css-theme-switcher 관련 코드와 toggleTheme 메소드만 주의 깊게 보면 된다.

index.css, app.css는 사실 신경쓰지 않아도 된다. 그냥 좀 화면을 예쁘게 만들어 주는 것 뿐이다.

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// index.js
import React from "react";

import ReactDOM from "react-dom";

import "./index.css";
import App from "./App";
import { ThemeSwitcherProvider } from "react-css-theme-switcher";

const themes = {
dark: `${process.env.PUBLIC_URL}/dark-theme.css`,
light: `${process.env.PUBLIC_URL}/light-theme.css`,
};

ReactDOM.render(
<React.StrictMode>
<ThemeSwitcherProvider themeMap={themes} defaultTheme="light">
<App />
</ThemeSwitcherProvider>
</React.StrictMode>,
document.getElementById("root")
);

index.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

min-height: 100vh;
}

.fade-in {
animation: fadeIn;
animation-duration: 0.6s;
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

app.js

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
29
30
31
import React from "react";
import "./App.css";
import { useThemeSwitcher } from "react-css-theme-switcher";
import { Switch, Input } from "antd";

export default function App() {
const [isDarkMode, setIsDarkMode] = React.useState();
const { switcher, currentTheme, status, themes } = useThemeSwitcher();

const toggleTheme = (isChecked) => {
setIsDarkMode(isChecked);
switcher({ theme: isChecked ? themes.dark : themes.light });
};

// Avoid theme change flicker
if (status === "loading") {
return null;
}

return (
<div className="main fade-in">
<h1>The current theme is: {currentTheme}</h1>
<Switch checked={isDarkMode} onChange={toggleTheme} />

<Input
style={{ width: 300, marginTop: 30 }}
placeholder="I will change with the theme!"
/>
</div>
);
}

app.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

min-height: 100vh;
}

.fade-in {
animation: fadeIn;
animation-duration: 0.6s;
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

마지막 결과 확인

1
npm run start

react-cra-antd-darktheme%20efa153b7e9b7443c9b838c30ff14e9e1/antd-darktheme.gif

예제 github 경로

https://github.com/blog-examples/react-antd-darktheme.git

참고자료

antd 디자인 dark테마 적용

https://jfelix.info/blog/dynamic-themes-in-ant-design-how-to-change-between-light-and-dark-theme

antd 디자인 적용

[https://jeonghwan-kim.github.io/2018/10/13/ant-design-101.html](