Skip to content

Commit

Permalink
Merge pull request #97 from sopt-makers/feat/#92-callout
Browse files Browse the repository at this point in the history
feat(Callout) : Callout 컴포넌트 개발
  • Loading branch information
sohee-K authored Jun 13, 2024
2 parents 90243cc + 423f97a commit 3cdf863
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 0 deletions.
70 changes: 70 additions & 0 deletions apps/docs/src/stories/Callout.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Callout } from "@sopt-makers/ui";
import { Meta, StoryObj } from "@storybook/react";

interface CalloutProps {
children: React.ReactNode;
type: "danger" | "information" | "warning";
hasIcon?: boolean;
buttonLabel?: string;
isButtonDisabled?: boolean;
onClick?: () => void;
}

export default {
title: "Components/Callout",
component: Callout,
tags: ["autodocs"],
} as Meta<CalloutProps>;

// danger 콜아웃 스토리
export const Danger: StoryObj<CalloutProps> = {
args: {
children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요",
type: "danger",
hasIcon: false,
},
};
// information 콜아웃 스토리
export const Information: StoryObj<CalloutProps> = {
args: {
children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요",
type: "information",
hasIcon: false,
},
};
// warning 콜아웃 스토리
export const Warning: StoryObj<CalloutProps> = {
args: {
children: "hasIcon 옵션으로 통해 아이콘을 표시할 수 있어요",
type: "warning",
hasIcon: false,
},
};

// warning+icon+button 콜아웃 스토리
export const CalloutWithBtn: StoryObj<CalloutProps> = {
args: {
children: (
<>
버튼이 있는 경우 hasIcon과 무관하게 아이콘이 항상 표시돼요. <br />
isButtonDisabled 옵션으로 disabled state를 확인해보세요.
</>
),
type: "warning",
hasIcon: true,
buttonLabel: "hover, press 해보세요!",
isButtonDisabled: false,
},
};

// 여러줄 텍스트 콜아웃 스토리
export const CalloutWithLongText: StoryObj<CalloutProps> = {
args: {
children:
"Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요. Facebook 정책이 변경되어, 앞으로 Facebook 로그인이 불가해요. 다른 계정으로 재설정 부탁드려요.",
type: "information",
hasIcon: true,
buttonLabel: "소셜 계정 재설정하기",
isButtonDisabled: false,
},
};
57 changes: 57 additions & 0 deletions packages/ui/Callout/Callout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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,
information: IconInfoCircle,
warning: IconAlertCircle,
};
interface CalloutProps {
children: ReactNode;
type: CalloutType;
hasIcon?: boolean;
buttonLabel?: string;
isButtonDisabled?: boolean;
onClick?: () => void;
}

function Callout(props: CalloutProps) {
const { children, type, hasIcon, buttonLabel, isButtonDisabled, onClick } =
props;
const Icon = icons[type];

return (
<aside className={calloutVariant[type]}>
{buttonLabel || hasIcon ? <Icon className={iconVariant[type]} /> : null}
<div className={container}>
<span className={text}>{children}</span>
{buttonLabel ? (
<button
className={button}
disabled={isButtonDisabled}
onClick={onClick}
type="button"
>
<span>{buttonLabel}</span>
<IconChevronRight className={buttonIcon} />
</button>
) : null}
</div>
</aside>
);
}

export default Callout;
24 changes: 24 additions & 0 deletions packages/ui/Callout/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { CSSProperties } from "react";
import theme from "../theme.css";
import type { CalloutType } from "./types";

export const iconColors: Record<CalloutType, string> = {
danger: theme.colors.red500,
information: theme.colors.blue500,
warning: theme.colors.yellow500,
};

export const calloutColors: Record<CalloutType, CSSProperties> = {
danger: {
backgroundColor: theme.colors.redAlpha100,
borderColor: theme.colors.red600,
},
information: {
backgroundColor: theme.colors.blueAlpha100,
borderColor: theme.colors.blueAlpha600,
},
warning: {
backgroundColor: "rgba(255, 194, 52, 0.1)",
borderColor: theme.colors.yellow600,
},
};
1 change: 1 addition & 0 deletions packages/ui/Callout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./Callout";
92 changes: 92 additions & 0 deletions packages/ui/Callout/style.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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",
gap: 18,
});

export const text = style({
textAlign: "left",
...theme.fontsObject.BODY_3_14_M,
color: theme.colors.gray30,
});

export const button = style({
display: "flex",
alignItems: "center",

paddingBottom: 4,

borderWidth: "0px 0px 0.8px 0px",
borderStyle: "solid",
borderColor: "transparent",
backgroundColor: "transparent",

cursor: "pointer",
color: theme.colors.gray30,
...theme.fontsObject.LABEL_4_12_SB,

":hover": {
color: theme.colors.gray50,
borderColor: theme.colors.gray50,
},
":active": {
color: theme.colors.gray100,
borderColor: theme.colors.gray100,
},
":disabled": {
color: theme.colors.gray500,
borderColor: "transparent",
cursor: "default",
},
});

export const buttonIcon = style({
width: 16,
color: theme.colors.gray30,
selectors: {
[`${button}:hover &`]: {
color: theme.colors.gray50,
},
[`${button}:active &`]: {
color: theme.colors.gray100,
},
[`${button}:disabled &`]: {
color: theme.colors.gray500,
},
},
});

// ▶️ icon styleVariants
const iconBase = style({
flexShrink: 0,
width: 20,
});

export const iconVariant = styleVariants(iconColors, (color) => [
iconBase,
{ color },
]);

// ▶️ callout styleVariants
const calloutBase = style({
display: "flex",
gap: 10,
alignItems: "flex-start",
padding: "14px 18px",

border: "1px solid",
borderRadius: 10,
});

export const calloutVariant = styleVariants(
calloutColors,
({ backgroundColor, borderColor }) => [
calloutBase,
{ backgroundColor, borderColor },
]
);
1 change: 1 addition & 0 deletions packages/ui/Callout/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type CalloutType = "danger" | "information" | "warning";
1 change: 1 addition & 0 deletions packages/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type { ToastOptionType } from './Toast';
export { TextField, TextArea, SearchField } from './Input';
export { default as Tag } from "./Tag";
export { default as Chip } from './Chip';
export { default as Callout } from "./Callout";

// test component
export { default as Test } from './Test';

0 comments on commit 3cdf863

Please sign in to comment.