전략평가 차트, 조건 영역 사이즈조절

This commit is contained in:
Macbook
2026-06-20 00:40:30 +09:00
parent 06f837223d
commit 6a5ac71344
2 changed files with 68 additions and 11 deletions
@@ -82,6 +82,10 @@ const RIGHT_KEY = 'seval-right-width';
const RIGHT_OPEN_KEY = 'seval-right-open'; const RIGHT_OPEN_KEY = 'seval-right-open';
const LEFT_DEFAULT = 380; const LEFT_DEFAULT = 380;
const RIGHT_DEFAULT = 440; const RIGHT_DEFAULT = 440;
const STRATEGY_PANEL_HEIGHT_KEY = 'seval-strategy-panel-height';
const STRATEGY_PANEL_MIN = 160;
const STRATEGY_PANEL_MAX = 520;
const STRATEGY_PANEL_DEFAULT = 280;
type LeftTab = 'strategy' | 'market' | 'settings'; type LeftTab = 'strategy' | 'market' | 'settings';
type RightTab = 'signal' | 'indicators' | 'chart' | 'ai'; type RightTab = 'signal' | 'indicators' | 'chart' | 'ai';
@@ -223,6 +227,9 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
const [leftOpen, setLeftOpen] = useState(() => readStoredBool(LEFT_OPEN_KEY, true)); const [leftOpen, setLeftOpen] = useState(() => readStoredBool(LEFT_OPEN_KEY, true));
const [rightWidth, setRightWidth] = useState(() => readMinWidth(RIGHT_KEY, RIGHT_DEFAULT)); const [rightWidth, setRightWidth] = useState(() => readMinWidth(RIGHT_KEY, RIGHT_DEFAULT));
const [rightOpen, setRightOpen] = useState(() => readStoredBool(RIGHT_OPEN_KEY, true)); const [rightOpen, setRightOpen] = useState(() => readStoredBool(RIGHT_OPEN_KEY, true));
const [strategyPanelHeight, setStrategyPanelHeight] = useState(() =>
readStoredSize(STRATEGY_PANEL_HEIGHT_KEY, STRATEGY_PANEL_DEFAULT),
);
/** 종목 탭·종목검색 전용 ticker — 차트 OHLCV·scan-signals 와 분리 (upbitWsBroker ticker 채널) */ /** 종목 탭·종목검색 전용 ticker — 차트 OHLCV·scan-signals 와 분리 (upbitWsBroker ticker 채널) */
const marketTabActive = leftOpen && leftTab === 'market'; const marketTabActive = leftOpen && leftTab === 'market';
@@ -235,10 +242,20 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
const leftRef = useRef(leftWidth); const leftRef = useRef(leftWidth);
const rightRef = useRef(rightWidth); const rightRef = useRef(rightWidth);
const strategyPanelHeightRef = useRef(strategyPanelHeight);
leftRef.current = leftWidth; leftRef.current = leftWidth;
rightRef.current = rightWidth; rightRef.current = rightWidth;
strategyPanelHeightRef.current = strategyPanelHeight;
const onLeftSplit = usePanelResize('vertical', setLeftWidth, () => leftRef.current, 300, 520, v => storeSize(LEFT_KEY, v)); const onLeftSplit = usePanelResize('vertical', setLeftWidth, () => leftRef.current, 300, 520, v => storeSize(LEFT_KEY, v));
const onStrategyPanelSplit = usePanelResize(
'horizontal',
setStrategyPanelHeight,
() => strategyPanelHeightRef.current,
STRATEGY_PANEL_MIN,
STRATEGY_PANEL_MAX,
v => storeSize(STRATEGY_PANEL_HEIGHT_KEY, v),
);
const toggleLeftPanel = useCallback(() => { const toggleLeftPanel = useCallback(() => {
setLeftOpen(prev => { setLeftOpen(prev => {
@@ -983,6 +1000,7 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
<main className={`btd-main${leftOpen ? '' : ' seval-main--left-collapsed'}`}> <main className={`btd-main${leftOpen ? '' : ' seval-main--left-collapsed'}`}>
<div className="btd-main-content seval-main-content"> <div className="btd-main-content seval-main-content">
<div className="seval-main-chart-area">
<StrategyEvaluationChart <StrategyEvaluationChart
market={market} market={market}
timeframe={chartTimeframe} timeframe={chartTimeframe}
@@ -1021,11 +1039,27 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
overlayVisibility={overlayVisibility} overlayVisibility={overlayVisibility}
onSetOverlayVisibility={handleSetOverlayVisibility} onSetOverlayVisibility={handleSetOverlayVisibility}
/> />
</div>
<div
className="btd-splitter btd-splitter--h seval-strategy-splitter"
role="separator"
aria-orientation="horizontal"
aria-label="차트·전략 패널 높이 조절"
aria-valuemin={STRATEGY_PANEL_MIN}
aria-valuemax={STRATEGY_PANEL_MAX}
aria-valuenow={strategyPanelHeight}
onPointerDown={onStrategyPanelSplit}
/>
<div
className="seval-strategy-panel-wrap"
style={{ height: strategyPanelHeight }}
>
<StrategyEvaluationStrategyPanel <StrategyEvaluationStrategyPanel
strategy={selectedStrategy} strategy={selectedStrategy}
editor={strategyEditor} editor={strategyEditor}
/> />
</div> </div>
</div>
</main> </main>
<div <div
+30 -7
View File
@@ -377,11 +377,37 @@
padding: 8px 10px; padding: 8px 10px;
} }
.seval-main-content .seval-chart { .seval-main-chart-area {
flex: 1;
min-height: 140px;
min-width: 0;
display: flex;
flex-direction: column;
}
.seval-main-chart-area .seval-chart {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
} }
.seval-strategy-splitter {
flex-shrink: 0;
margin: 2px 0;
border-radius: 2px;
}
.seval-strategy-panel-wrap {
flex: 0 0 auto;
min-height: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
.seval-strategy-splitter.btd-splitter.se-splitter--active {
background: color-mix(in srgb, var(--btd-gold) 35%, var(--btd-divider));
}
.seval-chart { .seval-chart {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -1273,10 +1299,8 @@
/* ── 중앙 하단 — 목록 방식 전략 설정 ── */ /* ── 중앙 하단 — 목록 방식 전략 설정 ── */
.seval-strategy-panel { .seval-strategy-panel {
position: relative; position: relative;
flex: 0 0 min(40vh, 380px); flex: 1;
min-height: 200px; min-height: 0;
max-height: min(48vh, 440px);
margin-top: 6px;
border: 1px solid var(--se-terminal-border, rgba(255, 255, 255, 0.08)); border: 1px solid var(--se-terminal-border, rgba(255, 255, 255, 0.08));
border-radius: 8px; border-radius: 8px;
background: var(--se-panel-card-bg, var(--se-terminal-bg, color-mix(in srgb, var(--bg) 92%, #000))); background: var(--se-panel-card-bg, var(--se-terminal-bg, color-mix(in srgb, var(--bg) 92%, #000)));
@@ -1285,8 +1309,7 @@
flex-direction: column; flex-direction: column;
} }
.seval-strategy-panel--empty { .seval-strategy-panel--empty {
flex: 0 0 auto; flex: 1;
max-height: none;
min-height: 0; min-height: 0;
padding: 12px 14px; padding: 12px 14px;
} }