Skip to content

Commit 3a55e20

Browse files
authored
Merge pull request #58 from SOPT-all/feat/benefit-component/#55
[feat/#55] 혜택가 컴포넌트 구현
2 parents cc27041 + 810f4c1 commit 3a55e20

File tree

8 files changed

+234
-8
lines changed

8 files changed

+234
-8
lines changed

src/App.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
1-
import { ProductSummary } from "./pages/home/components/product-summary/product-summary";
1+
import { MembershipBenefit } from "./shared/components/benefit/membership-benefit";
2+
import { MoreBenefit } from "./shared/components/benefit/more-benefit";
3+
import { PayBenefit } from "./shared/components/benefit/pay-benefit";
4+
import { MEMBERSHIP_DATA, PAY_BENEFITS_DATA } from "./shared/constants/benefit";
25
import * as styles from "./test.css";
36

47
function App() {
58
return (
69
<div className={styles.test}>
7-
<ProductSummary />
10+
<MembershipBenefit
11+
description={MEMBERSHIP_DATA.description}
12+
price={MEMBERSHIP_DATA.price}
13+
unit={MEMBERSHIP_DATA.unit}
14+
badges={MEMBERSHIP_DATA.badges}
15+
/>
16+
{PAY_BENEFITS_DATA.map((benefit) => (
17+
<PayBenefit
18+
key={benefit.id}
19+
title={benefit.title}
20+
description={benefit.desc}
21+
/>
22+
))}
23+
<MoreBenefit />
824
</div>
925
);
1026
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { color } from "@/shared/styles/tokens/color.css";
2+
import { typographyVars } from "@/shared/styles/typography.css";
3+
import { style } from "@vanilla-extract/css";
4+
import { recipe } from "@vanilla-extract/recipes";
5+
6+
export const container = recipe({
7+
base: {
8+
display: "flex",
9+
flex: "0 0 auto",
10+
flexDirection: "column",
11+
justifyContent: "space-between",
12+
13+
width: "fit-content",
14+
height: "12.2rem",
15+
padding: "1.6rem 1.2rem",
16+
borderRadius: "12px",
17+
},
18+
variants: {
19+
type: {
20+
"membership-benefit": {
21+
backgroundColor: color.white[300],
22+
},
23+
"pay-benefit": {
24+
backgroundColor: color.white[200],
25+
},
26+
"benefit-more": {
27+
backgroundColor: color.white[300],
28+
},
29+
},
30+
},
31+
});
32+
33+
export const benefitTitle = style({
34+
display: "flex",
35+
flexDirection: "column",
36+
gap: "0.2rem",
37+
width: "fit-content",
38+
});
39+
40+
export const benefitContent = recipe({
41+
base: {
42+
display: "flex",
43+
gap: "0.3rem",
44+
width: "fit-content",
45+
},
46+
variants: {
47+
type: {
48+
"membership-benefit": {
49+
maxWidth: "15.3rem",
50+
},
51+
"pay-benefit": {
52+
maxWidth: "8.9rem",
53+
},
54+
"benefit-more": {
55+
maxWidth: "4.6rem",
56+
},
57+
},
58+
},
59+
});
60+
61+
export const benefitBadge = style({
62+
padding: "0.4rem 0.6rem",
63+
borderRadius: "0.2px",
64+
backgroundColor: color.brand[200],
65+
});
66+
67+
// 공통되는 텍스트 스타일
68+
export const text = recipe({
69+
base: {
70+
...typographyVars.body3,
71+
color: color.black[100],
72+
whiteSpace: "pre-line",
73+
},
74+
variants: {
75+
type: {
76+
lg: {
77+
...typographyVars.heading2,
78+
},
79+
md: {
80+
...typographyVars.body1,
81+
},
82+
sm: {
83+
...typographyVars.caption2,
84+
},
85+
},
86+
color: {
87+
brand: {
88+
color: color.brand[100],
89+
},
90+
black: {
91+
color: color.black[200],
92+
},
93+
gray: {
94+
color: color.gray[100],
95+
},
96+
},
97+
},
98+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as styles from "./base-benefit.css";
2+
import type { ReactNode } from "react";
3+
4+
interface BaseProps {
5+
type: "membership-benefit" | "pay-benefit" | "benefit-more";
6+
children: ReactNode;
7+
}
8+
9+
export const BaseBenefit = ({ type, children }: BaseProps) => {
10+
return <div className={styles.container({ type })}>{children}</div>;
11+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { addComma } from "@/shared/utils/add-comma";
2+
import { BaseBenefit } from "./base-benefit";
3+
import * as styles from "./base-benefit.css";
4+
5+
interface MembershipBenefitProps {
6+
description: string;
7+
price: number;
8+
unit: string;
9+
badges: string[];
10+
}
11+
12+
export const MembershipBenefit = ({
13+
description,
14+
price,
15+
unit,
16+
badges,
17+
}: MembershipBenefitProps) => {
18+
return (
19+
<BaseBenefit type="membership-benefit">
20+
<div className={styles.benefitTitle}>
21+
<div className={styles.text({ type: "sm", color: "gray" })}>
22+
{description}
23+
</div>
24+
<div>
25+
<span className={styles.text({ type: "lg", color: "brand" })}>
26+
{addComma(String(price))}
27+
</span>
28+
<span className={styles.text({ type: "md", color: "brand" })}>
29+
{unit}
30+
</span>
31+
</div>
32+
</div>
33+
<div className={styles.benefitContent({ type: "membership-benefit" })}>
34+
{badges.map((badge, index) => (
35+
<div
36+
key={index}
37+
className={`${styles.benefitBadge} ${styles.text({ type: "sm", color: "brand" })}`}>
38+
{badge}
39+
</div>
40+
))}
41+
</div>
42+
</BaseBenefit>
43+
);
44+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Benefit as IconPlus } from "@/assets/svg";
2+
import { BaseBenefit } from "./base-benefit";
3+
import * as styles from "./base-benefit.css";
4+
5+
export const MoreBenefit = () => {
6+
return (
7+
<BaseBenefit type="benefit-more">
8+
<IconPlus />
9+
<div
10+
className={`${styles.benefitContent({ type: "benefit-more" })} ${styles.text()}`}>
11+
혜택
12+
<br />
13+
더보기
14+
</div>
15+
</BaseBenefit>
16+
);
17+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { BaseBenefit } from "./base-benefit";
2+
import * as styles from "./base-benefit.css";
3+
4+
interface PayBenefitProps {
5+
title: string;
6+
description: string;
7+
}
8+
9+
export const PayBenefit = ({ title, description }: PayBenefitProps) => {
10+
return (
11+
<BaseBenefit type="pay-benefit">
12+
<div className={styles.benefitTitle}>
13+
<span className={styles.text({ type: "sm", color: "gray" })}>
14+
결제 혜택
15+
</span>
16+
<span className={styles.text({ type: "md", color: "black" })}>
17+
{title}
18+
</span>
19+
</div>
20+
<div
21+
className={`${styles.benefitContent({ type: "pay-benefit" })} ${styles.text({ type: "sm", color: "gray" })}`}>
22+
{description}
23+
</div>
24+
</BaseBenefit>
25+
);
26+
};

src/shared/constants/benefit.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const MEMBERSHIP_DATA = {
2+
description: "월 1,200원 멤버십 가입시 혜택가",
3+
price: 7111,
4+
unit: "원",
5+
badges: ["4,000원 쿠폰", "25% 할인"],
6+
};
7+
8+
export const PAY_BENEFITS_DATA = [
9+
{ id: 1, title: "토스 페이", desc: "4만원 이상 결제 시 1% 할인" },
10+
{ id: 2, title: "Npay", desc: "기본 최대 할인\n 1%" },
11+
] as const;

src/test.css.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { style } from "@vanilla-extract/css";
22

33
export const test = style({
4+
width: "100%",
5+
padding: "1rem",
46
display: "flex",
5-
flexDirection: "column",
6-
gap: "10px",
7-
padding: "1.6rem",
8-
});
7+
gap: "0.6rem",
8+
overflowX: "auto",
99

10-
export const bigElement = style({
11-
height: "120vh",
10+
selectors: {
11+
"&::-webkit-scrollbar": {
12+
display: "none",
13+
},
14+
},
1215
});

0 commit comments

Comments
 (0)