diff --git a/src/App.module.scss b/src/App.module.scss
index 674c893..dd8252f 100644
--- a/src/App.module.scss
+++ b/src/App.module.scss
@@ -16,8 +16,9 @@
}
.Test3 {
- width: 99px;
+ width: 216px;
display: flex;
flex-direction: column;
- gap: 16px;
+ align-items: center;
+ gap: 8px;
}
diff --git a/src/App.tsx b/src/App.tsx
index 1a8ea41..7d79321 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,6 +2,7 @@ import styles from "./App.module.scss";
import Button from "@/components/ui/Button/Button";
import IconButton from "@/components/ui/IconButton/IconButton";
+import Text from "@/components/ui/Text/Text";
const App = () => {
return (
@@ -16,6 +17,17 @@ const App = () => {
+
+
+ 영수증으로
+
+
+ AI 음식 리뷰 남겨요
+
+
+ 손쉬운 음식 리뷰 작성
+
+
);
};
diff --git a/src/components/ui/Button/Button.module.scss b/src/components/ui/Button/Button.module.scss
index 723d0b7..703099c 100644
--- a/src/components/ui/Button/Button.module.scss
+++ b/src/components/ui/Button/Button.module.scss
@@ -4,7 +4,7 @@
@include buttonSecondary;
&.style-primary {
- background-color: var(--color-text01);
+ background-color: var(--color-text-primary);
color: var(--color-white);
}
@@ -15,12 +15,12 @@
&.style-tertiary {
background-color: var(--color-gray200);
- color: var(--color-text02);
+ color: var(--color-text-secondary);
}
&:disabled {
background-color: var(--color-gray350);
- color: var(--color-text03);
+ color: var(--color-text-tertiary);
cursor: not-allowed;
}
}
diff --git a/src/components/ui/IconButton/IconButton.module.scss b/src/components/ui/IconButton/IconButton.module.scss
index f1f51d8..b135f57 100644
--- a/src/components/ui/IconButton/IconButton.module.scss
+++ b/src/components/ui/IconButton/IconButton.module.scss
@@ -16,7 +16,7 @@
gap: 0.125rem;
height: 2.375rem;
padding: 0.5rem 0.875rem;
- background-color: var(--color-text01);
+ background-color: var(--color-text-primary);
color: var(--color-white);
border-radius: 0.75rem;
@include buttonTertiary;
diff --git a/src/components/ui/Text/Text.module.scss b/src/components/ui/Text/Text.module.scss
new file mode 100644
index 0000000..9f077d7
--- /dev/null
+++ b/src/components/ui/Text/Text.module.scss
@@ -0,0 +1,67 @@
+.Text {
+ line-height: 1.5;
+
+ @each $color-name
+ in ("white", "black", "primary", "secondary", "tertiary", "quarternary", "gradient")
+ {
+ @if $color-name == "gradient" {
+ &.color-#{$color-name} {
+ background: var(--color-text-gradient);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+ } @else {
+ &.color-#{$color-name} {
+ color: var(--color-text-#{$color-name});
+ }
+ }
+ }
+
+ @each $size-name in ("xxs", "xs", "sm", "default", "md", "lg", "xl") {
+ &.size-#{"#{$size-name}"} {
+ font-size: var(--font-size-#{$size-name});
+ }
+ }
+
+ @each $weight-name in ("regular", "medium", "semi-bold", "bold") {
+ &.weight-#{"#{$weight-name}"} {
+ font-weight: var(--font-weight-#{$weight-name});
+ }
+ }
+
+ @each $align-name in ("left", "center", "right") {
+ &.align-#{"#{$align-name}"} {
+ text-align: #{$align-name};
+ }
+ }
+
+ &.truncated {
+ overflow: hidden;
+ display: block;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ &.multi-line-truncated {
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ text-overflow: ellipsis;
+ -webkit-line-clamp: 2;
+ line-clamp: 2;
+ }
+}
+
+.TextStory {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ width: 200px;
+
+ .Wrapper {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+ }
+}
diff --git a/src/components/ui/Text/Text.stories.tsx b/src/components/ui/Text/Text.stories.tsx
new file mode 100644
index 0000000..8a9a9dd
--- /dev/null
+++ b/src/components/ui/Text/Text.stories.tsx
@@ -0,0 +1,109 @@
+import Text from "@/components/ui/Text/Text";
+import styles from "@/components/ui/Text/Text.module.scss";
+import type { TextProps } from "@/components/ui/Text/Text.types";
+
+import type { Meta, StoryObj, StoryFn } from "@storybook/react";
+
+const meta: Meta = {
+ title: "Example/Text",
+ component: Text,
+ parameters: {
+ layout: "centered",
+ },
+ tags: ["!autodocs"],
+};
+
+export default meta;
+
+const Template: StoryFn = ({ children, ...props }) => (
+
+ {children}
+
+);
+
+export const Primary: StoryObj = {
+ render: Template,
+ args: {
+ size: "default",
+ color: "black",
+ weight: "regular",
+ align: "left",
+ truncated: false,
+ children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
+ },
+};
+
+export const SizeProps: StoryObj = {
+ render: () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+};
+
+export const WeightProps: StoryObj = {
+ render: () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+};
+
+export const ColorPorps: StoryObj = {
+ render: () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+};
diff --git a/src/components/ui/Text/Text.tsx b/src/components/ui/Text/Text.tsx
new file mode 100644
index 0000000..9fc1325
--- /dev/null
+++ b/src/components/ui/Text/Text.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+
+import classNames from "classnames";
+
+import styles from "@/components/ui/Text/Text.module.scss";
+import type { TextProps } from "@/components/ui/Text/Text.types";
+
+const Text = React.forwardRef(
+ (
+ {
+ as: Comp = "span",
+ children,
+ color = "black",
+ size = "default",
+ className,
+ weight = "regular",
+ align = "left",
+ truncated,
+ ...props
+ },
+ ref,
+ ) => {
+ const isMultiLineTruncated = typeof truncated === "number" && truncated >= 1;
+
+ return (
+
+ {children}
+
+ );
+ },
+);
+
+export default Text;
diff --git a/src/components/ui/Text/Text.types.ts b/src/components/ui/Text/Text.types.ts
new file mode 100644
index 0000000..fc51701
--- /dev/null
+++ b/src/components/ui/Text/Text.types.ts
@@ -0,0 +1,23 @@
+type TextSize = "xxs" | "xs" | "sm" | "default" | "md" | "lg" | "xl";
+
+type TextWeight = "regular" | "medium" | "semi-bold" | "bold";
+
+type TextAlign = "left" | "center" | "right";
+
+type TextColor =
+ | "white"
+ | "black"
+ | "primary"
+ | "secondary"
+ | "tertiary"
+ | "quarternary"
+ | "gradient";
+
+export interface TextProps extends React.HTMLAttributes {
+ as?: React.ElementType;
+ color?: TextColor;
+ size?: TextSize;
+ weight?: TextWeight;
+ align?: TextAlign;
+ truncated?: boolean | number;
+}
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 0b0e75d..d1287c8 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -12,13 +12,16 @@
--font-size-xs: 0.875rem;
--font-size-xxs: 0.8125rem;
- --color-white: #fff;
- --color-black: #000;
- --color-text01: #363642;
- --color-text02: #68696e;
- --color-text03: #a6a6ad;
- --color-text04: #e0e0e0;
- --color-text-gradient: linear-gradient(#d444ba, #443fb6);
+ --color-text-white: #fff;
+ --color-text-black: #000;
+ --color-text-primary: #363642;
+ --color-text-secondary: #68696e;
+ --color-text-tertiary: #a6a6ad;
+ --color-text-quarternary: #e0e0e0;
+ --color-text-gradient: linear-gradient(90deg, #d444ba, #443fb6);
+
+ --color-white: #ffffff;
+ --color-black: #000000;
--color-gray100: #f8f8f8;
--color-gray200: #ebecf0;
--color-gray300: #e1e2e8;