Skip to content
Merged
21 changes: 15 additions & 6 deletions src/components/common/dropdownmenu/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export type TMenuItem = {
icon?: React.ReactNode;
onClick: () => void;
active?: boolean;
danger?: boolean;
labelClassName?: string;
};

const easeOut = [0, 0, 0.2, 1] as const;
Expand Down Expand Up @@ -114,19 +116,23 @@ export function DropdownMenu({
}}
className={twMerge(
"group flex w-full items-center justify-between rounded-2xl px-5 py-4 text-left font-body2 transition-ui-fast",
it.active
? "bg-info-blue/10 text-info-blue"
: "text-text-body hover:bg-primary-100/50 hover:text-info-blue",
it.danger
? "text-info-red hover:bg-info-red/10 hover:text-info-red"
: it.active
? "bg-info-blue/10 text-info-blue"
: "text-text-body hover:bg-primary-100/50 hover:text-info-blue",
Comment thread
jjjsun marked this conversation as resolved.
)}
>
<div className="flex min-w-0 flex-1 items-center gap-3">
{it.icon ? (
<span
className={twMerge(
"inline-flex h-5 w-5 items-center justify-center text-text-body",
it.active
? "text-info-blue"
: "group-hover:text-info-blue",
it.danger
? "text-info-red group-hover:text-info-red"
: it.active
? "text-info-blue"
: "group-hover:text-info-blue",
)}
aria-hidden="true"
>
Expand All @@ -137,6 +143,9 @@ export function DropdownMenu({
className={twMerge(
"min-w-0 truncate font-body2 text-left",
it.active && "font-label",
it.danger &&
"text-info-red group-hover:text-info-red",
it.labelClassName,
)}
>
{it.label}
Expand Down
8 changes: 7 additions & 1 deletion src/components/timeline/TimelineBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface ITimelineBarProps {
rowHeight?: number;
rowOffset?: number;
className?: string;
onBarClick?: (bar: ITimelineCampaignBar) => void;
onMenuClick?: (bar: ITimelineCampaignBar) => void; //선택, 추후 이슈로 다룰 예정
}

Expand All @@ -26,6 +27,7 @@ export default function TimelineBar({
rowHeight = TIMELINE_ROW_HEIGHT,
rowOffset = TIMELINE_ROW_OFFSET,
className,
onBarClick,
onMenuClick,
}: ITimelineBarProps) {
const status = TIMELINE_PERFORMANCE_STATUS_STYLE[bar.performanceStatus];
Expand All @@ -43,6 +45,7 @@ export default function TimelineBar({
status.barBg,
className,
)}
onClick={() => onBarClick?.(bar)}
style={{ left, top, width, height: TIMELINE_BAR_HEIGHT }}
>
<div
Expand All @@ -66,7 +69,10 @@ export default function TimelineBar({
type="button"
aria-label="캠페인 메뉴"
className="flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-text-placeholder transition-colors hover:bg-surface-500/5"
onClick={() => onMenuClick?.(bar)}
onClick={(event) => {
event.stopPropagation();
onMenuClick?.(bar);
}}
>
<KebabIcon className="h-3.5 w-3.5" />
</button>
Expand Down
84 changes: 84 additions & 0 deletions src/components/timeline/TimelinePerformancePanel.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useState } from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";

import {
TIMELINE_SUMMARY_PANEL_MOCK,
TIMELINE_SUMMARY_PANEL_NO_AI_MOCK,
} from "@/types/timeline/timeline.mock";

import TimelinePerformancePanel from "./TimelinePerformancePanel";

const meta: Meta<typeof TimelinePerformancePanel> = {
title: "Timeline/PerformancePanel",
component: TimelinePerformancePanel,
parameters: { layout: "fullscreen" },
args: {
onClose: fn(),
onEdit: fn(),
onDelete: fn(),
},
};

export default meta;
type TStory = StoryObj<typeof TimelinePerformancePanel>;

function ClosedPreivew() {
const [open, setOpen] = useState(false);

return (
<>
<div>
<button
type="button"
onClick={() => setOpen(true)}
className="rounded-lg bg-primary-400 px-4 py-2 font-body2 text-surface-100"
>
패널 열기
</button>
</div>
<TimelinePerformancePanel
isOpen={open}
onClose={() => setOpen(false)}
data={TIMELINE_SUMMARY_PANEL_NO_AI_MOCK}
onEdit={fn()}
onDelete={fn()}
/>
</>
);
}

export const Closed: TStory = {
render: () => <ClosedPreivew />,
};

export const Open: TStory = {
args: {
isOpen: true,
data: TIMELINE_SUMMARY_PANEL_NO_AI_MOCK,
},
};

export const OpenWithSummary: TStory = {
args: {
isOpen: true,
data: TIMELINE_SUMMARY_PANEL_MOCK,
},
};

function InteractivePreview() {
const [open, setOpen] = useState(true);
return (
<TimelinePerformancePanel
isOpen={open}
onClose={() => setOpen(false)}
data={TIMELINE_SUMMARY_PANEL_MOCK}
onEdit={fn()}
onDelete={fn()}
/>
);
}

export const Interactive: TStory = {
render: () => <InteractivePreview />,
};
Loading
Loading