From d35f0c30eafa36b417c15c88c0c95df620cc1f82 Mon Sep 17 00:00:00 2001 From: airman5573 <68623798+airman5573@users.noreply.github.com> Date: Wed, 6 Jul 2022 11:38:14 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Header=20=EB=B0=8F=20Home=20Page=20UI?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: typo 수정 custom-styles를 custom-types로 수정 Co-authored-by: TaeYoon * feat: Header 컴포넌트 구현 및 스토리 작성 Header, Logo, Avatar, SearchBar 컴포넌트 구현 Co-authored-by: TaeYoon * style: font 추가 기존 폰트에 Bold, ExtraBold, Light 폰트를 추가 Co-authored-by: TaeYoon * feat: Home화면 구성 Header와 MainPage 컴포넌트를 App에 결합 Co-authored-by: TaeYoon * refactor: css를 붙여 일관성 유지 styled component안에서 theme을 사용할때 css함수를 붙였다. 왜냐하면, 자동완성 기능과 VSC에서 가독성이 더 좋아지기 때문이다. Co-authored-by: TaeYoon Co-authored-by: TaeYoon --- frontend/.prettierrc.json | 10 ++- frontend/.storybook/main.js | 1 + frontend/package-lock.json | 17 ++++- frontend/package.json | 3 +- frontend/src/App.tsx | 30 ++++++++- frontend/src/assets/images/logo.png | Bin 0 -> 5809 bytes .../src/components/Avatar/Avatar.stories.tsx | 22 +++++++ frontend/src/components/Avatar/index.tsx | 16 +++++ frontend/src/components/Avatar/style.tsx | 26 ++++++++ frontend/src/components/Card/style.ts | 2 + .../src/components/Header/Header.stories.tsx | 14 ++++ frontend/src/components/Header/index.tsx | 30 +++++++++ frontend/src/components/Header/style.ts | 60 +++++++++++++++++ frontend/src/components/Logo/Logo.stories.tsx | 15 +++++ frontend/src/components/Logo/index.tsx | 16 +++++ frontend/src/components/Logo/style.tsx | 30 +++++++++ .../SearchBar/SearchBar.stories.tsx | 13 ++++ frontend/src/components/SearchBar/index.tsx | 16 +++++ frontend/src/components/SearchBar/style.ts | 54 ++++++++++++++++ frontend/src/components/StudyCard/index.tsx | 2 +- frontend/src/components/Wrapper/index.tsx | 1 + frontend/src/custom-types/images.d.ts | 3 + frontend/src/custom-types/types.d.ts | 2 +- frontend/src/pages/MainPage/index.tsx | 6 +- frontend/src/pages/MainPage/style.ts | 4 ++ frontend/src/styles/Globalstyles.tsx | 61 +++++++++++++++++- frontend/tsconfig.json | 5 +- frontend/webpack/webpack.common.js | 1 + 28 files changed, 445 insertions(+), 15 deletions(-) create mode 100644 frontend/src/assets/images/logo.png create mode 100644 frontend/src/components/Avatar/Avatar.stories.tsx create mode 100644 frontend/src/components/Avatar/index.tsx create mode 100644 frontend/src/components/Avatar/style.tsx create mode 100644 frontend/src/components/Header/Header.stories.tsx create mode 100644 frontend/src/components/Header/index.tsx create mode 100644 frontend/src/components/Header/style.ts create mode 100644 frontend/src/components/Logo/Logo.stories.tsx create mode 100644 frontend/src/components/Logo/index.tsx create mode 100644 frontend/src/components/Logo/style.tsx create mode 100644 frontend/src/components/SearchBar/SearchBar.stories.tsx create mode 100644 frontend/src/components/SearchBar/index.tsx create mode 100644 frontend/src/components/SearchBar/style.ts create mode 100644 frontend/src/custom-types/images.d.ts diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index d16efa35a..30657e39d 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -10,7 +10,15 @@ "arrowParens": "avoid", "endOfLine": "auto", - "importOrder": ["^@emotion", "^@custom-styles/(.*)$", "^@styles/(.*)$", "^@pages/(.*)$" ,"^@components/(.*)$", "^[./]"], + "importOrder": [ + "^@emotion", + "^@assets/(.*)$", + "^@custom-types/(.*)$", + "^@styles/(.*)$", + "^@pages/(.*)$", + "^@components/(.*)$", + "^[./]" + ], "importOrderSeparation": true, "importOrderSortSpecifiers": true } diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js index 47b2fef37..deab7c1cf 100644 --- a/frontend/.storybook/main.js +++ b/frontend/.storybook/main.js @@ -16,6 +16,7 @@ module.exports = { '@styles': resolve(__dirname, '../src/styles'), '@types': resolve(__dirname, '../src/types'), '@pages': resolve(__dirname, '../src/pages'), + '@assets': resolve(__dirname, '../src/assets'), }; config.module.rules[0].use[0].options.presets = [ diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cb4541ffb..4f35acc68 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "emotion-reset": "^3.0.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-icons": "^4.4.0" }, "devDependencies": { "@babel/cli": "^7.17.10", @@ -20926,6 +20927,14 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "node_modules/react-icons": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz", + "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-inspector": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", @@ -41460,6 +41469,12 @@ } } }, + "react-icons": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz", + "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==", + "requires": {} + }, "react-inspector": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 9cc696e58..893e21837 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -66,6 +66,7 @@ "dependencies": { "emotion-reset": "^3.0.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-icons": "^4.4.0" } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f58e25086..3a55bfbfe 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,33 @@ +import { css } from '@emotion/react'; + +import MainPage from '@pages/MainPage'; + +import Header from '@components/Header'; +import Wrapper from '@components/Wrapper'; + const App = () => { - return
MoaMoa
; + return ( +
+
+
+ + + +
+
+ ); }; export default App; diff --git a/frontend/src/assets/images/logo.png b/frontend/src/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2da11e93146b80ed5fdf8d37915dc068fcf55958 GIT binary patch literal 5809 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 Ce{d%N literal 0 HcmV?d00001 diff --git a/frontend/src/components/Avatar/Avatar.stories.tsx b/frontend/src/components/Avatar/Avatar.stories.tsx new file mode 100644 index 000000000..834ff7310 --- /dev/null +++ b/frontend/src/components/Avatar/Avatar.stories.tsx @@ -0,0 +1,22 @@ +import { Story } from '@storybook/react'; + +import Avatar from '@components/Avatar'; +import type { AvatarProps } from '@components/Avatar'; + +export default { + title: 'Components/Avatar', + component: Avatar, + argTypes: { + profileImg: { controls: 'text' }, + profileAlt: { controls: 'text' }, + }, +}; + +const Template: Story = props => ; + +export const Default = Template.bind({}); +Default.args = { + profileImg: + 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80', + profileAlt: '프로필 이미지', +}; diff --git a/frontend/src/components/Avatar/index.tsx b/frontend/src/components/Avatar/index.tsx new file mode 100644 index 000000000..8845c2608 --- /dev/null +++ b/frontend/src/components/Avatar/index.tsx @@ -0,0 +1,16 @@ +import * as S from './style'; + +export interface AvatarProps { + profileImg: string; + profileAlt: string; +} + +const Avatar: React.FC = ({ profileImg, profileAlt }) => { + return ( + + + + ); +}; + +export default Avatar; diff --git a/frontend/src/components/Avatar/style.tsx b/frontend/src/components/Avatar/style.tsx new file mode 100644 index 000000000..3c14af4af --- /dev/null +++ b/frontend/src/components/Avatar/style.tsx @@ -0,0 +1,26 @@ +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; + +export const ImageContainer = styled.div` + ${({ theme }) => css` + width: 36px; + min-width: 36px; + height: 36px; + border-radius: 50%; + box-shadow: 0px 1px 5px 0px ${theme.colors.secondary.dark}; + overflow: hidden; + transition: opacity 0.2s ease; + + &:hover, + &:active { + opacity: 0.9; + } + `} +`; + +export const Image = styled.img` + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +`; diff --git a/frontend/src/components/Card/style.ts b/frontend/src/components/Card/style.ts index aa7dfe708..61d5b82df 100644 --- a/frontend/src/components/Card/style.ts +++ b/frontend/src/components/Card/style.ts @@ -38,6 +38,8 @@ export const Image = styled.img` export const Contents = styled.div` padding: 8px 8px 12px; + + background-color: ${({ theme }) => theme.colors.secondary.light}; `; export const Title = styled.h4` diff --git a/frontend/src/components/Header/Header.stories.tsx b/frontend/src/components/Header/Header.stories.tsx new file mode 100644 index 000000000..dbd1722b4 --- /dev/null +++ b/frontend/src/components/Header/Header.stories.tsx @@ -0,0 +1,14 @@ +import { Story } from '@storybook/react'; + +import Header from '@components/Header'; +import Wrapper from '@components/Wrapper'; + +export default { + title: 'Components/Header', + component: Header, +}; + +const Template: Story = props =>
; + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx new file mode 100644 index 000000000..fff350682 --- /dev/null +++ b/frontend/src/components/Header/index.tsx @@ -0,0 +1,30 @@ +import { SerializedStyles } from '@emotion/react'; + +import Avatar from '@components/Avatar'; +import Logo from '@components/Logo'; +import SearchBar from '@components/SearchBar'; + +import * as S from './style'; + +type Props = { + className?: string; + css?: SerializedStyles; +}; + +const Header: React.FC = ({ className }) => { + return ( + + + + + + + + ); +}; + +export default Header; diff --git a/frontend/src/components/Header/style.ts b/frontend/src/components/Header/style.ts new file mode 100644 index 000000000..8695cb2f0 --- /dev/null +++ b/frontend/src/components/Header/style.ts @@ -0,0 +1,60 @@ +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; + +import * as Logo from '@components/Logo/style'; +import * as SearchBar from '@components/SearchBar/style'; + +export const SearchBarContainer = styled.div` + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + + width: 100%; + max-width: 400px; +`; + +export const Row = styled.header` + ${({ theme }) => css` + display: flex; + justify-content: space-between; + align-items: center; + gap: 20px; + + position: relative; + + padding: 20px 40px; + + background-color: ${theme.colors.secondary.light}; + border-bottom: 1px solid ${theme.colors.secondary.dark}; + + @media (max-width: 1100px) { + ${Logo.ImageContainer} { + margin-right: 0; + } + ${Logo.BorderText} { + display: none; + } + ${SearchBarContainer} { + position: static; + left: 0; + top: 0; + transform: none; + } + } + + @media (max-width: 800px) { + padding: 16px 24px; + ${SearchBar.Input} { + font-size: 18px; + } + } + + @media (max-width: 500px) { + padding: 10px 12px; + ${SearchBar.Input} { + font-size: 16px; + } + } + `} +`; diff --git a/frontend/src/components/Logo/Logo.stories.tsx b/frontend/src/components/Logo/Logo.stories.tsx new file mode 100644 index 000000000..65df212ce --- /dev/null +++ b/frontend/src/components/Logo/Logo.stories.tsx @@ -0,0 +1,15 @@ +import { Story } from '@storybook/react'; + +import Logo from "@components/Logo"; + +export default { + title: 'Components/Logo', + component: Logo, +}; + +const Template: Story = props => ( + +); + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/frontend/src/components/Logo/index.tsx b/frontend/src/components/Logo/index.tsx new file mode 100644 index 000000000..23f1b2f09 --- /dev/null +++ b/frontend/src/components/Logo/index.tsx @@ -0,0 +1,16 @@ +import logoImage from '@assets/images/logo.png'; + +import * as S from './style'; + +const Logo: React.FC = () => { + return ( + + + 모아모아 로고 이미지 + + MOAMOA + + ); +}; + +export default Logo; diff --git a/frontend/src/components/Logo/style.tsx b/frontend/src/components/Logo/style.tsx new file mode 100644 index 000000000..e23001352 --- /dev/null +++ b/frontend/src/components/Logo/style.tsx @@ -0,0 +1,30 @@ +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; + +export const Row = styled.div` + display: flex; + justify-content: center; + align-items: center; + + cursor: pointer; +`; + +export const ImageContainer = styled.div` + display: flex; + align-items: center; + + width: 40px; + margin-right: 4px; + img { + width: 100%; + } +`; + +export const BorderText = styled.h1` + ${({ theme }) => css` + color: ${theme.colors.primary.base}; + font-size: 40px; + font-weight: 800; + -webkit-text-stroke: 1px ${theme.colors.primary.dark}; + `} +`; diff --git a/frontend/src/components/SearchBar/SearchBar.stories.tsx b/frontend/src/components/SearchBar/SearchBar.stories.tsx new file mode 100644 index 000000000..5bb54e7e0 --- /dev/null +++ b/frontend/src/components/SearchBar/SearchBar.stories.tsx @@ -0,0 +1,13 @@ +import { Story } from '@storybook/react'; + +import SearchBar from '@components/SearchBar'; + +export default { + title: 'Components/SearchBar', + component: SearchBar, +}; + +const Template: Story = props => ; + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/frontend/src/components/SearchBar/index.tsx b/frontend/src/components/SearchBar/index.tsx new file mode 100644 index 000000000..7ff74f4e3 --- /dev/null +++ b/frontend/src/components/SearchBar/index.tsx @@ -0,0 +1,16 @@ +import { FiSearch } from 'react-icons/fi'; + +import * as S from './style'; + +const SearchBar: React.FC = () => { + return ( + + + + + + + ); +}; + +export default SearchBar; diff --git a/frontend/src/components/SearchBar/style.ts b/frontend/src/components/SearchBar/style.ts new file mode 100644 index 000000000..58fd1bd0c --- /dev/null +++ b/frontend/src/components/SearchBar/style.ts @@ -0,0 +1,54 @@ +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + position: relative; +`; + +export const Input = styled.input` + ${({ theme }) => css` + width: 100%; + padding: 8px 40px; + overflow: hidden; + + font-size: 20px; + border-radius: 20px; + border: 3px solid ${theme.colors.primary.base}; + + text-align: center; + + &:focus { + border-color: ${theme.colors.primary.light}; + & + button { + svg { + stroke: ${theme.colors.primary.light}; + } + } + } + `} +`; + +export const Button = styled.button` + ${({ theme }) => css` + display: flex; + align-items: center; + + position: absolute; + top: 0; + right: 0; + bottom: 0; + + padding-right: 20px; + font-size: 20px; + + background: transparent; + border: none; + + &:hover, + &:active { + svg { + stroke: ${theme.colors.primary.light}; + } + } + `} +`; diff --git a/frontend/src/components/StudyCard/index.tsx b/frontend/src/components/StudyCard/index.tsx index c3c15fe27..076356157 100644 --- a/frontend/src/components/StudyCard/index.tsx +++ b/frontend/src/components/StudyCard/index.tsx @@ -13,7 +13,7 @@ const StudyCard: React.FC = ({ thumbnailUrl, thumbnailAlt, title thumbnailAlt={thumbnailAlt} title={title} description={description} - extraChips={[]} + extraChips={[]} /> ); }; diff --git a/frontend/src/components/Wrapper/index.tsx b/frontend/src/components/Wrapper/index.tsx index 4d67e3e0b..f4ca47547 100644 --- a/frontend/src/components/Wrapper/index.tsx +++ b/frontend/src/components/Wrapper/index.tsx @@ -4,6 +4,7 @@ const Wrapper = styled.div` width: 100%; max-width: 1280px; margin: 0 auto; + padding: 0 20px; `; export default Wrapper; diff --git a/frontend/src/custom-types/images.d.ts b/frontend/src/custom-types/images.d.ts new file mode 100644 index 000000000..0fbca75c8 --- /dev/null +++ b/frontend/src/custom-types/images.d.ts @@ -0,0 +1,3 @@ +declare module '*.jpg' +declare module '*.jpeg' +declare module '*.png' diff --git a/frontend/src/custom-types/types.d.ts b/frontend/src/custom-types/types.d.ts index edbd5286d..4bd42fc87 100644 --- a/frontend/src/custom-types/types.d.ts +++ b/frontend/src/custom-types/types.d.ts @@ -1,4 +1,4 @@ -import { theme } from 'styles/theme'; +import { theme } from '@styles/theme'; type ThemeConfig = typeof theme; declare module '@emotion/react' { diff --git a/frontend/src/pages/MainPage/index.tsx b/frontend/src/pages/MainPage/index.tsx index 50fdd557d..d98099ee0 100644 --- a/frontend/src/pages/MainPage/index.tsx +++ b/frontend/src/pages/MainPage/index.tsx @@ -16,9 +16,8 @@ const MainPage: React.FC = () => {
-
  • +
  • { />
  • {studyList.map(study => ( -
  • +
  • li { + cursor: pointer; + } + @media (max-width: 1100px) { grid-template-columns: repeat(3, 1fr); } diff --git a/frontend/src/styles/Globalstyles.tsx b/frontend/src/styles/Globalstyles.tsx index 6df57ed57..426298adc 100644 --- a/frontend/src/styles/Globalstyles.tsx +++ b/frontend/src/styles/Globalstyles.tsx @@ -14,12 +14,60 @@ const GlobalStyles = () => { margin: 0; color: ${theme.colors.black}; } + @font-face { + font-family: 'NanumSquareRound'; + font-weight: 300; + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundL.eot); + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundL.eot?#iefix) + format('embedded-opentype'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundL.woff2) + format('woff2'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundL.woff) + format('woff'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundL.ttf) + format('truetype'); + } + + @font-face { + font-family: 'NanumSquareRound'; + font-weight: 400; + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundR.eot); + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundR.eot?#iefix) + format('embedded-opentype'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundR.woff2) + format('woff2'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundR.woff) + format('woff'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundR.ttf) + format('truetype'); + } @font-face { font-family: 'NanumSquareRound'; - src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_two@1.0/NanumSquareRound.woff') format('woff'); - font-weight: normal; - font-style: normal; + font-weight: 700; + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundB.eot); + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundB.eot?#iefix) + format('embedded-opentype'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundB.woff2) + format('woff2'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundB.woff) + format('woff'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundB.ttf) + format('truetype'); + } + + @font-face { + font-family: 'NanumSquareRound'; + font-weight: 800; + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundEB.eot); + src: url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundEB.eot?#iefix) + format('embedded-opentype'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundEB.woff2) + format('woff2'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundEB.woff) + format('woff'), + url(https://hangeul.pstatic.net/hangeul_static/webfont/NanumSquareRound/NanumSquareRoundEB.ttf) + format('truetype'); } body { @@ -43,6 +91,13 @@ const GlobalStyles = () => { a { text-decoration: none; } + + input { + background-color: ${theme.colors.white}; + &::placeholder { + color: ${theme.colors.secondary.dark}; + } + } `} /> ); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index cb0096aa6..1821f2cea 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -19,9 +19,10 @@ "@components/*": ["components/*"], "@styles/*": ["styles/*"], "@custom-types/*": ["custom-types/*"], - "@pages/*": ["pages/*"] + "@pages/*": ["pages/*"], + "@assets/*": ["assets/*"] }, - "typeRoots": ["./types.d.ts"] + "typeRoots": ["src/custom-types"] }, "include": ["src"] } diff --git a/frontend/webpack/webpack.common.js b/frontend/webpack/webpack.common.js index 1bb97974d..0ebe92b65 100644 --- a/frontend/webpack/webpack.common.js +++ b/frontend/webpack/webpack.common.js @@ -41,6 +41,7 @@ module.exports = { '@styles': resolve(__dirname, '../src/styles'), '@custom-types': resolve(__dirname, '../src/custom-types'), '@pages': resolve(__dirname, '../src/pages'), + '@assets': resolve(__dirname, '../src/assets'), }, }, };