├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── server
├── config.json
├── database.json
└── server.js
├── src
├── App.css
├── App.js
├── App.test.js
├── assets
│ ├── banner-video.mp4
│ ├── fonts
│ │ └── BMYEONSUNG.ttf
│ ├── logo.png
│ ├── main-items.jpg
│ ├── main-parts.jpg
│ ├── main-styles.jpg
│ ├── main1.jpg
│ ├── main2.jpg
│ ├── main3.jpg
│ └── part
│ │ ├── deck1.jpg
│ │ ├── deck2.jpg
│ │ ├── etc1.jpg
│ │ ├── etc2.jpg
│ │ ├── etc3.jpg
│ │ ├── truck1.webp
│ │ ├── wheel1.png
│ │ └── wheel2.jpg
├── components
│ ├── BannerImage.js
│ ├── BannerVideo.js
│ ├── Card.js
│ ├── Footer.js
│ ├── Header.js
│ ├── ImagesWithTitle.js
│ ├── ItemGrid.js
│ ├── Meta.js
│ ├── Tabs.js
│ ├── TextOnImg.js
│ ├── ThreeColumns.js
│ ├── TwoColumns.js
│ └── YoutubePlayer.js
├── index.css
├── index.js
├── pages
│ ├── ItemsPage.js
│ ├── MainPage.js
│ ├── PartPage.js
│ └── RidingStylesPage.js
├── serviceWorker.js
├── setupTests.js
├── styles.css
└── tailwind.css
├── tailwind.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 | .idea
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Lecture-3
2 |
3 | '프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React) - Part. 2'의 1번째 강의 소스입니다.
4 |
5 | ### 실행
6 |
7 | 1. download sources
8 |
9 | ```
10 | $ git clone https://github.com/performance-lecture/lecture-3.git
11 | ```
12 |
13 | 2. install dependencies
14 |
15 | ```
16 | $ npm install
17 | or
18 | $ yarn
19 | ```
20 |
21 | 3. start development server
22 |
23 | ```
24 | $ npm start
25 | or
26 | $ yarn start
27 | ```
28 |
29 | 4. start json-server
30 |
31 | ```
32 | $ npm run server
33 | or
34 | $ yarn server
35 | ```
36 | *3번의 dev server 와 다른 콘솔에서 띄워줍니다.
37 |
38 | ### 질문
39 |
40 | 궁금하신 부분은 강의 내 질문 & 답변 게시판 또는 해당 레포지토리의 Issues를 이용해주시기 바랍니다.
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lecture-3",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^4.2.4",
7 | "@testing-library/react": "^9.3.2",
8 | "@testing-library/user-event": "^7.1.2",
9 | "axios": "^0.19.1",
10 | "express": "^4.17.1",
11 | "react": "^16.12.0",
12 | "react-dom": "^16.12.0",
13 | "react-router-dom": "^5.1.2",
14 | "react-scripts": "3.3.0",
15 | "tailwindcss": "^1.1.4"
16 | },
17 | "scripts": {
18 | "start": "npm run build:style && react-scripts start",
19 | "build": "npm run build:style && react-scripts build",
20 | "build:style": "postcss src/tailwind.css -o src/styles.css",
21 | "serve": "node ./server/server.js",
22 | "server": "node ./node_modules/json-server/lib/cli/bin.js --watch ./server/database.json -c ./server/config.json"
23 | },
24 | "eslintConfig": {
25 | "extends": "react-app"
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | },
39 | "devDependencies": {
40 | "autoprefixer": "^9.7.3",
41 | "json-server": "^0.15.1",
42 | "postcss-cli": "^7.1.0",
43 | "serve": "^11.3.2"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('tailwindcss')('./tailwind.js'),
4 | require('autoprefixer'),
5 | ],
6 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "port": 3001
3 | }
--------------------------------------------------------------------------------
/server/database.json:
--------------------------------------------------------------------------------
1 | {
2 | "items": [
3 | {
4 | "title": "OSTRICH 2019 – SIDEWALL",
5 | "link": "https://land-mfg.com/product/ostrich-2019-longboard-deck/",
6 | "price": "210,00",
7 | "image": "https://land-mfg.com/wp-content/uploads/alternative-longboards-ostrich-2019-1.jpg"
8 | },
9 | {
10 | "title": "KAROO 2020 – GIRL WITH CORK",
11 | "link": "https://land-mfg.com/product/karoo-2020-girl-with-cork/",
12 | "price": "220,00",
13 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2016-GirlwithCork-kopia.jpg"
14 | },
15 | {
16 | "title": "KAROO 2020 – BOY WITH STARS",
17 | "link": "https://land-mfg.com/product/karoo-2020-boy-with-stars/",
18 | "price": "220,00",
19 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2016-Boywithstars-kopia.jpg"
20 | },
21 | {
22 | "title": "KAROO 2020 – BOY WITH MOON",
23 | "link": "https://land-mfg.com/product/karoo-2020-boy-with-moon/",
24 | "price": "220,00",
25 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2016-Boywithmoon-600x1320-01-kopia.jpg"
26 | },
27 | {
28 | "title": "KAROO 2020 – BOY WITH BOAT",
29 | "link": "https://land-mfg.com/product/karoo-2020-boy-with-boat/",
30 | "price": "220,00",
31 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2016-Boywithboat-600x1320-01-kopia.jpg"
32 | },
33 | {
34 | "title": "KAROO 2020 – BOY WITH SWORD",
35 | "link": "https://land-mfg.com/product/karoo-2020-boy-with-sword/",
36 | "price": "220,00",
37 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2017-Boy-01-kopia.jpg"
38 | },
39 | {
40 | "title": "KAROO 2020 – MASK",
41 | "link": "https://land-mfg.com/product/karoo-2020-mask/",
42 | "price": "220,00",
43 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2017-Mask-01-kopia.jpg"
44 | },
45 | {
46 | "title": "KAROO 2020 – ROBOT GIRL",
47 | "link": "https://land-mfg.com/product/karoo-2020-robot-girl/",
48 | "price": "220,00",
49 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2017-Robot-kopia.jpg"
50 | },
51 | {
52 | "title": "KAROO 2020 – GIRL WITH GUN",
53 | "link": "https://land-mfg.com/product/karoo-2020-girl-with-gun/",
54 | "price": "220,00",
55 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2017-StandingGirl-01-kopia.jpg"
56 | },
57 | {
58 | "title": "KAROO 2020 – GIRL WITH SMILE",
59 | "link": "https://land-mfg.com/product/karoo-2020-girl-with-smile/",
60 | "price": "220,00",
61 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2017-SittingGirl-01-kopia.jpg"
62 | },
63 | {
64 | "title": "KAROO 2020 – SNAKE",
65 | "link": "https://land-mfg.com/product/karoo-2020-snake/",
66 | "price": "220,00",
67 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-w%C4%85%C5%BC-01-kopia.jpg"
68 | },
69 | {
70 | "title": "KAROO 2020 – WORM",
71 | "link": "https://land-mfg.com/product/karoo-2020-worm/",
72 | "price": "220,00",
73 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-Robak-01-01-kopia.jpg"
74 | },
75 | {
76 | "title": "KAROO 2020 – GIRL WITH APPLE",
77 | "link": "https://land-mfg.com/product/karoo-2020-girl-with-apple/",
78 | "price": "220,00",
79 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-Laska-z-jablkiem-01-kopia.jpg"
80 | },
81 | {
82 | "title": "KAROO 2020 – GIRL WITH FLUTE",
83 | "link": "https://land-mfg.com/product/karoo-2020-girl-with-flute/",
84 | "price": "220,00",
85 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-Laska-z-fletem-01-kopia.jpg"
86 | },
87 | {
88 | "title": "KAROO 2020 – RAVEN",
89 | "link": "https://land-mfg.com/product/karoo-2020-raven/",
90 | "price": "220,00",
91 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-Kruk-kopia.jpg"
92 | },
93 | {
94 | "title": "KAROO 2020 – SKELETON",
95 | "link": "https://land-mfg.com/product/karoo-2020-skeleton/",
96 | "price": "220,00",
97 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-ko%C5%9Bciotrup-01-kopia.jpg"
98 | },
99 | {
100 | "title": "KAROO 2020 – FUCK",
101 | "link": "https://land-mfg.com/product/karoo-2020-fuck/",
102 | "price": "220,00",
103 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-fuck-01-kopia.jpg"
104 | },
105 | {
106 | "title": "KAROO 2020 – FACE",
107 | "link": "https://land-mfg.com/product/karoo-2020-face/",
108 | "price": "220,00",
109 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-FACE-01-kopia.jpg"
110 | },
111 | {
112 | "title": "KAROO 2020 – BUDDHA",
113 | "link": "https://land-mfg.com/product/karoo-2020-buddha/",
114 | "price": "220,00",
115 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2018-ziomek-w-kwiatku-01-01-kopia.jpg"
116 | },
117 | {
118 | "title": "KAROO 2020 – DOG WITH BONE",
119 | "link": "https://land-mfg.com/product/karoo-2020-dog-with-bone/",
120 | "price": "220,00",
121 | "image": "https://land-mfg.com/wp-content/uploads/Karoo2019-KidwithMask-01-kopia.jpg"
122 | },
123 | {
124 | "title": "OSTRICH 2020 – GIRL WITH SMILE",
125 | "link": "https://land-mfg.com/product/ostrich-2020-girl-with-smile/",
126 | "price": "210,00",
127 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-laskasiedzaca-01-kopia.jpg"
128 | },
129 | {
130 | "title": "OSTRICH 2020 – GIRL WITH APPLE",
131 | "link": "https://land-mfg.com/product/ostrich-2020-girl-with-apple/",
132 | "price": "210,00",
133 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-laska-z-jablkiem-01-kopia.jpg"
134 | },
135 | {
136 | "title": "OSTRICH 2020 – GIRL WITH FLUTE",
137 | "link": "https://land-mfg.com/product/ostrich-2020-girl-with-flute/",
138 | "price": "210,00",
139 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-laska-z-fletem-01-01-kopia.jpg"
140 | },
141 | {
142 | "title": "OSTRICH 2020 – RAVEN",
143 | "link": "https://land-mfg.com/product/ostrich-2020-raven/",
144 | "price": "210,00",
145 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-kruk-01-kopia.jpg"
146 | },
147 | {
148 | "title": "OSTRICH 2020 – SKELETON",
149 | "link": "https://land-mfg.com/product/ostrich-2020-skeleton/",
150 | "price": "210,00",
151 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-kosciotrup-01-01-kopia.jpg"
152 | },
153 | {
154 | "title": "OSTRICH 2020 – ROOSTER",
155 | "link": "https://land-mfg.com/product/ostrich-2020-rooster/",
156 | "price": "210,00",
157 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-kogut-01-kopia.jpg"
158 | },
159 | {
160 | "title": "OSTRICH 2020 – FUCK",
161 | "link": "https://land-mfg.com/product/ostrich-2020-fuck/",
162 | "price": "210,00",
163 | "image": "https://land-mfg.com/wp-content/uploads/Ostrich2017-fuck-01-kopia.jpg"
164 | },
165 | {
166 | "title": "FLAMINGO 2020 – GIRL IN THE VALLEY",
167 | "link": "https://land-mfg.com/product/flamingo-2020-girl-in-the-valley/",
168 | "price": "205,00",
169 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2013-laska_Obszar-roboczy-1-kopia.jpg"
170 | },
171 | {
172 | "title": "FLAMINGO 2020 – CAT",
173 | "link": "https://land-mfg.com/product/flamingo-2020-cat/",
174 | "price": "205,00",
175 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2013-kot_Obszar-roboczy-1-kopia.jpg"
176 | },
177 | {
178 | "title": "FLAMINGO 2020 – LUMBERJACK",
179 | "link": "https://land-mfg.com/product/flamingo-2020-lumberjack/",
180 | "price": "205,00",
181 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2013-Drwal_Obszar-roboczy-1-kopia.jpg"
182 | },
183 | {
184 | "title": "FLAMINGO 2020 – BEAR",
185 | "link": "https://land-mfg.com/product/flamingo-2020-bear/",
186 | "price": "205,00",
187 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2013-bear_Obszar-roboczy-1-kopia.jpg"
188 | },
189 | {
190 | "title": "FLAMINGO 2020 – MEN WITH PANDA",
191 | "link": "https://land-mfg.com/product/flamingo-2020-men-with-panda/",
192 | "price": "205,00",
193 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2015-ziomek-z-panda_Obszar-roboczy-1-kopia.jpg"
194 | },
195 | {
196 | "title": "FLAMINGO 2020 – GIRL WITH ARROW",
197 | "link": "https://land-mfg.com/product/flamingo-2020-girl-with-arrow/",
198 | "price": "205,00",
199 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2015-laska-ze-strza%C5%82a_Obszar-roboczy-1-kopia.jpg"
200 | },
201 | {
202 | "title": "FLAMINGO 2020 – GIRL WITH SKULL",
203 | "link": "https://land-mfg.com/product/flamingo-2020-girl-with-skull/",
204 | "price": "205,00",
205 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2015-laska-z-czaszka_Obszar-roboczy-1-kopia.jpg"
206 | },
207 | {
208 | "title": "FLAMINGO 2020 – BOY WITH BOAT",
209 | "link": "https://land-mfg.com/product/flamingo-2020-boy-with-boat/",
210 | "price": "205,00",
211 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2016-ziomek-z-lodka_Obszar-roboczy-1-kopia.jpg"
212 | },
213 | {
214 | "title": "FLAMINGO 2020 – BOY WITH MOON",
215 | "link": "https://land-mfg.com/product/flamingo-2020-boy-with-moon/",
216 | "price": "205,00",
217 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2016-ziomek-z-ksiezycem_Obszar-roboczy-1-kopia.jpg"
218 | },
219 | {
220 | "title": "FLAMINGO 2020 – BOY WITH STARS",
221 | "link": "https://land-mfg.com/product/flamingo-2020-boy-with-stars/",
222 | "price": "205,00",
223 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2016-ziomek-z-gwiazdami_Obszar-roboczy-1-kopia.jpg"
224 | },
225 | {
226 | "title": "FLAMINGO 2020 – GIRL WITH CORK",
227 | "link": "https://land-mfg.com/product/flamingo-2020-girl-with-cork/",
228 | "price": "205,00",
229 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2016-laska-z-korkiem_Obszar-roboczy-1-kopia.jpg"
230 | },
231 | {
232 | "title": "FLAMINGO 2020 – BOY WITH SWORD",
233 | "link": "https://land-mfg.com/product/flamingo-2020-boy-with-sword/",
234 | "price": "205,00",
235 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-ziomek-z-mieczem_Obszar-roboczy-1-kopia.jpg"
236 | },
237 | {
238 | "title": "FLAMINGO 2020 – ROBOT GIRL",
239 | "link": "https://land-mfg.com/product/flamingo-2020-robot-girl/",
240 | "price": "205,00",
241 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-robot_Obszar-roboczy-1-kopia.jpg"
242 | },
243 | {
244 | "title": "FLAMINGO 2020 – MASK",
245 | "link": "https://land-mfg.com/product/flamingo-2020-mask/",
246 | "price": "205,00",
247 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-maska_Obszar-roboczy-1-kopia.jpg"
248 | },
249 | {
250 | "title": "FLAMINGO 2020 – GIRL WITH SMILE",
251 | "link": "https://land-mfg.com/product/flamingo-2020-girl-with-smile/",
252 | "price": "205,00",
253 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-laska-siedzaca_Obszar-roboczy-1-kopia.jpg"
254 | },
255 | {
256 | "title": "FLAMINGO 2020 – CTHULHU",
257 | "link": "https://land-mfg.com/product/flamingo-2020-cthulhu/",
258 | "price": "205,00",
259 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-thzulu_Obszar-roboczy-1-kopia.jpg"
260 | },
261 | {
262 | "title": "FLAMINGO 2020 – ROBOT",
263 | "link": "https://land-mfg.com/product/flamingo-2020-robot/",
264 | "price": "205,00",
265 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-robot-mackami_Obszar-roboczy-1-kopia.jpg"
266 | },
267 | {
268 | "title": "FLAMINGO 2020 – EAGLE WITH OCTOPUS",
269 | "link": "https://land-mfg.com/product/flamingo-2020-eagle-with-octopus/",
270 | "price": "205,00",
271 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-ptak_Obszar-roboczy-1_Obszar-roboczy-1-kopia.jpg"
272 | },
273 | {
274 | "title": "FLAMINGO 2020 – GODZILLA",
275 | "link": "https://land-mfg.com/product/flamingo-2020-godzilla/",
276 | "price": "205,00",
277 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2017-gozilla_Obszar-roboczy-1-kopia.jpg"
278 | },
279 | {
280 | "title": "FLAMINGO 2020 – BUDDHA",
281 | "link": "https://land-mfg.com/product/flamingo-2020-buddha/",
282 | "price": "205,00",
283 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2018-ziomek-w-kwiatku_Obszar-roboczy-1-kopia.jpg"
284 | },
285 | {
286 | "title": "FLAMINGO 2020 – SNAKE",
287 | "link": "https://land-mfg.com/product/flamingo-2020-snake/",
288 | "price": "205,00",
289 | "image": "https://land-mfg.com/wp-content/uploads/Flamingo2018-waz_Obszar-roboczy-1-kopia.jpg"
290 | }
291 | ]
292 | }
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const app = express()
3 | const port = 5000
4 | const path = require('path')
5 |
6 |
7 | const header = {
8 | setHeaders: (res, path) => {
9 | res.setHeader('Cache-Control', 'private, no-cache, no-store, must-revalidate')
10 | res.setHeader('Expires', '-1')
11 | res.setHeader('Pragma', 'no-cache')
12 | },
13 | }
14 |
15 | app.use(express.static(path.join(__dirname, '../build'), header))
16 | app.get('*', (req, res) => {
17 | res.sendFile(path.join(__dirname, '../build/index.html'))
18 | })
19 |
20 | app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
21 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .react-player iframe {
2 | height: 100% !important;
3 | }
4 |
5 | @font-face {
6 | font-family: BMYEONSUNG;
7 | src: url('./assets/fonts/BMYEONSUNG.ttf');
8 | }
9 |
10 | .BannerVideo {
11 | font-family: 'BMYEONSUNG', sans-serif;
12 | }
13 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Switch, Route} from 'react-router-dom'
3 | import './App.css'
4 | import './styles.css'
5 |
6 | import Header from './components/Header'
7 | import Footer from './components/Footer'
8 | import MainPage from './pages/MainPage'
9 | import ItemsPage from './pages/ItemsPage'
10 | import PartPage from './pages/PartPage'
11 | import RidingStylesPage from './pages/RidingStylesPage'
12 |
13 | function App() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | )
28 | }
29 |
30 | export default App
31 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | const { getByText } = render();
7 | const linkElement = getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/src/assets/banner-video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/banner-video.mp4
--------------------------------------------------------------------------------
/src/assets/fonts/BMYEONSUNG.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/fonts/BMYEONSUNG.ttf
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/main-items.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main-items.jpg
--------------------------------------------------------------------------------
/src/assets/main-parts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main-parts.jpg
--------------------------------------------------------------------------------
/src/assets/main-styles.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main-styles.jpg
--------------------------------------------------------------------------------
/src/assets/main1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main1.jpg
--------------------------------------------------------------------------------
/src/assets/main2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main2.jpg
--------------------------------------------------------------------------------
/src/assets/main3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/main3.jpg
--------------------------------------------------------------------------------
/src/assets/part/deck1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/deck1.jpg
--------------------------------------------------------------------------------
/src/assets/part/deck2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/deck2.jpg
--------------------------------------------------------------------------------
/src/assets/part/etc1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/etc1.jpg
--------------------------------------------------------------------------------
/src/assets/part/etc2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/etc2.jpg
--------------------------------------------------------------------------------
/src/assets/part/etc3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/etc3.jpg
--------------------------------------------------------------------------------
/src/assets/part/truck1.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/truck1.webp
--------------------------------------------------------------------------------
/src/assets/part/wheel1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/wheel1.png
--------------------------------------------------------------------------------
/src/assets/part/wheel2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/performance-lecture/lecture-3/5db56604d229ddc818355ffa60472f58f57e601e/src/assets/part/wheel2.jpg
--------------------------------------------------------------------------------
/src/components/BannerImage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function BannerImage(props) {
4 | return (
5 |
6 |
7 |

8 |
9 |
14 |
15 | )
16 | }
17 |
18 | export default BannerImage
19 |
--------------------------------------------------------------------------------
/src/components/BannerVideo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import video from '../assets/banner-video.mp4'
3 |
4 | function BannerVideo() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
KEEP
13 |
CALM
14 |
AND
15 |
RIDE
16 |
LONGBOARD
17 |
18 |
19 |
20 | )
21 | }
22 |
23 | export default BannerVideo
24 |
--------------------------------------------------------------------------------
/src/components/Card.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function Card(props) {
4 | return (
5 |
6 |

7 |
8 | {props.children}
9 |
10 |
11 | )
12 | }
13 |
14 | export default Card
15 |
--------------------------------------------------------------------------------
/src/components/Footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function Footer(props) {
4 | return (
5 |
6 | ©Performance Optimization Lecture for React
7 |
8 | )
9 | }
10 |
11 | export default Footer
12 |
--------------------------------------------------------------------------------
/src/components/Header.js:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react'
2 | import {Link} from 'react-router-dom'
3 | import logo from '../assets/logo.png'
4 |
5 | function Header(props) {
6 | const [isOpened, setIsOpened] = useState(false)
7 |
8 | const toggleSidebar = () => {
9 | setIsOpened(!isOpened)
10 | }
11 |
12 | return (
13 | <>
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
33 |
34 |
35 |
36 | Main
37 |
38 |
39 | Items
40 |
41 |
42 | Part of Board
43 |
44 |
45 | Riding Styles
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
62 |
63 |
Main
64 |
Items
65 |
Part of Board
66 |
Riding Styles
67 |
68 |
69 | >
70 | )
71 | }
72 |
73 |
74 |
75 | export default Header
76 |
--------------------------------------------------------------------------------
/src/components/ImagesWithTitle.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function ImagesWithTitle(props) {
4 | return (
5 |
6 |
7 |
{props.title}
8 | {props.images.map((img) => (
9 |
10 | ))}
11 |
12 |
13 | )
14 | }
15 |
16 | export default ImagesWithTitle
17 |
--------------------------------------------------------------------------------
/src/components/ItemGrid.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function ItemGrid(props) {
4 | const makeSrcset = (src) => {
5 | const _src = src.replace('.jpg', '')
6 | return (
7 | _src + '-675x844.jpg 675w,' +
8 | _src + '-540x675.jpg 540w,' +
9 | _src + '-240x300.jpg 240w,' +
10 | _src + '-819x1024.jpg 819w,' +
11 | _src + '.jpg 1280w'
12 | )
13 | }
14 |
15 | return (
16 |
29 | )
30 | }
31 |
32 | export default ItemGrid
33 |
--------------------------------------------------------------------------------
/src/components/Meta.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 |
4 | function Meta(props) {
5 | return (
6 |
7 |
8 | {props.title}
9 |
10 |
11 | {props.content}
12 |
13 |
14 |
15 |
보러가기
16 |
19 |
20 |
21 |
22 | )
23 | }
24 |
25 | export default Meta
26 |
--------------------------------------------------------------------------------
/src/components/Tabs.js:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react'
2 |
3 | function Tabs(props) {
4 | const [tab, setTab] = useState(0)
5 | return (
6 |
7 |
8 | {props.data.map((item, index) => (
9 |
{setTab(index)}}
13 | >
14 | {item.title}
15 |
16 | ))}
17 |
18 |
19 | {props.data.map((item, index) => (
20 |
21 | {item.content}
22 |
23 | ))}
24 |
25 |
26 | )
27 | }
28 |
29 | export default Tabs
30 |
--------------------------------------------------------------------------------
/src/components/TextOnImg.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function TextOnImg(props) {
4 | return (
5 |
6 | TextOnImg
7 |
8 | )
9 | }
10 |
11 | export default TextOnImg
12 |
--------------------------------------------------------------------------------
/src/components/ThreeColumns.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function ThreeColumns(props) {
4 | return (
5 |
6 |
7 |
8 | {props.columns[0]}
9 |
10 |
11 | {props.columns[1]}
12 |
13 |
14 | {props.columns[2]}
15 |
16 |
17 |
18 | )
19 | }
20 |
21 | export default ThreeColumns
22 |
--------------------------------------------------------------------------------
/src/components/TwoColumns.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function TwoColumns(props) {
4 | return (
5 |
6 |
7 |
8 | {props.columns[0]}
9 |
10 |
11 | {props.columns[1]}
12 |
13 |
14 |
15 | )
16 | }
17 |
18 | export default TwoColumns
19 |
--------------------------------------------------------------------------------
/src/components/YoutubePlayer.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function YoutubePlayer(props) {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import { BrowserRouter } from 'react-router-dom'
4 | import './index.css'
5 | import App from './App'
6 | import * as serviceWorker from './serviceWorker'
7 |
8 | ReactDOM.render(
9 |
10 |
11 | ,
12 | document.getElementById('root')
13 | )
14 |
15 | // If you want your app to work offline and load faster, you can change
16 | // unregister() to register() below. Note this comes with some pitfalls.
17 | // Learn more about service workers: https://bit.ly/CRA-PWA
18 | serviceWorker.unregister()
19 |
--------------------------------------------------------------------------------
/src/pages/ItemsPage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react'
2 | import axios from 'axios'
3 |
4 | import BannerImage from '../components/BannerImage'
5 | import ItemGrid from '../components/ItemGrid'
6 | import main_items from '../assets/main-items.jpg'
7 |
8 | function ItemsPage(props) {
9 | const [items, setItems] = useState([])
10 |
11 | const getItems = () => {
12 | axios.get('http://localhost:3001/items')
13 | .then((success) => {
14 | console.log(success.data)
15 | setItems(success.data)
16 | })
17 | }
18 |
19 | useEffect(() => {
20 | getItems()
21 | }, [])
22 |
23 | return (
24 |
35 | )
36 | }
37 |
38 | export default ItemsPage
39 |
--------------------------------------------------------------------------------
/src/pages/MainPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import BannerVideo from '../components/BannerVideo'
3 | import ThreeColumns from '../components/ThreeColumns'
4 | import TwoColumns from '../components/TwoColumns'
5 | import Card from '../components/Card'
6 | import Meta from '../components/Meta'
7 | import main1 from '../assets/main1.jpg'
8 | import main2 from '../assets/main2.jpg'
9 | import main3 from '../assets/main3.jpg'
10 | import main_items from '../assets/main-items.jpg'
11 | import main_parts from '../assets/main-parts.jpg'
12 | import main_styles from '../assets/main-styles.jpg'
13 |
14 | function MainPage(props) {
15 | return (
16 |
17 |
18 |
19 |
롱보드는 아주 재밌습니다.,
22 | 롱보드를 타면 아주 신납니다.,
23 | 롱보드는 굉장히 재밌습니다.
24 | ]}
25 | />
26 | ,
30 |
35 | ]}
36 | />
37 | ,
45 |
46 | ]}
47 | mobileReverse={true}
48 | />
49 | ,
53 |
58 | ]}
59 | />
60 |
61 |
62 | )
63 | }
64 |
65 | export default MainPage
66 |
--------------------------------------------------------------------------------
/src/pages/PartPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import BannerImage from '../components/BannerImage'
3 | import ImagesWithTitle from '../components/ImagesWithTitle'
4 | import main_parts from '../assets/main-parts.jpg'
5 | import deck1 from '../assets/part/deck1.jpg'
6 | import deck2 from '../assets/part/deck2.jpg'
7 | import truck1 from '../assets/part/truck1.webp'
8 | import wheel1 from '../assets/part/wheel1.png'
9 | import wheel2 from '../assets/part/wheel2.jpg'
10 | import etc1 from '../assets/part/etc1.jpg'
11 | import etc2 from '../assets/part/etc2.jpg'
12 | import etc3 from '../assets/part/etc3.jpg'
13 |
14 | function PartPage(props) {
15 | return (
16 |
17 |
21 |
22 |
27 |
32 |
37 |
42 |
43 |
44 | )
45 | }
46 |
47 | export default PartPage
48 |
--------------------------------------------------------------------------------
/src/pages/RidingStylesPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import Tabs from '../components/Tabs'
4 | import BannerImage from '../components/BannerImage'
5 | import YoutubePlayer from '../components/YoutubePlayer'
6 | import main_styles from '../assets/main-styles.jpg'
7 |
8 | function RidingStylesPage(props) {
9 | const opts = {
10 | width: '100%',
11 | height: '100%',
12 | playerVars: {
13 | autoplay: 1
14 | }
15 | };
16 |
17 | const DATA = [
18 | {
19 | title: "댄싱",
20 | content: (
21 |
22 | )
23 | },
24 | {
25 | title: "프리스타일",
26 | content: (
27 |
28 | )
29 | },
30 | {
31 | title: "다운힐",
32 | content: (
33 |
34 | )
35 | },
36 | {
37 | title: "프리라이딩",
38 | content: (
39 |
40 | )
41 | }
42 | ]
43 |
44 |
45 | return (
46 |
55 | )
56 | }
57 |
58 | export default RidingStylesPage
59 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.0/8 are considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl, {
104 | headers: { 'Service-Worker': 'script' }
105 | })
106 | .then(response => {
107 | // Ensure service worker exists, and that we really are getting a JS file.
108 | const contentType = response.headers.get('content-type');
109 | if (
110 | response.status === 404 ||
111 | (contentType != null && contentType.indexOf('javascript') === -1)
112 | ) {
113 | // No service worker found. Probably a different app. Reload the page.
114 | navigator.serviceWorker.ready.then(registration => {
115 | registration.unregister().then(() => {
116 | window.location.reload();
117 | });
118 | });
119 | } else {
120 | // Service worker found. Proceed as normal.
121 | registerValidSW(swUrl, config);
122 | }
123 | })
124 | .catch(() => {
125 | console.log(
126 | 'No internet connection found. App is running in offline mode.'
127 | );
128 | });
129 | }
130 |
131 | export function unregister() {
132 | if ('serviceWorker' in navigator) {
133 | navigator.serviceWorker.ready.then(registration => {
134 | registration.unregister();
135 | });
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect';
6 |
--------------------------------------------------------------------------------
/src/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | .bg-texture {
6 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3E%3Cpath fill='%23000000' fill-opacity='0.84' d='M1 3h1v1H1V3zm2-2h1v1H3V1z'%3E%3C/path%3E%3C/svg%3E");
7 | }
--------------------------------------------------------------------------------
/tailwind.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | prefix: '',
3 | important: false,
4 | separator: ':',
5 | theme: {
6 | screens: {
7 | sm: '640px',
8 | md: '768px',
9 | lg: '1024px',
10 | xl: '1280px',
11 | },
12 | colors: {
13 | transparent: 'transparent',
14 |
15 | black: '#000',
16 | white: '#fff',
17 |
18 | gray: {
19 | 100: '#f7fafc',
20 | 200: '#edf2f7',
21 | 300: '#e2e8f0',
22 | 400: '#cbd5e0',
23 | 500: '#a0aec0',
24 | 600: '#718096',
25 | 700: '#4a5568',
26 | 800: '#2d3748',
27 | 900: '#1a202c',
28 | },
29 | red: {
30 | 100: '#fff5f5',
31 | 200: '#fed7d7',
32 | 300: '#feb2b2',
33 | 400: '#fc8181',
34 | 500: '#f56565',
35 | 600: '#e53e3e',
36 | 700: '#c53030',
37 | 800: '#9b2c2c',
38 | 900: '#742a2a',
39 | },
40 | orange: {
41 | 100: '#fffaf0',
42 | 200: '#feebc8',
43 | 300: '#fbd38d',
44 | 400: '#f6ad55',
45 | 500: '#ed8936',
46 | 600: '#dd6b20',
47 | 700: '#c05621',
48 | 800: '#9c4221',
49 | 900: '#7b341e',
50 | },
51 | yellow: {
52 | 100: '#fffff0',
53 | 200: '#fefcbf',
54 | 300: '#faf089',
55 | 400: '#f6e05e',
56 | 500: '#ecc94b',
57 | 600: '#d69e2e',
58 | 700: '#b7791f',
59 | 800: '#975a16',
60 | 900: '#744210',
61 | },
62 | green: {
63 | 100: '#f0fff4',
64 | 200: '#c6f6d5',
65 | 300: '#9ae6b4',
66 | 400: '#68d391',
67 | 500: '#48bb78',
68 | 600: '#38a169',
69 | 700: '#2f855a',
70 | 800: '#276749',
71 | 900: '#22543d',
72 | },
73 | teal: {
74 | 100: '#e6fffa',
75 | 200: '#b2f5ea',
76 | 300: '#81e6d9',
77 | 400: '#4fd1c5',
78 | 500: '#38b2ac',
79 | 600: '#319795',
80 | 700: '#2c7a7b',
81 | 800: '#285e61',
82 | 900: '#234e52',
83 | },
84 | blue: {
85 | 100: '#ebf8ff',
86 | 200: '#bee3f8',
87 | 300: '#90cdf4',
88 | 400: '#63b3ed',
89 | 500: '#4299e1',
90 | 600: '#3182ce',
91 | 700: '#2b6cb0',
92 | 800: '#2c5282',
93 | 900: '#2a4365',
94 | },
95 | indigo: {
96 | 100: '#ebf4ff',
97 | 200: '#c3dafe',
98 | 300: '#a3bffa',
99 | 400: '#7f9cf5',
100 | 500: '#667eea',
101 | 600: '#5a67d8',
102 | 700: '#4c51bf',
103 | 800: '#434190',
104 | 900: '#3c366b',
105 | },
106 | purple: {
107 | 100: '#faf5ff',
108 | 200: '#e9d8fd',
109 | 300: '#d6bcfa',
110 | 400: '#b794f4',
111 | 500: '#9f7aea',
112 | 600: '#805ad5',
113 | 700: '#6b46c1',
114 | 800: '#553c9a',
115 | 900: '#44337a',
116 | },
117 | pink: {
118 | 100: '#fff5f7',
119 | 200: '#fed7e2',
120 | 300: '#fbb6ce',
121 | 400: '#f687b3',
122 | 500: '#ed64a6',
123 | 600: '#d53f8c',
124 | 700: '#b83280',
125 | 800: '#97266d',
126 | 900: '#702459',
127 | },
128 | },
129 | spacing: {
130 | px: '1px',
131 | '0': '0',
132 | '1': '0.25rem',
133 | '2': '0.5rem',
134 | '3': '0.75rem',
135 | '4': '1rem',
136 | '5': '1.25rem',
137 | '6': '1.5rem',
138 | '8': '2rem',
139 | '10': '2.5rem',
140 | '12': '3rem',
141 | '16': '4rem',
142 | '20': '5rem',
143 | '24': '6rem',
144 | '32': '8rem',
145 | '40': '10rem',
146 | '48': '12rem',
147 | '56': '14rem',
148 | '64': '16rem',
149 | '16:9': '56.25%',
150 | },
151 | backgroundColor: theme => theme('colors'),
152 | backgroundPosition: {
153 | bottom: 'bottom',
154 | center: 'center',
155 | left: 'left',
156 | 'left-bottom': 'left bottom',
157 | 'left-top': 'left top',
158 | right: 'right',
159 | 'right-bottom': 'right bottom',
160 | 'right-top': 'right top',
161 | top: 'top',
162 | },
163 | backgroundSize: {
164 | auto: 'auto',
165 | cover: 'cover',
166 | contain: 'contain',
167 | },
168 | borderColor: theme => ({
169 | ...theme('colors'),
170 | default: theme('colors.gray.300', 'currentColor'),
171 | }),
172 | borderRadius: {
173 | none: '0',
174 | sm: '0.125rem',
175 | default: '0.25rem',
176 | lg: '0.5rem',
177 | full: '9999px',
178 | },
179 | borderWidth: {
180 | default: '1px',
181 | '0': '0',
182 | '2': '2px',
183 | '4': '4px',
184 | '8': '8px',
185 | },
186 | boxShadow: {
187 | default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
188 | md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
189 | lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
190 | xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
191 | '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
192 | inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
193 | outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
194 | none: 'none',
195 | },
196 | container: {},
197 | cursor: {
198 | auto: 'auto',
199 | default: 'default',
200 | pointer: 'pointer',
201 | wait: 'wait',
202 | text: 'text',
203 | move: 'move',
204 | 'not-allowed': 'not-allowed',
205 | },
206 | fill: {
207 | current: 'currentColor',
208 | },
209 | flex: {
210 | '1': '1 1 0%',
211 | auto: '1 1 auto',
212 | initial: '0 1 auto',
213 | none: 'none',
214 | },
215 | flexGrow: {
216 | '0': '0',
217 | default: '1',
218 | },
219 | flexShrink: {
220 | '0': '0',
221 | default: '1',
222 | },
223 | fontFamily: {
224 | sans: [
225 | '-apple-system',
226 | 'BlinkMacSystemFont',
227 | '"Segoe UI"',
228 | 'Roboto',
229 | '"Helvetica Neue"',
230 | 'Arial',
231 | '"Noto Sans"',
232 | 'sans-serif',
233 | '"Apple Color Emoji"',
234 | '"Segoe UI Emoji"',
235 | '"Segoe UI Symbol"',
236 | '"Noto Color Emoji"',
237 | ],
238 | serif: [
239 | 'Georgia',
240 | 'Cambria',
241 | '"Times New Roman"',
242 | 'Times',
243 | 'serif',
244 | ],
245 | mono: [
246 | 'Menlo',
247 | 'Monaco',
248 | 'Consolas',
249 | '"Liberation Mono"',
250 | '"Courier New"',
251 | 'monospace',
252 | ],
253 | },
254 | fontSize: {
255 | xs: '0.75rem',
256 | sm: '0.875rem',
257 | base: '1rem',
258 | lg: '1.125rem',
259 | xl: '1.25rem',
260 | '2xl': '1.5rem',
261 | '3xl': '1.875rem',
262 | '4xl': '2.25rem',
263 | '5xl': '3rem',
264 | '6xl': '4rem',
265 | },
266 | fontWeight: {
267 | hairline: '100',
268 | thin: '200',
269 | light: '300',
270 | normal: '400',
271 | medium: '500',
272 | semibold: '600',
273 | bold: '700',
274 | extrabold: '800',
275 | black: '900',
276 | },
277 | height: theme => ({
278 | auto: 'auto',
279 | ...theme('spacing'),
280 | full: '100%',
281 | screen: '100vh',
282 | }),
283 | inset: {
284 | '0': '0',
285 | auto: 'auto',
286 | '1/2': '50%',
287 | '-1/2': '-50%',
288 | },
289 | letterSpacing: {
290 | tighter: '-0.05em',
291 | tight: '-0.025em',
292 | normal: '0',
293 | wide: '0.025em',
294 | wider: '0.05em',
295 | widest: '0.1em',
296 | },
297 | lineHeight: {
298 | none: '1',
299 | tight: '1.25',
300 | snug: '1.375',
301 | normal: '1.5',
302 | relaxed: '1.625',
303 | loose: '2',
304 | },
305 | listStyleType: {
306 | none: 'none',
307 | disc: 'disc',
308 | decimal: 'decimal',
309 | },
310 | margin: (theme, { negative }) => ({
311 | auto: 'auto',
312 | ...theme('spacing'),
313 | ...negative(theme('spacing')),
314 | }),
315 | maxHeight: {
316 | full: '100%',
317 | screen: '100vh',
318 | },
319 | maxWidth: {
320 | xs: '20rem',
321 | sm: '24rem',
322 | md: '28rem',
323 | lg: '32rem',
324 | xl: '36rem',
325 | '2xl': '42rem',
326 | '3xl': '48rem',
327 | '4xl': '56rem',
328 | '5xl': '64rem',
329 | '6xl': '72rem',
330 | full: '100%',
331 | none: 'none',
332 | },
333 | minHeight: {
334 | '0': '0',
335 | full: '100%',
336 | screen: '100vh',
337 | },
338 | minWidth: {
339 | '0': '0',
340 | full: '100%',
341 | },
342 | objectPosition: {
343 | bottom: 'bottom',
344 | center: 'center',
345 | left: 'left',
346 | 'left-bottom': 'left bottom',
347 | 'left-top': 'left top',
348 | right: 'right',
349 | 'right-bottom': 'right bottom',
350 | 'right-top': 'right top',
351 | top: 'top',
352 | },
353 | opacity: {
354 | '0': '0',
355 | '25': '0.25',
356 | '50': '0.5',
357 | '75': '0.75',
358 | '100': '1',
359 | },
360 | order: {
361 | first: '-9999',
362 | last: '9999',
363 | none: '0',
364 | '1': '1',
365 | '2': '2',
366 | '3': '3',
367 | '4': '4',
368 | '5': '5',
369 | '6': '6',
370 | '7': '7',
371 | '8': '8',
372 | '9': '9',
373 | '10': '10',
374 | '11': '11',
375 | '12': '12',
376 | },
377 | padding: theme => theme('spacing'),
378 | placeholderColor: theme => theme('colors'),
379 | stroke: {
380 | current: 'currentColor',
381 | },
382 | textColor: theme => theme('colors'),
383 | width: theme => ({
384 | auto: 'auto',
385 | ...theme('spacing'),
386 | '1/2': '50%',
387 | '1/3': '33.333333%',
388 | '2/3': '66.666667%',
389 | '1/4': '25%',
390 | '2/4': '50%',
391 | '3/4': '75%',
392 | '1/5': '20%',
393 | '2/5': '40%',
394 | '3/5': '60%',
395 | '4/5': '80%',
396 | '1/6': '16.666667%',
397 | '2/6': '33.333333%',
398 | '3/6': '50%',
399 | '4/6': '66.666667%',
400 | '5/6': '83.333333%',
401 | '1/12': '8.333333%',
402 | '2/12': '16.666667%',
403 | '3/12': '25%',
404 | '4/12': '33.333333%',
405 | '5/12': '41.666667%',
406 | '6/12': '50%',
407 | '7/12': '58.333333%',
408 | '8/12': '66.666667%',
409 | '9/12': '75%',
410 | '10/12': '83.333333%',
411 | '11/12': '91.666667%',
412 | full: '100%',
413 | screen: '100vw',
414 | }),
415 | zIndex: {
416 | auto: 'auto',
417 | '0': '0',
418 | '10': '10',
419 | '20': '20',
420 | '30': '30',
421 | '40': '40',
422 | '50': '50',
423 | '-1': '-1',
424 | },
425 | },
426 | variants: {
427 | accessibility: ['responsive', 'focus'],
428 | alignContent: ['responsive'],
429 | alignItems: ['responsive'],
430 | alignSelf: ['responsive'],
431 | appearance: ['responsive'],
432 | backgroundAttachment: ['responsive'],
433 | backgroundColor: ['responsive', 'hover', 'focus'],
434 | backgroundPosition: ['responsive'],
435 | backgroundRepeat: ['responsive'],
436 | backgroundSize: ['responsive'],
437 | borderCollapse: ['responsive'],
438 | borderColor: ['responsive', 'hover', 'focus'],
439 | borderRadius: ['responsive'],
440 | borderStyle: ['responsive'],
441 | borderWidth: ['responsive'],
442 | boxShadow: ['responsive', 'hover', 'focus'],
443 | cursor: ['responsive'],
444 | display: ['responsive'],
445 | fill: ['responsive'],
446 | flex: ['responsive'],
447 | flexDirection: ['responsive'],
448 | flexGrow: ['responsive'],
449 | flexShrink: ['responsive'],
450 | flexWrap: ['responsive'],
451 | float: ['responsive'],
452 | fontFamily: ['responsive'],
453 | fontSize: ['responsive'],
454 | fontSmoothing: ['responsive'],
455 | fontStyle: ['responsive'],
456 | fontWeight: ['responsive', 'hover', 'focus'],
457 | height: ['responsive'],
458 | inset: ['responsive'],
459 | justifyContent: ['responsive'],
460 | letterSpacing: ['responsive'],
461 | lineHeight: ['responsive'],
462 | listStylePosition: ['responsive'],
463 | listStyleType: ['responsive'],
464 | margin: ['responsive'],
465 | maxHeight: ['responsive'],
466 | maxWidth: ['responsive'],
467 | minHeight: ['responsive'],
468 | minWidth: ['responsive'],
469 | objectFit: ['responsive'],
470 | objectPosition: ['responsive'],
471 | opacity: ['responsive', 'hover', 'focus'],
472 | order: ['responsive'],
473 | outline: ['responsive', 'focus'],
474 | overflow: ['responsive'],
475 | padding: ['responsive'],
476 | placeholderColor: ['responsive', 'focus'],
477 | pointerEvents: ['responsive'],
478 | position: ['responsive'],
479 | resize: ['responsive'],
480 | stroke: ['responsive'],
481 | tableLayout: ['responsive'],
482 | textAlign: ['responsive'],
483 | textColor: ['responsive', 'hover', 'focus'],
484 | textDecoration: ['responsive', 'hover', 'focus'],
485 | textTransform: ['responsive'],
486 | userSelect: ['responsive'],
487 | verticalAlign: ['responsive'],
488 | visibility: ['responsive'],
489 | whitespace: ['responsive'],
490 | width: ['responsive'],
491 | wordBreak: ['responsive'],
492 | zIndex: ['responsive'],
493 | },
494 | corePlugins: {},
495 | plugins: [
496 | function({ addUtilities }) {
497 | const newUtilities = {
498 | '.translateX-1\\/2': {
499 | transform: 'translateX(50%)',
500 | },
501 | '.translateX--1\\/2': {
502 | transform: 'translateX(-50%)',
503 | },
504 | '.keep-all': {
505 | wordBreak: 'keep-all',
506 | }
507 | }
508 |
509 | addUtilities(newUtilities, ['responsive'])
510 | }
511 | ],
512 | }
513 |
--------------------------------------------------------------------------------