트레이딩창 UI 배치 및 UX 수정 및 기획서 추가

This commit is contained in:
2026-02-24 15:43:56 +09:00
parent 19ebb1c6ea
commit a16af8ad7d
16 changed files with 1615 additions and 479 deletions

View File

@@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface DashboardLayoutProps {
header: ReactNode;
header?: ReactNode;
chart: ReactNode;
orderBook: ReactNode;
orderForm: ReactNode;
@@ -14,8 +14,9 @@ interface DashboardLayoutProps {
}
/**
* @description 트레이드 본문 레이아웃을 구성합니다. 상단 차트 영역은 보임/숨김 토글을 지원합니다.
* @see features/trade/components/layout/TradeDashboardContent.tsx 상위 컴포넌트에서 차트 토글 상태를 관리하고 본 레이아웃에 전달합니다.
* @description 트레이드 본문을 업비트 스타일의 2단 레이아웃으로 렌더링합니다.
* @summary UI 흐름: TradeDashboardContent -> DashboardLayout -> 상단(차트) + 하단(호가/주문) 배치
* @see features/trade/components/layout/TradeDashboardContent.tsx - 차트 토글 상태와 슬롯 컴포넌트를 전달합니다.
*/
export function DashboardLayout({
header,
@@ -29,54 +30,46 @@ export function DashboardLayout({
return (
<div
className={cn(
"flex flex-col bg-background dark:bg-[linear-gradient(135deg,rgba(53,35,86,0.18),rgba(13,13,20,0.98))]",
// Mobile: Scrollable page height
"min-h-[calc(100vh-64px)]",
// Desktop: Fixed height, no window scroll
"xl:h-[calc(100vh-64px)] xl:overflow-hidden",
"flex h-full min-h-0 flex-col bg-background dark:bg-[linear-gradient(135deg,rgba(53,35,86,0.18),rgba(13,13,20,0.98))]",
className,
)}
>
{/* 1. Header Area */}
<div className="flex-none border-b border-brand-100 bg-white dark:border-brand-800/45 dark:bg-brand-900/22">
{header}
</div>
{/* ========== 1. OPTIONAL HEADER AREA ========== */}
{header && (
<div className="flex-none border-b border-brand-100 bg-white dark:border-brand-800/45 dark:bg-brand-900/22">
{header}
</div>
)}
{/* 2. Main Content Area */}
<div
className={cn(
"flex-1 min-h-0 overflow-y-auto",
"xl:overflow-hidden",
)}
>
<div className="flex min-h-full flex-col xl:h-full xl:min-h-0">
{/* ========== CHART SECTION ========== */}
<section className="flex-none border-b border-border dark:border-brand-800/45">
<div className="flex items-center justify-between gap-2 bg-muted/20 px-3 py-1.5 dark:bg-brand-900/30 sm:px-4">
<div className="min-w-0">
<p className="text-xs font-semibold text-foreground dark:text-brand-50 sm:text-sm">
{/* ========== 2. MAIN CONTENT AREA ========== */}
<div className="flex-1 min-h-0 overflow-y-auto xl:overflow-hidden">
<div className="flex min-h-full flex-col xl:h-full xl:min-h-0 xl:overflow-hidden">
{/* ========== TOP: CHART AREA ========== */}
<section className="flex min-h-0 flex-col border-b border-border dark:border-brand-800/45 xl:h-[34%] xl:min-h-[200px]">
{/* 모바일 전용 차트 토글 */}
<div className="flex items-center justify-between gap-2 bg-muted/15 px-3 py-1.5 dark:bg-brand-900/25 sm:px-4 xl:hidden">
<div className="flex min-w-0 items-center gap-2">
<span className="h-2 w-2 rounded-full bg-green-400 shadow-[0_0_6px_rgba(74,222,128,0.6)]" />
<p className="text-xs font-semibold text-foreground dark:text-brand-50">
</p>
<p className="text-[10px] text-muted-foreground dark:text-brand-100/70 sm:text-[11px]">
.
</p>
</div>
{/* UI 흐름: 차트 토글 버튼 -> onToggleChart 호출 -> TradeDashboardContent의 상태 변경 -> 차트 wrapper 높이 반영 */}
{/* UI 흐름: 토글 클릭 -> onToggleChart -> 상위 상태 변경 -> 차트 표시/숨김 */}
<Button
type="button"
variant="outline"
size="sm"
onClick={onToggleChart}
className="h-7 gap-1 border-brand-200 bg-white px-2 text-[11px] text-brand-700 hover:bg-brand-50 dark:border-brand-700/55 dark:bg-brand-900/35 dark:text-brand-100 dark:hover:bg-brand-800/35 sm:h-8 sm:px-3 sm:text-xs"
className="h-6 gap-1 border-brand-200 bg-white/70 px-2 text-[11px] text-brand-700 hover:bg-brand-50 dark:border-brand-700/55 dark:bg-brand-900/35 dark:text-brand-100 dark:hover:bg-brand-800/35 sm:h-7 sm:px-3"
aria-expanded={isChartVisible}
>
{isChartVisible ? (
<>
<ChevronUp className="h-3.5 w-3.5" />
<ChevronUp className="h-3 w-3" />
</>
) : (
<>
<ChevronDown className="h-3.5 w-3.5" />
<ChevronDown className="h-3 w-3" />
</>
)}
</Button>
@@ -84,28 +77,28 @@ export function DashboardLayout({
<div
className={cn(
"overflow-hidden border-t border-border/70 transition-[max-height,opacity] duration-200 dark:border-brand-800/45",
isChartVisible ? "max-h-[56vh] opacity-100" : "max-h-0 opacity-0",
"overflow-hidden border-t border-border/70 transition-[max-height,opacity] duration-300 dark:border-brand-800/45 xl:flex-1 xl:min-h-0 xl:max-h-none xl:opacity-100",
isChartVisible ? "max-h-[64vh] opacity-100" : "max-h-0 opacity-0",
)}
>
<div className="h-[34vh] min-h-[280px] w-full sm:h-[40vh] xl:h-[34vh] 2xl:h-[38vh]">
<div className="h-[29vh] min-h-[200px] w-full sm:h-[33vh] xl:h-full xl:min-h-0">
{chart}
</div>
</div>
</section>
{/* ========== ORDERBOOK + ORDER SECTION ========== */}
<div className="flex flex-1 min-h-0 flex-col xl:flex-row xl:overflow-hidden">
<section className="flex min-h-0 flex-col border-b border-border dark:border-brand-800/45 xl:flex-1 xl:border-b-0 xl:border-r">
<div className="h-[390px] min-h-0 sm:h-[430px] xl:h-full">
{/* ========== BOTTOM: ORDERBOOK + ORDER AREA ========== */}
<section className="flex flex-1 min-h-0 flex-col xl:grid xl:grid-cols-[minmax(0,1fr)_480px] 2xl:grid-cols-[minmax(0,1fr)_540px] xl:overflow-hidden">
<div className="flex min-h-0 flex-col border-b border-border dark:border-brand-800/45 xl:border-b-0 xl:border-r">
<div className="min-h-0 xl:h-full xl:min-h-0">
{orderBook}
</div>
</section>
</div>
<section className="flex min-h-0 flex-col bg-background dark:bg-brand-900/12 xl:w-[430px] 2xl:w-[470px]">
<div className="min-h-[320px] xl:h-full">{orderForm}</div>
</section>
</div>
<div className="flex min-h-0 flex-col bg-background dark:bg-brand-900/12">
<div className="min-h-[280px] xl:h-full xl:min-h-0">{orderForm}</div>
</div>
</section>
</div>
</div>
</div>