From b4dcebf758830a4a649a51d98f1bf1c58ef4b8dc Mon Sep 17 00:00:00 2001 From: Macbook Date: Sat, 30 May 2026 02:55:41 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EC=B1=A0?= =?UTF-8?q?=ED=8A=B8=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.css | 4 +++ frontend/src/components/TradingChart.tsx | 32 ++++++++++++++----- frontend/src/styles/tradeNotificationList.css | 7 ++-- frontend/src/utils/ChartManager.ts | 6 +++- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index 8fc5399..e39acd0 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -942,6 +942,10 @@ html.theme-blue { overflow-y: auto; overflow-x: hidden; } +/* 캔들 전체보기 — 보조지표 스크롤 영역 잠금 (전환 시 scrollTop 드리프트 방지) */ +.tv-chart-wrap--candle-only { + overflow-y: hidden; +} .tv-chart-wrap::-webkit-scrollbar { width: 6px; } .tv-chart-wrap::-webkit-scrollbar-track { background: transparent; } .tv-chart-wrap::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 3px; } diff --git a/frontend/src/components/TradingChart.tsx b/frontend/src/components/TradingChart.tsx index 9739bd9..48b289e 100644 --- a/frontend/src/components/TradingChart.tsx +++ b/frontend/src/components/TradingChart.tsx @@ -347,8 +347,9 @@ const TradingChart: React.FC = ({ return; } + const candleOnly = candleOnlyModeRef.current; let required: number; - if (candleOnlyModeRef.current) { + if (candleOnly) { mgr.applyCandleOnlyLayout(true, wrapperH); required = wrapperH; } else { @@ -358,14 +359,16 @@ const TradingChart: React.FC = ({ required = mgr.resetPaneHeights(wrapperH); } - if (paneLayoutClamp) { + const w = wrapper.clientWidth; + + if (candleOnly || paneLayoutClamp) { + // 전체보기·미니차트: 래퍼 높이에 고정 resize (autoSize 피드백 루프·무한 스크롤 방지) try { - const w = wrapper.clientWidth; if (w > 0 && wrapperH > 0) mgr.resize(w, wrapperH); } catch { /* ok */ } - } - - if (!paneLayoutClamp && required > wrapperH + 4) { + container.style.height = `${wrapperH}px`; + if (candleOnly) wrapper.scrollTop = 0; + } else if (required > wrapperH + 4) { container.style.height = `${required}px`; } else { container.style.height = ''; @@ -979,9 +982,22 @@ const TradingChart: React.FC = ({ if (width === prevW && height === prevH) return; // 이전 크기가 0이었다가 유효해진 경우 (= display:none → visible 전환) const wasHidden = prevW <= 0 || prevH <= 0; - prevW = width; prevH = height; if (width <= 0 || height <= 0) return; + // 캔들 전체보기: 컨테이너가 래퍼보다 커지면 즉시 클램프 (ResizeObserver ↔ autoSize 루프 차단) + if (candleOnlyModeRef.current) { + const wh = wrapperRef.current?.clientHeight ?? 0; + if (wh > 0 && height > wh + 4) { + prevW = width; + prevH = wh; + const m = managerRef.current; + if (m) applyPaneLayout(m); + return; + } + } + + prevW = width; prevH = height; + if (resizeDebounceRef.current) clearTimeout(resizeDebounceRef.current); resizeDebounceRef.current = window.setTimeout(() => { resizeDebounceRef.current = null; @@ -1426,7 +1442,7 @@ const TradingChart: React.FC = ({ // wrapperRef: 스크롤 영역 (overflow-y: auto → App.css .tv-chart-wrap)
diff --git a/frontend/src/styles/tradeNotificationList.css b/frontend/src/styles/tradeNotificationList.css index a9b4425..2440568 100644 --- a/frontend/src/styles/tradeNotificationList.css +++ b/frontend/src/styles/tradeNotificationList.css @@ -1160,14 +1160,15 @@ ul.tnl-list.tnl-list--grid { min-height: 300px; } -/* 그리드형 — 상세 메타와 투자전략 구분선 사이 여백 축소 */ +/* 그리드형 — 메타 하단 빈 공간 제거, 구분선·투자전략 간격 분리 */ .tnl-summary-card--grid .tnl-summary-meta { flex: 0 1 auto; + margin-bottom: -4px; } .tnl-summary-card--grid .tnl-summary-strategy-field { - margin-top: -6px; - padding-top: 2px; + margin-top: 0; + padding-top: 8px; } .tnl-row--grid.tnl-row--unread .tnl-summary-card { diff --git a/frontend/src/utils/ChartManager.ts b/frontend/src/utils/ChartManager.ts index b3b529c..6e0a750 100644 --- a/frontend/src/utils/ChartManager.ts +++ b/frontend/src/utils/ChartManager.ts @@ -2643,9 +2643,13 @@ export class ChartManager { visible: false, } as Parameters['applyOptions']>[0]); } catch { /* ok */ } - this.container.style.height = ''; this._resetPaneHeightsCandleFullscreen(availableHeight); this._hideAllSubPaneIndicators(); + const H = availableHeight && availableHeight > 0 ? availableHeight : 0; + const W = this.container.clientWidth; + if (H > 0 && W > 0) { + try { this.chart.resize(W, H); } catch { /* ok */ } + } } else { this.restoreFromCandleFullscreen(availableHeight); }