From ff8f64bde63e34a48472690c628a15783fa2d480 Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Tue, 14 Oct 2025 22:50:38 +0900 Subject: [PATCH 1/9] =?UTF-8?q?chore:=20callout=20lint=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/src/stories/Callout.stories.tsx | 34 ++++++------ packages/ui/Callout/Callout.tsx | 29 +++------- packages/ui/Callout/constants.ts | 8 +-- packages/ui/Callout/index.tsx | 2 +- packages/ui/Callout/style.css.ts | 66 +++++++++++------------ packages/ui/Callout/types.ts | 2 +- 6 files changed, 59 insertions(+), 82 deletions(-) diff --git a/apps/docs/src/stories/Callout.stories.tsx b/apps/docs/src/stories/Callout.stories.tsx index ebf6546f..936bf01e 100644 --- a/apps/docs/src/stories/Callout.stories.tsx +++ b/apps/docs/src/stories/Callout.stories.tsx @@ -1,9 +1,9 @@ -import { Callout } from "@sopt-makers/ui"; -import { Meta, StoryObj } from "@storybook/react"; +import { Callout } from '@sopt-makers/ui'; +import { Meta, StoryObj } from '@storybook/react'; interface CalloutProps { children: React.ReactNode; - type: "danger" | "information" | "warning"; + type: 'danger' | 'information' | 'warning'; hasIcon?: boolean; buttonLabel?: string; isButtonDisabled?: boolean; @@ -11,35 +11,35 @@ interface CalloutProps { } export default { - title: "Components/Callout", + title: 'Components/Callout', component: Callout, - tags: ["autodocs"], + tags: ['autodocs'], argTypes: { type: { control: 'radio', options: ['danger', 'information', 'warning'] }, - } + }, } as Meta; // danger 콜아웃 스토리 export const Danger: StoryObj = { args: { - children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요", - type: "danger", + children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + type: 'danger', hasIcon: false, }, }; // information 콜아웃 스토리 export const Information: StoryObj = { args: { - children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요", - type: "information", + children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + type: 'information', hasIcon: false, }, }; // warning 콜아웃 스토리 export const Warning: StoryObj = { args: { - children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요", - type: "warning", + children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + type: 'warning', hasIcon: false, }, }; @@ -53,9 +53,9 @@ export const CalloutWithBtn: StoryObj = { isButtonDisabled 옵션으로 disabled state를 확인해보세요. ), - type: "warning", + type: 'warning', hasIcon: true, - buttonLabel: "hover, press 해보세요!", + buttonLabel: 'hover, press 해보세요!', isButtonDisabled: false, }, }; @@ -64,10 +64,10 @@ export const CalloutWithBtn: StoryObj = { export const CalloutWithLongText: StoryObj = { args: { children: - "Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요. Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요.", - type: "information", + 'Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요. Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요.', + type: 'information', hasIcon: true, - buttonLabel: "소셜 계정 재설정하기", + buttonLabel: '소셜 계정 재설정하기', isButtonDisabled: false, }, }; diff --git a/packages/ui/Callout/Callout.tsx b/packages/ui/Callout/Callout.tsx index fc75d7de..fe26320f 100644 --- a/packages/ui/Callout/Callout.tsx +++ b/packages/ui/Callout/Callout.tsx @@ -1,18 +1,7 @@ -import { - IconAlertCircle, - IconChevronRight, - IconInfoCircle, -} from "@sopt-makers/icons"; -import type { ReactNode } from "react"; -import { - buttonIcon, - button, - calloutVariant, - container, - iconVariant, - text, -} from "./style.css"; -import type { CalloutType } from "./types"; +import { IconAlertCircle, IconChevronRight, IconInfoCircle } from '@sopt-makers/icons'; +import type { ReactNode } from 'react'; +import { buttonIcon, button, calloutVariant, container, iconVariant, text } from './style.css'; +import type { CalloutType } from './types'; const icons = { danger: IconAlertCircle, @@ -29,8 +18,7 @@ interface CalloutProps { } function Callout(props: CalloutProps) { - const { children, type, hasIcon, buttonLabel, isButtonDisabled, onClick } = - props; + const { children, type, hasIcon, buttonLabel, isButtonDisabled, onClick } = props; const Icon = icons[type]; return ( @@ -39,12 +27,7 @@ function Callout(props: CalloutProps) {
{children} {buttonLabel ? ( - diff --git a/packages/ui/Callout/constants.ts b/packages/ui/Callout/constants.ts index 6c640b41..8611769e 100644 --- a/packages/ui/Callout/constants.ts +++ b/packages/ui/Callout/constants.ts @@ -1,6 +1,6 @@ -import type { CSSProperties } from "react"; -import theme from "../theme.css"; -import type { CalloutType } from "./types"; +import type { CSSProperties } from 'react'; +import theme from '../theme.css'; +import type { CalloutType } from './types'; export const iconColors: Record = { danger: theme.colors.red500, @@ -18,7 +18,7 @@ export const calloutColors: Record = { borderColor: theme.colors.blueAlpha600, }, warning: { - backgroundColor: "rgba(255, 194, 52, 0.1)", + backgroundColor: 'rgba(255, 194, 52, 0.1)', borderColor: theme.colors.yellow600, }, }; diff --git a/packages/ui/Callout/index.tsx b/packages/ui/Callout/index.tsx index 68a89912..7e77f57e 100644 --- a/packages/ui/Callout/index.tsx +++ b/packages/ui/Callout/index.tsx @@ -1 +1 @@ -export { default } from "./Callout"; +export { default } from './Callout'; diff --git a/packages/ui/Callout/style.css.ts b/packages/ui/Callout/style.css.ts index 613009a0..6014533d 100644 --- a/packages/ui/Callout/style.css.ts +++ b/packages/ui/Callout/style.css.ts @@ -1,47 +1,47 @@ -import { style, styleVariants } from "@vanilla-extract/css"; -import theme from "../theme.css"; -import { calloutColors, iconColors } from "./constants"; +import { style, styleVariants } from '@vanilla-extract/css'; +import theme from '../theme.css'; +import { calloutColors, iconColors } from './constants'; export const container = style({ - display: "flex", - flexDirection: "column", - alignItems: "flex-start", + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', gap: 18, }); export const text = style({ - textAlign: "left", + textAlign: 'left', ...theme.fontsObject.BODY_3_14_M, color: theme.colors.gray30, }); export const button = style({ - display: "flex", - alignItems: "center", + 'display': 'flex', + 'alignItems': 'center', - paddingBottom: 4, + 'paddingBottom': 4, - borderWidth: "0px 0px 0.8px 0px", - borderStyle: "solid", - borderColor: "transparent", - backgroundColor: "transparent", + 'borderWidth': '0px 0px 0.8px 0px', + 'borderStyle': 'solid', + 'borderColor': 'transparent', + 'backgroundColor': 'transparent', - cursor: "pointer", - color: theme.colors.gray30, + 'cursor': 'pointer', + 'color': theme.colors.gray30, ...theme.fontsObject.LABEL_4_12_SB, - ":hover": { + ':hover': { color: theme.colors.gray50, borderColor: theme.colors.gray50, }, - ":active": { + ':active': { color: theme.colors.gray100, borderColor: theme.colors.gray100, }, - ":disabled": { + ':disabled': { color: theme.colors.gray500, - borderColor: "transparent", - cursor: "default", + borderColor: 'transparent', + cursor: 'default', }, }); @@ -67,26 +67,20 @@ const iconBase = style({ width: 20, }); -export const iconVariant = styleVariants(iconColors, (color) => [ - iconBase, - { color }, -]); +export const iconVariant = styleVariants(iconColors, (color) => [iconBase, { color }]); // ▶️ callout styleVariants const calloutBase = style({ - display: "flex", + display: 'flex', gap: 10, - alignItems: "flex-start", - padding: "14px 18px", + alignItems: 'flex-start', + padding: '14px 18px', - border: "1px solid", + border: '1px solid', borderRadius: 10, }); -export const calloutVariant = styleVariants( - calloutColors, - ({ backgroundColor, borderColor }) => [ - calloutBase, - { backgroundColor, borderColor }, - ] -); +export const calloutVariant = styleVariants(calloutColors, ({ backgroundColor, borderColor }) => [ + calloutBase, + { backgroundColor, borderColor }, +]); diff --git a/packages/ui/Callout/types.ts b/packages/ui/Callout/types.ts index 887157fb..a10837b9 100644 --- a/packages/ui/Callout/types.ts +++ b/packages/ui/Callout/types.ts @@ -1 +1 @@ -export type CalloutType = "danger" | "information" | "warning"; +export type CalloutType = 'danger' | 'information' | 'warning'; From 2a99a31ab04238c7912d717e5c0342a35e97137b Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Tue, 14 Oct 2025 23:03:45 +0900 Subject: [PATCH 2/9] =?UTF-8?q?docs:=20storybook=20contents=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5text=20=EB=B3=80=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/src/stories/Callout.stories.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/docs/src/stories/Callout.stories.tsx b/apps/docs/src/stories/Callout.stories.tsx index 936bf01e..021fdf88 100644 --- a/apps/docs/src/stories/Callout.stories.tsx +++ b/apps/docs/src/stories/Callout.stories.tsx @@ -19,10 +19,16 @@ export default { }, } as Meta; +const content = ( + <> + hasIcon 옵션으로 통해 아이콘을 표시할 수 있으며
+ buttonLabel과 onClick 옵션을 통해 버튼의 text와 클릭 핸들러를 설정할 수 있어요 + +); // danger 콜아웃 스토리 export const Danger: StoryObj = { args: { - children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + children: content, type: 'danger', hasIcon: false, }, @@ -30,7 +36,7 @@ export const Danger: StoryObj = { // information 콜아웃 스토리 export const Information: StoryObj = { args: { - children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + children: content, type: 'information', hasIcon: false, }, @@ -38,7 +44,7 @@ export const Information: StoryObj = { // warning 콜아웃 스토리 export const Warning: StoryObj = { args: { - children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요', + children: content, type: 'warning', hasIcon: false, }, From a72fb137679d2a2267f3fd9a03466bc19c9e233e Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Wed, 15 Oct 2025 05:14:32 +0900 Subject: [PATCH 3/9] =?UTF-8?q?docs:=20callout=20props=20case=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/src/stories/Callout.stories.tsx | 57 ++++++++++++++--------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/apps/docs/src/stories/Callout.stories.tsx b/apps/docs/src/stories/Callout.stories.tsx index 021fdf88..73416528 100644 --- a/apps/docs/src/stories/Callout.stories.tsx +++ b/apps/docs/src/stories/Callout.stories.tsx @@ -1,14 +1,8 @@ import { Callout } from '@sopt-makers/ui'; import { Meta, StoryObj } from '@storybook/react'; +import type React from 'react'; -interface CalloutProps { - children: React.ReactNode; - type: 'danger' | 'information' | 'warning'; - hasIcon?: boolean; - buttonLabel?: string; - isButtonDisabled?: boolean; - onClick?: () => void; -} +type CalloutProps = React.ComponentProps; export default { title: 'Components/Callout', @@ -49,21 +43,40 @@ export const Warning: StoryObj = { hasIcon: false, }, }; +// danger+icon 콜아웃 스토리 +export const MultipleIconCallouts: StoryObj = { + render: () => ( +
+ + + +
+ ), +}; -// warning+icon+button 콜아웃 스토리 -export const CalloutWithBtn: StoryObj = { - args: { - children: ( - <> - 버튼이 있는 경우 hasIcon과 무관하게 아이콘이 항상 표시돼요.
- isButtonDisabled 옵션으로 disabled state를 확인해보세요. - - ), - type: 'warning', - hasIcon: true, - buttonLabel: 'hover, press 해보세요!', - isButtonDisabled: false, - }, +export const MultipleButtonCallouts: StoryObj = { + render: () => ( +
+ + <> + 버튼이 있는 경우 hasIcon과 무관하게 아이콘이 항상 표시돼요.
+ isButtonDisabled 옵션으로 disabled state를 확인해보세요. + +
+ + <> + 버튼이 있는 경우 hasIcon과 무관하게 아이콘이 항상 표시돼요.
+ isButtonDisabled 옵션으로 disabled state를 확인해보세요. + +
+ + <> + 버튼이 있는 경우 hasIcon과 무관하게 아이콘이 항상 표시돼요.
+ isButtonDisabled 옵션으로 disabled state를 확인해보세요. + +
+
+ ), }; // 여러줄 텍스트 콜아웃 스토리 From e6b7c8e0a82104ada33729daf5c772b89badb0cf Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Wed, 15 Oct 2025 05:50:35 +0900 Subject: [PATCH 4/9] =?UTF-8?q?style:=20callout=20min=20style=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/Callout/style.css.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/ui/Callout/style.css.ts b/packages/ui/Callout/style.css.ts index 6014533d..0640a1ba 100644 --- a/packages/ui/Callout/style.css.ts +++ b/packages/ui/Callout/style.css.ts @@ -76,6 +76,8 @@ const calloutBase = style({ alignItems: 'flex-start', padding: '14px 18px', + minWidth: 358, + minHeight: 50, border: '1px solid', borderRadius: 10, }); From 894458acdaee66c2d5df524bb95f954210ed30f6 Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Wed, 15 Oct 2025 05:54:35 +0900 Subject: [PATCH 5/9] =?UTF-8?q?docs:=20callout=20argTypes=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/src/stories/Callout.stories.tsx | 61 +++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/apps/docs/src/stories/Callout.stories.tsx b/apps/docs/src/stories/Callout.stories.tsx index 73416528..6a938155 100644 --- a/apps/docs/src/stories/Callout.stories.tsx +++ b/apps/docs/src/stories/Callout.stories.tsx @@ -9,7 +9,52 @@ export default { component: Callout, tags: ['autodocs'], argTypes: { - type: { control: 'radio', options: ['danger', 'information', 'warning'] }, + children: { + description: '콜아웃의 내용을 작성합니다.', + control: 'text', + table: { + type: { summary: 'ReactNode' }, + }, + }, + type: { + description: '콜아웃의 타입을 지정합니다. 타입에 따라 색상과 아이콘이 변경됩니다.', + control: 'radio', + options: ['danger', 'information', 'warning'], + table: { + type: { summary: 'danger | information | warning' }, + defaultValue: { summary: 'information' }, + }, + }, + hasIcon: { + description: '아이콘 표시 여부를 지정합니다. buttonLabel이 있으면 이 옵션과 무관하게 아이콘이 항상 표시됩니다.', + control: 'boolean', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' }, + }, + }, + buttonLabel: { + description: '버튼의 텍스트를 지정합니다. 지정하면 버튼이 표시됩니다.', + control: 'text', + table: { + type: { summary: 'string' }, + }, + }, + isButtonDisabled: { + description: '버튼의 비활성화 상태를 지정합니다.', + control: 'boolean', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' }, + }, + }, + onClick: { + description: '버튼 클릭 시 실행할 함수를 지정합니다.', + action: 'clicked', + table: { + type: { summary: '() => void' }, + }, + }, }, } as Meta; @@ -30,7 +75,7 @@ export const Danger: StoryObj = { // information 콜아웃 스토리 export const Information: StoryObj = { args: { - children: content, + children: 'hasIcon 옵션으로 통해 아이콘을 표시할 수 있으며 ', type: 'information', hasIcon: false, }, @@ -38,7 +83,7 @@ export const Information: StoryObj = { // warning 콜아웃 스토리 export const Warning: StoryObj = { args: { - children: content, + children: 'buttonLabel과 onClick 옵션을 통해 버튼의 text와 클릭 핸들러를 설정할 수 있어요', type: 'warning', hasIcon: false, }, @@ -90,3 +135,13 @@ export const CalloutWithLongText: StoryObj = { isButtonDisabled: false, }, }; + +export const CalloutWithShortText: StoryObj = { + args: { + children: '짧은 텍스트 ', + type: 'information', + hasIcon: true, + buttonLabel: '짧은 라벨', + isButtonDisabled: false, + }, +}; From 4b5da41b8a15d4efa95a00d3a8eff40a02e429f7 Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Sun, 28 Dec 2025 00:35:48 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20buttonLabel=EC=9D=80=20=EB=8B=A8?= =?UTF-8?q?=EB=8F=85=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=97=86=EB=8A=94=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20usage=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/Callout/Callout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/Callout/Callout.tsx b/packages/ui/Callout/Callout.tsx index fe26320f..5613ae12 100644 --- a/packages/ui/Callout/Callout.tsx +++ b/packages/ui/Callout/Callout.tsx @@ -26,7 +26,7 @@ function Callout(props: CalloutProps) { {buttonLabel || hasIcon ? : null}
{children} - {buttonLabel ? ( + {children && buttonLabel ? ( ) : null}
From 08f46197963d0d570d207f93ecd09410e35ed5f3 Mon Sep 17 00:00:00 2001 From: ljh0608 Date: Sun, 28 Dec 2025 01:07:46 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20Callout=20story=20default=20value=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/src/stories/Callout.stories.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/docs/src/stories/Callout.stories.tsx b/apps/docs/src/stories/Callout.stories.tsx index 6a938155..8573765f 100644 --- a/apps/docs/src/stories/Callout.stories.tsx +++ b/apps/docs/src/stories/Callout.stories.tsx @@ -22,7 +22,6 @@ export default { options: ['danger', 'information', 'warning'], table: { type: { summary: 'danger | information | warning' }, - defaultValue: { summary: 'information' }, }, }, hasIcon: { @@ -30,7 +29,7 @@ export default { control: 'boolean', table: { type: { summary: 'boolean' }, - defaultValue: { summary: 'false' }, + defaultValue: { summary: 'true' }, }, }, buttonLabel: {