diff --git a/.eslintrc b/.eslintrc
index 7d72ee8c..c99fa561 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -85,6 +85,12 @@
"allowExpressions": true
}
],
+ "react/no-unknown-property": [
+ "error",
+ {
+ "ignore": ["css"]
+ }
+ ],
"react/react-in-jsx-scope": "off",
"react/require-default-props": [
"error",
diff --git a/client/src/components/pages/MainPage.tsx b/client/src/components/pages/MainPage.tsx
index ce3968cb..ed5dfd2f 100644
--- a/client/src/components/pages/MainPage.tsx
+++ b/client/src/components/pages/MainPage.tsx
@@ -1,7 +1,8 @@
import React, { useEffect } from "react";
-import { Box } from "@/components/atoms";
import { AgendaSection, ChatSection } from "@/components/organisms";
import { useAgenda } from "@/services/agenda";
+import { align, gap, justify, padding, row } from "@/styles";
+import { w, h } from "@/styles/size";
export const MainPage: React.FC = () => {
const { retrieveAgendas } = useAgenda(state => ({
@@ -13,18 +14,20 @@ export const MainPage: React.FC = () => {
}, []);
return (
-
-
+
);
};
diff --git a/client/src/styles/background.ts b/client/src/styles/background.ts
new file mode 100644
index 00000000..27c1ad30
--- /dev/null
+++ b/client/src/styles/background.ts
@@ -0,0 +1,13 @@
+import { mapColors } from "@/styles/color";
+import { css } from "@emotion/react";
+
+/**
+ * Applies background-color
+ * @example
+ * bg.gray100 // Apply gray100 background-color
+ */
+export const bg = mapColors(
+ color => css`
+ background-color: ${color};
+ `,
+);
diff --git a/client/src/styles/border.ts b/client/src/styles/border.ts
new file mode 100644
index 00000000..8056d591
--- /dev/null
+++ b/client/src/styles/border.ts
@@ -0,0 +1,14 @@
+import { css } from "@emotion/react";
+import { mapColors } from "@/styles/color";
+
+/**
+ * Applies border
+ * @example
+ * border.gray300 // Apply gray300 border
+ * [border.gray300, round.md] // Usage with `round` mixin
+ */
+export const border = mapColors(
+ color => css`
+ border: 1px solid ${color};
+ `,
+);
diff --git a/client/src/styles/color.ts b/client/src/styles/color.ts
new file mode 100644
index 00000000..644899e8
--- /dev/null
+++ b/client/src/styles/color.ts
@@ -0,0 +1,32 @@
+export const colors = {
+ white: "#FFFFFF",
+ black: "#444444",
+ white100: "#FAFBFC",
+ gray100: "#FAFAFA",
+ gray200: "#EEEEEE",
+ gray300: "#D9D9D9",
+ gray400: "#B6B6B6",
+ gray500: "#8C8C8C",
+ gray600: "#555555",
+ grayTrans: "rgba(85, 85, 85, 0.1)",
+ blue100: "#FAFCFF",
+ blue200: "#E7F0FF",
+ blue300: "#BFDCFF",
+ blue400: "#6EABF4",
+ blue500: "#2F80DE",
+ blue600: "#065DAC",
+ blue700: "#004B81",
+ purpleLight: "#F6EEFE",
+ purple: "#9836EF",
+ orangeLight: "#FDF7E6",
+ orange: "#FF9211",
+ greenLight: "#E9F9EF",
+ green: "#008B1C",
+} as const;
+
+type ColorKeys = keyof typeof colors;
+export type Color = (typeof colors)[ColorKeys];
+export const mapColors = (cb: (color: Color) => T) =>
+ Object.fromEntries(
+ Object.entries(colors).map(([key, value]) => [key, cb(value)] as const),
+ ) as Record;
diff --git a/client/src/styles/index.ts b/client/src/styles/index.ts
new file mode 100644
index 00000000..d17828a9
--- /dev/null
+++ b/client/src/styles/index.ts
@@ -0,0 +1,8 @@
+export * from "./background";
+export * from "./border";
+export * from "./color";
+export * from "./layout";
+export * from "./round";
+export * from "./spacing";
+export * from "./text";
+export * from "./size";
diff --git a/client/src/styles/layout.ts b/client/src/styles/layout.ts
new file mode 100644
index 00000000..394ca47f
--- /dev/null
+++ b/client/src/styles/layout.ts
@@ -0,0 +1,59 @@
+import { css } from "@emotion/react";
+
+export const column = css`
+ display: flex;
+ flex-direction: column;
+`;
+
+export const row = css`
+ display: flex;
+ flex-direction: row;
+`;
+
+export const center = css`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
+export const justify = {
+ start: css`
+ justify-content: flex-start;
+ `,
+ center: css`
+ justify-content: center;
+ `,
+ end: css`
+ justify-content: flex-end;
+ `,
+ between: css`
+ justify-content: space-between;
+ `,
+ around: css`
+ justify-content: space-around;
+ `,
+} as const;
+
+export const align = {
+ start: css`
+ align-items: flex-start;
+ `,
+ center: css`
+ align-items: center;
+ `,
+ end: css`
+ align-items: flex-end;
+ `,
+ stretch: css`
+ align-items: stretch;
+ `,
+} as const;
+
+/**
+ * Applies flexbox with column direction
+ * @example
+ * gap(10) // Apply 10px gap
+ */
+export const gap = (value: number) => css`
+ gap: ${value}px;
+`;
diff --git a/client/src/styles/round.ts b/client/src/styles/round.ts
new file mode 100644
index 00000000..3faf1944
--- /dev/null
+++ b/client/src/styles/round.ts
@@ -0,0 +1,16 @@
+import { css } from "@emotion/react";
+
+/**
+ * Applies border radius
+ * @example
+ * round.md // Apply 5px radius
+ * round.lg // Apply 10px radius
+ */
+export const round = {
+ md: css`
+ border-radius: 5px;
+ `,
+ lg: css`
+ border-radius: 10px;
+ `,
+} as const;
diff --git a/client/src/styles/size.ts b/client/src/styles/size.ts
new file mode 100644
index 00000000..ea522c22
--- /dev/null
+++ b/client/src/styles/size.ts
@@ -0,0 +1,29 @@
+import { css } from "@emotion/react";
+
+const applyAttribute = (attribute: "height" | "width") =>
+ Object.assign(
+ (value: number) => css`
+ ${attribute}: ${value}px;
+ `,
+ {
+ fill: css`
+ ${attribute}: 100%;
+ `,
+ },
+ );
+
+/**
+ * Applies height
+ * @example
+ * h(10) // 10px height
+ * h.fill // 100% height
+ */
+export const h = applyAttribute("height");
+
+/**
+ * Applies width
+ * @example
+ * w(10) // 10px width
+ * w.fill // 100% width
+ */
+export const w = applyAttribute("width");
diff --git a/client/src/styles/spacing.ts b/client/src/styles/spacing.ts
new file mode 100644
index 00000000..83aed694
--- /dev/null
+++ b/client/src/styles/spacing.ts
@@ -0,0 +1,31 @@
+import { css } from "@emotion/react";
+
+const style = (attribute: string) => (value: number) => css`
+ ${attribute}: ${value}px;
+`;
+
+const applyPrefix = (prefix: "padding" | "margin") =>
+ Object.assign(style(prefix), {
+ top: style(`${prefix}-top`),
+ bottom: style(`${prefix}-bottom`),
+ left: style(`${prefix}-left`),
+ right: style(`${prefix}-right`),
+ vertical: style(`${prefix}-block`),
+ horizontal: style(`${prefix}-inline`),
+ });
+
+/**
+ * @example
+ * padding(10) // 10px padding for all sides
+ * padding.top(5) // 5px padding for top
+ * padding.horizontal(8) // 8px padding for left and right
+ */
+export const padding = applyPrefix("padding");
+
+/**
+ * @example
+ * margin(10) // 10px margin for all sides
+ * margin.top(5) // 5px margin for top
+ * margin.horizontal(8) // 8px margin for left and right
+ */
+export const margin = applyPrefix("margin");
diff --git a/client/src/styles/text.ts b/client/src/styles/text.ts
new file mode 100644
index 00000000..63e7854e
--- /dev/null
+++ b/client/src/styles/text.ts
@@ -0,0 +1,32 @@
+import { css } from "@emotion/react";
+import { mapColors } from "@/styles/color";
+
+const style = (size: number, weight: number) => css`
+ font-size: ${size}px;
+ font-weight: ${weight};
+`;
+
+/**
+ * Applies typography styles and text color
+ * @example
+ * text.title1 // Apply title1 typography
+ * text.gray300 // Apply gray300 text color
+ */
+export const text = {
+ ...mapColors(
+ color => css`
+ color: ${color};
+ `,
+ ),
+ title1: style(15, 500),
+ title2: style(14, 500),
+ title3: style(13, 500),
+ subtitle: style(11, 500),
+ body: style(12, 500),
+ option1: style(10, 500),
+ option2: style(9, 500),
+ boldtitle1: style(14, 700),
+ boldtitle2: style(13, 700),
+ boldtitle3: style(12, 700),
+ boldtitle4: style(11, 700),
+} as const;
diff --git a/client/tsconfig.json b/client/tsconfig.json
index c5d978e6..94e3fa96 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -21,6 +21,7 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
+ "jsxImportSource": "@emotion/react",
"types": ["vite-plugin-svgr/client"]
},
"include": ["src", "vite.config.ts"],
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 652749fe..c02c172d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2670,7 +2670,7 @@ packages:
/eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
dependencies:
- debug: 3.2.7
+ debug: 3.2.7(supports-color@5.5.0)
is-core-module: 2.13.0
resolve: 1.22.4
transitivePeerDependencies:
@@ -2722,7 +2722,7 @@ packages:
optional: true
dependencies:
'@typescript-eslint/parser': 6.2.1(eslint@8.48.0)(typescript@5.1.6)
- debug: 3.2.7
+ debug: 3.2.7(supports-color@5.5.0)
eslint: 8.48.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.2.1)(eslint-plugin-import@2.28.1)(eslint@8.48.0)
@@ -2745,7 +2745,7 @@ packages:
array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
- debug: 3.2.7
+ debug: 3.2.7(supports-color@5.5.0)
doctrine: 2.1.0
eslint: 8.48.0
eslint-import-resolver-node: 0.3.9