diff --git a/craco.config.js b/craco.config.js index e39f09a..43d9cf8 100644 --- a/craco.config.js +++ b/craco.config.js @@ -10,6 +10,10 @@ module.exports = { "@pages": path.resolve(__dirname, "src/pages"), "@routes": path.resolve(__dirname, "src/routes"), "@utils": path.resolve(__dirname, "src/utils"), + "@layouts": path.resolve(__dirname, "src/layouts"), + "@assets": path.resolve(__dirname, "src/assets"), + "@styles": path.resolve(__dirname, "src/styles"), + "@contexts": path.resolve(__dirname, "src/contexts"), }, }, }; diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 491dfe5..0000000 --- a/src/App.js +++ /dev/null @@ -1,5 +0,0 @@ -function App() { - return

Hello React!

; -} - -export default App; diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..b75fc0d --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,18 @@ +import { ThemeProvider } from "styled-components"; +import GlobalStyle from "@styles/GlobalStyle"; +import * as CommonStyle from "@styles/common"; +import Router from "@/routes/index"; +import ContextProvider from "@contexts"; + +function App() { + return ( + + + + + + + ); +} + +export default App; diff --git a/src/apis/index.js b/src/apis/index.js new file mode 100644 index 0000000..58d0fa3 --- /dev/null +++ b/src/apis/index.js @@ -0,0 +1,11 @@ +import axios from "axios"; + +const instance = axios.create({ + baseURL: process.env.REACT_APP_API_URL, + timeout: 2000, +}); + +export const getCarList = async (params) => { + const response = await instance.get("/cars", { params }); + return response; +}; diff --git a/src/assets/icons/back.svg b/src/assets/icons/back.svg new file mode 100644 index 0000000..62d1f16 --- /dev/null +++ b/src/assets/icons/back.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/index.js b/src/assets/icons/index.js new file mode 100644 index 0000000..89d0b9b --- /dev/null +++ b/src/assets/icons/index.js @@ -0,0 +1,7 @@ +import { ReactComponent as Back } from "@assets/icons/back.svg"; + +const icon = { + back: Back, +}; + +export default icon; diff --git a/src/components/CarDetailList/List.styled.jsx b/src/components/CarDetailList/List.styled.jsx new file mode 100644 index 0000000..9601580 --- /dev/null +++ b/src/components/CarDetailList/List.styled.jsx @@ -0,0 +1,39 @@ +import styled from "styled-components"; + +const List = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; + +const ListHeader = styled.div` + display: flex; + height: 45px; + align-items: center; + color: ${({ theme }) => theme.COLORS.WHITE}; + background-color: ${({ theme }) => theme.COLORS.BLUE}; + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + padding-left: 20px; +`; + +const ListItem = styled.li` + display: flex; + justify-content: space-between; + align-items: center; + height: 48px; + padding: 0 20px; +`; + +const Name = styled.span` + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + color: ${({ theme }) => theme.COLORS.BLACK}; +`; + +const Contents = styled.span` + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + color: ${({ theme }) => theme.COLORS.BLACK}; +`; + +export { List, ListHeader, ListItem, Name, Contents }; diff --git a/src/components/CarDetailList/index.jsx b/src/components/CarDetailList/index.jsx new file mode 100644 index 0000000..a4b0d9b --- /dev/null +++ b/src/components/CarDetailList/index.jsx @@ -0,0 +1,19 @@ +import * as S from "@components/CarDetailList/List.styled"; + +const CarDetailList = ({ title, contents }) => { + return ( + + {title} + + + ); +}; + +export default CarDetailList; diff --git a/src/components/CarItem/CarItem.styled.jsx b/src/components/CarItem/CarItem.styled.jsx new file mode 100644 index 0000000..9061662 --- /dev/null +++ b/src/components/CarItem/CarItem.styled.jsx @@ -0,0 +1,41 @@ +import styled from "styled-components"; +import Tag from "@components/Tag"; + +const CarItem = styled.li` + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: row; + width: 390px; + height: 120px; + padding: 0 20px; + border-bottom: 1px solid ${({ theme }) => theme.COLORS.BLACK}; + cursor: pointer; +`; + +const CarInfo = styled.div` + display: flex; + flex-direction: column; + gap: 8px; +`; + +const Title = styled.div` + display: flex; + flex-direction: column; + font-size: ${({ theme }) => theme.FONT.SIZE.BASE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; +`; + +const Contents = styled.div` + display: flex; + flex-direction: column; + font-size: ${({ theme }) => theme.FONT.SIZE.SMALL}; +`; + +const Badge = styled(Tag)` + position: absolute; + z-index: 10; +`; + +export { CarItem, CarInfo, Title, Contents, Badge }; diff --git a/src/components/CarItem/index.jsx b/src/components/CarItem/index.jsx new file mode 100644 index 0000000..9aea2e9 --- /dev/null +++ b/src/components/CarItem/index.jsx @@ -0,0 +1,40 @@ +import { useNavigate } from "react-router-dom"; + +import ROUTE_PATH from "@/routes/routerPaths"; +import Image from "@components/common/Image"; +import * as S from "@components/CarItem/CarItem.styled"; +import { useCarInfoContext } from "@contexts/carInfo"; + +const CarItem = ({ carInfo }) => { + const navigate = useNavigate(); + const { setSelectedCarInfo } = useCarInfoContext(); + + const { id, amount, attribute } = carInfo; + const { brand, name, segment, imageUrl, fuelType } = attribute; + + const handleClick = () => { + setSelectedCarInfo(carInfo); + navigate(`${ROUTE_PATH.DETAIL}/${id}`); + }; + + const isNew = false; + + return ( + + + + {brand} + {name} + + + {`${segment} / ${fuelType}`} + {`월 ${amount.toLocaleString()} 원 부터`} + + + + {isNew && } + + ); +}; + +export default CarItem; diff --git a/src/components/Category/Category.styled.jsx b/src/components/Category/Category.styled.jsx new file mode 100644 index 0000000..ac9af27 --- /dev/null +++ b/src/components/Category/Category.styled.jsx @@ -0,0 +1,18 @@ +import styled from "styled-components"; + +const Category = styled.ul` + display: flex; + width: 100%; + height: 40px; + overflow-x: scroll; + gap: 8px; + border-bottom: 1px solid ${({ theme }) => theme.COLORS.BLACK}; +`; + +const CategoryItem = styled.li` + display: flex; + align-items: center; + justify-content: center; +`; + +export { Category, CategoryItem }; diff --git a/src/components/Category/index.jsx b/src/components/Category/index.jsx new file mode 100644 index 0000000..6bb414d --- /dev/null +++ b/src/components/Category/index.jsx @@ -0,0 +1,23 @@ +import * as S from "@components/Category/Category.styled"; +import Tag from "@components/Tag"; +import { useCategoryContext } from "@contexts/category"; + +const Category = ({ categories }) => { + const { selectedCategory, setSelectedCategory } = useCategoryContext(); + + const handleClick = ({ target }) => { + setSelectedCategory(target.id); + }; + + return ( + + {categories.map(({ id, name }) => ( + + + + ))} + + ); +}; + +export default Category; diff --git a/src/components/Tag/Tag.styled.jsx b/src/components/Tag/Tag.styled.jsx new file mode 100644 index 0000000..8668770 --- /dev/null +++ b/src/components/Tag/Tag.styled.jsx @@ -0,0 +1,36 @@ +import styled, { css, ThemeConsumer } from "styled-components"; + +const ITEM_TAG_STYLE = css` + width: 52px; + height: 22px; + border-radius: 42px; + font-size: ${({ theme }) => theme.FONT.SIZE.SMALL}; + color: ${({ theme }) => theme.COLORS.WHITE}; + background-color: ${({ theme }) => theme.COLORS.BLUE}; +`; + +const DEFAULT_TAG_STYLE = css` + width: 62px; + height: 27px; + border-radius: 62px; + font-size: ${({ theme }) => theme.FONT.SIZE.BASE}; + color: ${({ isSelected, theme }) => (isSelected ? theme.COLORS.WHITE : theme.COLORS.BLACK)}; + background-color: ${({ isSelected, theme }) => + isSelected ? theme.COLORS.BLACK : theme.COLORS.GREY}; +`; + +const TAG_STYLE = { + small: ITEM_TAG_STYLE, + default: DEFAULT_TAG_STYLE, +}; + +const Tag = styled.button` + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + ${({ size = "default" }) => TAG_STYLE[size]} +`; + +export { Tag }; diff --git a/src/components/Tag/index.jsx b/src/components/Tag/index.jsx new file mode 100644 index 0000000..61760dd --- /dev/null +++ b/src/components/Tag/index.jsx @@ -0,0 +1,11 @@ +import * as S from "@components/Tag/Tag.styled"; + +const Tag = ({ size = "default", id, name, isSelected, onClick }) => { + return ( + + {name} + + ); +}; + +export default Tag; diff --git a/src/components/common/Icon/index.jsx b/src/components/common/Icon/index.jsx new file mode 100644 index 0000000..81804f9 --- /dev/null +++ b/src/components/common/Icon/index.jsx @@ -0,0 +1,8 @@ +import icon from "@/assets/icons/index"; + +const Icon = ({ iconName }) => { + const IconComponent = icon[iconName]; + return ; +}; + +export default Icon; diff --git a/src/components/common/Image/Image.styled.jsx b/src/components/common/Image/Image.styled.jsx new file mode 100644 index 0000000..b0b3c53 --- /dev/null +++ b/src/components/common/Image/Image.styled.jsx @@ -0,0 +1,23 @@ +import styled, { css } from "styled-components"; + +const BIG_IMAGE = css` + width: 390px; + height: 205px; +`; + +const DEFAULT_IMAGE = css` + width: 152px; + height: 80px; +`; + +const IMAGE_STYLE = { + default: DEFAULT_IMAGE, + big: BIG_IMAGE, +}; + +const Image = styled.img` + object-fit: cover; + ${({ size = "default" }) => IMAGE_STYLE[size]} +`; + +export { Image }; diff --git a/src/components/common/Image/index.jsx b/src/components/common/Image/index.jsx new file mode 100644 index 0000000..4460353 --- /dev/null +++ b/src/components/common/Image/index.jsx @@ -0,0 +1,4 @@ +import * as S from "@components/common/Image/Image.styled"; +const Image = ({ url, size = "default" }) => ; + +export default Image; diff --git a/src/constants/carInfo.js b/src/constants/carInfo.js new file mode 100644 index 0000000..7aa812f --- /dev/null +++ b/src/constants/carInfo.js @@ -0,0 +1,12 @@ +export const SEGMENT = { + C: "소형", + D: "중형", + E: "대형", + SUV: "SUV", +}; + +export const FUEL_TYPE = { + gasoline: "가솔린", + ev: "전기", + hybrid: "하이브리드", +}; diff --git a/src/contexts/carInfo.jsx b/src/contexts/carInfo.jsx new file mode 100644 index 0000000..a553cd1 --- /dev/null +++ b/src/contexts/carInfo.jsx @@ -0,0 +1,20 @@ +import { createContext, useContext, useState } from "react"; + +const CarInfoContext = createContext(); +CarInfoContext.displayName = "CarInfoContext"; + +const useCarInfoContext = () => { + const context = useContext(CarInfoContext); + if (!context) { + throw new Error("useCarInfoContext should be used within CarInfoContext.Provider"); + } + return context; +}; + +const CarInfoProvider = ({ children }) => { + const [selectedCarInfo, setSelectedCarInfo] = useState(); + const value = { selectedCarInfo, setSelectedCarInfo }; + return {children}; +}; + +export { useCarInfoContext, CarInfoProvider }; diff --git a/src/contexts/category.jsx b/src/contexts/category.jsx new file mode 100644 index 0000000..e94dfe0 --- /dev/null +++ b/src/contexts/category.jsx @@ -0,0 +1,20 @@ +import { createContext, useContext, useState } from "react"; + +const CategoryContext = createContext(); +CategoryContext.displayName = "CategoryContext"; + +const useCategoryContext = () => { + const context = useContext(CategoryContext); + if (!context) { + throw new Error("useCategoryContext should be used within CategoryContext.Provider"); + } + return context; +}; + +const CategoryProvider = ({ children }) => { + const [selectedCategory, setSelectedCategory] = useState("all"); + const value = { selectedCategory, setSelectedCategory }; + return {children}; +}; + +export { useCategoryContext, CategoryProvider }; diff --git a/src/contexts/index.jsx b/src/contexts/index.jsx new file mode 100644 index 0000000..fecefb1 --- /dev/null +++ b/src/contexts/index.jsx @@ -0,0 +1,10 @@ +import { CarInfoProvider } from "@contexts/carInfo"; +import { CategoryProvider } from "@contexts/category"; + +const ContextProvider = ({ children }) => ( + + {children} + +); + +export default ContextProvider; diff --git a/src/hooks/useFetch.jsx b/src/hooks/useFetch.jsx new file mode 100644 index 0000000..2cd1514 --- /dev/null +++ b/src/hooks/useFetch.jsx @@ -0,0 +1,24 @@ +import { useState } from "react"; + +const useFetch = (apiFunc) => { + const [isFetching, setFetching] = useState(false); + const [data, setResponse] = useState(); + + const fetch = (params) => { + setFetching(() => { + apiFunc(params) + .then(({ data }) => { + setResponse(data.payload); + setFetching(false); + }) + .catch((error) => { + console.log(error); + }); + return true; + }); + }; + + return { isFetching, fetch, data }; +}; + +export default useFetch; diff --git a/src/index.js b/src/index.jsx similarity index 99% rename from src/index.js rename to src/index.jsx index a64e7d5..110ab10 100644 --- a/src/index.js +++ b/src/index.jsx @@ -1,5 +1,6 @@ import React from "react"; import ReactDOM from "react-dom/client"; + import "./index.css"; import App from "./App"; diff --git a/src/layouts/Header/Header.styled.jsx b/src/layouts/Header/Header.styled.jsx new file mode 100644 index 0000000..f22a2dc --- /dev/null +++ b/src/layouts/Header/Header.styled.jsx @@ -0,0 +1,27 @@ +import styled from "styled-components"; + +const Header = styled.div` + display: flex; + align-items: center; + position: relative; + min-width: 360px; + width: 450px; + height: 60px; + border-bottom: 1px solid ${({ theme }) => theme.COLORS.BLACK}; +`; + +const Title = styled.h1` + width: 100%; + text-align: center; + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + color: ${({ theme }) => theme.COLORS.BLACK}; +`; + +const IconWrapper = styled.div` + position: absolute; + z-index: 10; + left: 20px; +`; + +export { Header, Title, IconWrapper }; diff --git a/src/layouts/Header/index.jsx b/src/layouts/Header/index.jsx new file mode 100644 index 0000000..fad77fc --- /dev/null +++ b/src/layouts/Header/index.jsx @@ -0,0 +1,32 @@ +import * as S from "@layouts/Header/Header.styled"; +import Icon from "@/components/common/Icon/index"; +import { useLocation, useNavigate } from "react-router-dom"; +import ROUTE_PATH from "@/routes/routerPaths"; + +const TITLE = { + HOME: "전체차량", + DETAIL: "차량상세", +}; + +const Header = () => { + const { pathname } = useLocation(); + const isHome = pathname === ROUTE_PATH.BASE; + + const navigate = useNavigate(); + const handleClick = () => { + navigate(`${ROUTE_PATH.BASE}`); + }; + + return ( + + {!isHome && ( + + + + )} + {isHome ? TITLE.HOME : TITLE.DETAIL} + + ); +}; + +export default Header; diff --git a/src/layouts/index.jsx b/src/layouts/index.jsx new file mode 100644 index 0000000..327333b --- /dev/null +++ b/src/layouts/index.jsx @@ -0,0 +1,23 @@ +import { Outlet } from "react-router-dom"; +import styled from "styled-components"; + +import Header from "@layouts/Header/index"; + +const Layout = () => { + return ( + +
+ + + ); +}; + +const LayoutContainer = styled.div` + display: flex; + position: relative; + align-items: center; + flex-direction: column; + height: 100vh; +`; + +export default Layout; diff --git a/src/pages/CarDetail/CarDetail.styled.jsx b/src/pages/CarDetail/CarDetail.styled.jsx new file mode 100644 index 0000000..4cfa529 --- /dev/null +++ b/src/pages/CarDetail/CarDetail.styled.jsx @@ -0,0 +1,56 @@ +import styled, { css } from "styled-components"; + +const CarDetail = styled.div` + display: flex; + flex-direction: column; + min-width: 360px; + width: 450px; +`; + +const Thumbnail = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 206px; +`; + +const TitleWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + height: 92px; + padding: 0 20px; +`; + +const MAIN_TITLE_STYLE = css` + font-size: ${({ theme }) => theme.FONT.SIZE.X_LARGE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + text-align: left; +`; + +const SUB_TITLE_STYLE = css` + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + text-align: left; +`; + +const AMOUNT_TITLE_STYLE = css` + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.REGULAR}; + text-align: right; + padding: 13px 20px 13px 0; +`; + +const titleStyle = { + main: MAIN_TITLE_STYLE, + sub: SUB_TITLE_STYLE, + amount: AMOUNT_TITLE_STYLE, +}; + +const Title = styled.span` + width: 100%; + ${({ type }) => titleStyle[type]} +`; + +export { CarDetail, Thumbnail, TitleWrapper, Title }; diff --git a/src/pages/CarDetail/index.jsx b/src/pages/CarDetail/index.jsx new file mode 100644 index 0000000..94a59d0 --- /dev/null +++ b/src/pages/CarDetail/index.jsx @@ -0,0 +1,59 @@ +import { useCarInfoContext } from "../../contexts/carInfo"; +import * as S from "@pages/CarDetail/CarDetail.styled"; +import Image from "../../components/common/Image/index"; +import { FUEL_TYPE, SEGMENT } from "../../constants/carInfo"; +import CarDetailList from "../../components/CarDetailList"; + +const CarDetail = () => { + const { selectedCarInfo: carInfo } = useCarInfoContext(); + const { amount } = carInfo; + const { brand, name, imageUrl } = carInfo.attribute; + const carContents = createCarContents(carInfo); + + return ( + + + + + + {brand} + {name} + {`월 ${amount.toLocaleString()}원`} + + {Object.keys(carContents).map((title) => ( + + ))} + + ); +}; + +const createCarContents = (carInfo) => { + const { startDate, insurance, additionalProducts } = carInfo; + const { segment, fuelType } = carInfo.attribute; + + const carContents = { + "차량 정보": [ + { name: "차종", contents: SEGMENT[segment] }, + { name: "연료", contents: FUEL_TYPE[fuelType] }, + { name: "이용 가능일", contents: startDate }, + ], + }; + + if (insurance && insurance.length > 0) { + carContents["보험"] = insurance.map(({ name, description }) => ({ + name, + contents: description, + })); + } + + if (additionalProducts && additionalProducts.length > 0) { + carContents["추가 상품"] = additionalProducts.map(({ name, amount }) => ({ + name, + contents: `월 ${amount.toLocaleString()}원`, + })); + } + + return carContents; +}; + +export default CarDetail; diff --git a/src/pages/Home/Home.styled.jsx b/src/pages/Home/Home.styled.jsx new file mode 100644 index 0000000..f8d43b0 --- /dev/null +++ b/src/pages/Home/Home.styled.jsx @@ -0,0 +1,20 @@ +import styled from "styled-components"; + +const Home = styled.div` + min-width: 360px; + width: 450px; + height: 100%; +`; + +const BackgroundMsg = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD}; + font-size: ${({ theme }) => theme.FONT.SIZE.LARGE}; + color: ${({ theme }) => theme.COLORS.BLACK}; +`; + +export { Home, BackgroundMsg }; diff --git a/src/pages/Home/index.jsx b/src/pages/Home/index.jsx new file mode 100644 index 0000000..38ec90d --- /dev/null +++ b/src/pages/Home/index.jsx @@ -0,0 +1,60 @@ +import * as S from "@pages/Home/Home.styled"; +import Category from "@components/Category/index"; +import { useEffect, useState } from "react"; +import { useCategoryContext } from "@/contexts/category"; +import { getCarList } from "@/apis/index"; +import CarItem from "@/components/CarItem/index"; +import useFetch from "../../hooks/useFetch"; + +const categories = [ + { + id: "all", + name: "전체", + }, + { + id: "C", + name: "소형", + }, + { + id: "D", + name: "중형", + }, + { + id: "E", + name: "대형", + }, +]; + +const Home = () => { + const { fetch, isFetching, data: carList } = useFetch(getCarList); + const { selectedCategory } = useCategoryContext(); + const [backgroundMsg, setBackgroundMsg] = useState(""); + + useEffect(() => { + const params = selectedCategory !== "all" ? { segment: selectedCategory } : {}; + fetch(params); + }, [selectedCategory]); + + useEffect(() => { + if (isFetching) { + setBackgroundMsg("불러오는 중"); + return; + } + + if (!carList || carList.length === 0) { + setBackgroundMsg("차량이 없습니다!"); + } else { + setBackgroundMsg(""); + } + }, [isFetching, carList]); + + return ( + + + {!isFetching && carList && carList.map((data) => )} + {backgroundMsg !== "" && {backgroundMsg}} + + ); +}; + +export default Home; diff --git a/src/routes/index.jsx b/src/routes/index.jsx new file mode 100644 index 0000000..dae6339 --- /dev/null +++ b/src/routes/index.jsx @@ -0,0 +1,21 @@ +import { BrowserRouter, Route, Routes } from "react-router-dom"; +import ROUTE_PATH from "@/routes/routerPaths"; +import Layout from "@/layouts"; +import Home from "@/pages/Home"; +import CarDetail from "../pages/CarDetail/index"; + +const Router = () => { + return ( + + + }> + } /> + } /> + NOT FOUND} /> + + + + ); +}; + +export default Router; diff --git a/src/routes/routerPaths.js b/src/routes/routerPaths.js new file mode 100644 index 0000000..143deaf --- /dev/null +++ b/src/routes/routerPaths.js @@ -0,0 +1,7 @@ +const ROUTE_PATH = { + BASE: process.env.REACT_APP_BASE_URL || "/", + DETAIL: "/detail", + NOT_FOUND: "*", +}; + +export default ROUTE_PATH; diff --git a/src/styles/GlobalStyle.js b/src/styles/GlobalStyle.js new file mode 100644 index 0000000..aa4940e --- /dev/null +++ b/src/styles/GlobalStyle.js @@ -0,0 +1,20 @@ +import { createGlobalStyle } from "styled-components"; + +export default createGlobalStyle` + +html { + font-size: 62.5%; +} + +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} + +button { + border: 0; + outline: 0; +} +`; diff --git a/src/styles/common/color.js b/src/styles/common/color.js new file mode 100644 index 0000000..df7fdbb --- /dev/null +++ b/src/styles/common/color.js @@ -0,0 +1,8 @@ +const COLORS = { + BLACK: "#000000", + GREY: "#D9D9D9", + BLUE: "#0094FF", + WHITE: "#FFFFFF", +}; + +export default COLORS; diff --git a/src/styles/common/font.js b/src/styles/common/font.js new file mode 100644 index 0000000..0a8b5ab --- /dev/null +++ b/src/styles/common/font.js @@ -0,0 +1,20 @@ +const FONT_SIZE = { + X_LARGE: "2.4rem", + LARGE: "1.8rem", + BASE: "1.4rem", + SMALL: "1.2rem", +}; + +const FONT_WEIGHT = { + BOLD: "700", + MEDIUM: "500", + REGULAR: "400", + LIGHT: "100", +}; + +const FONT = { + SIZE: FONT_SIZE, + WEIGHT: FONT_WEIGHT, +}; + +export default FONT; diff --git a/src/styles/common/index.js b/src/styles/common/index.js new file mode 100644 index 0000000..e75a6d2 --- /dev/null +++ b/src/styles/common/index.js @@ -0,0 +1,4 @@ +import COLORS from "@styles/common/color"; +import FONT from "@styles/common/font"; + +export { COLORS, FONT };