feat(chart): split toolbar into indicators row + actions row
When showSma is true, the indicator chips (MA5/20/60 + RSI + MACD) and the action buttons (수평선 / CSV / 전체화면, plus the fullscreen symbol label) were sharing one flex-wrap row. On narrow widths the actions wrapped into the middle of the indicators because `ml-auto` only enforces right-pull while everything fits on one line — once wrap kicks in the right-side group loses its anchor. Split into two rows so wrap in either group stays local: - Indicators row: rendered only when showSma. Hidden in 1D (intraday) where none of these are meaningful, matching prior behavior. - Actions row: always rendered. Leading fullscreen label + `ml-auto` to push the three action buttons right; on narrow widths they wrap among themselves without colliding with indicator chips.
This commit is contained in:
@@ -929,11 +929,80 @@ export function StockChart({ chart, prediction, targets }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={wrapperRef} className={wrapperCls}>
|
<div ref={wrapperRef} className={wrapperCls}>
|
||||||
|
{/*
|
||||||
|
툴바를 2 그룹으로 분리:
|
||||||
|
A) 보조지표 (MA5/20/60 + RSI + MACD) — 일봉 계열에서만 의미. 안 보이면 row 자체 생략.
|
||||||
|
B) 액션 (전체화면 종목 라벨 + 수평선 + CSV + 전체화면 토글) — 항상 표시.
|
||||||
|
같은 줄에 다 묶었을 때 모바일/좁은 폭에서 indicators 와 actions 가 섞여서 wrap 되며
|
||||||
|
"ml-auto" 가 줄바꿈 직전에서만 분리 효과를 주고 그 외엔 actions 가 indicators 사이로 끼어듦.
|
||||||
|
분리하면 indicators wrap 은 indicators 안에서만 일어남 — actions 그룹은 자체 정렬 유지.
|
||||||
|
*/}
|
||||||
|
{showSma && (
|
||||||
|
<div className="mb-1 flex flex-wrap items-center gap-1.5 px-1">
|
||||||
|
{SMA_PRESETS.map((p) => {
|
||||||
|
const on = active.has(p.window);
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={p.window}
|
||||||
|
type="button"
|
||||||
|
onClick={() => toggle(p.window)}
|
||||||
|
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
||||||
|
on
|
||||||
|
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
||||||
|
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
||||||
|
}`}
|
||||||
|
aria-pressed={on}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="inline-block h-2 w-2 rounded-full"
|
||||||
|
style={{ backgroundColor: on ? p.color : "transparent", border: `1px solid ${p.color}` }}
|
||||||
|
/>
|
||||||
|
{p.label}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<span className="mx-1 text-zinc-700">|</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setRsiOn((v) => !v)}
|
||||||
|
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
||||||
|
rsiOn
|
||||||
|
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
||||||
|
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
||||||
|
}`}
|
||||||
|
aria-pressed={rsiOn}
|
||||||
|
title="상대강도지수 (Relative Strength Index, 14일)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="inline-block h-2 w-2 rounded-full"
|
||||||
|
style={{ backgroundColor: rsiOn ? "#e879f9" : "transparent", border: "1px solid #e879f9" }}
|
||||||
|
/>
|
||||||
|
RSI
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setMacdOn((v) => !v)}
|
||||||
|
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
||||||
|
macdOn
|
||||||
|
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
||||||
|
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
||||||
|
}`}
|
||||||
|
aria-pressed={macdOn}
|
||||||
|
title="MACD (12/26/9) — 추세 전환 신호"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="inline-block h-2 w-2 rounded-full"
|
||||||
|
style={{ backgroundColor: macdOn ? "#60a5fa" : "transparent", border: "1px solid #60a5fa" }}
|
||||||
|
/>
|
||||||
|
MACD
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="mb-1 flex flex-wrap items-center gap-1.5 px-1">
|
<div className="mb-1 flex flex-wrap items-center gap-1.5 px-1">
|
||||||
{/*
|
{/*
|
||||||
전체화면 모드 한정 종목 라벨 — 일반 모드는 위에 PriceHero 가 종목명/코드를 크게 보여주지만
|
전체화면 모드 한정 종목 라벨 — 일반 모드는 위에 PriceHero 가 종목명/코드를 크게 보여주지만
|
||||||
fullscreen 은 fixed inset 으로 PriceHero 가 가려져서 무슨 종목 차트인지 식별이 어려워짐.
|
fullscreen 은 fixed inset 으로 PriceHero 가 가려져서 무슨 종목 차트인지 식별이 어려워짐.
|
||||||
툴바 leading 자리에 작은 라벨을 끼워 시각적 노이즈 최소로 보완.
|
actions row leading 자리에 작은 라벨을 끼워 시각적 노이즈 최소로 보완.
|
||||||
(캔버스 위의 CrosshairLabel 과 위치 겹치지 않도록 캔버스가 아닌 툴바에 둠.)
|
(캔버스 위의 CrosshairLabel 과 위치 겹치지 않도록 캔버스가 아닌 툴바에 둠.)
|
||||||
*/}
|
*/}
|
||||||
{fullscreen && (
|
{fullscreen && (
|
||||||
@@ -942,67 +1011,6 @@ export function StockChart({ chart, prediction, targets }: Props) {
|
|||||||
<span className="font-mono text-[10px] text-zinc-500">{chart.code}</span>
|
<span className="font-mono text-[10px] text-zinc-500">{chart.code}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{showSma && (
|
|
||||||
<>
|
|
||||||
{SMA_PRESETS.map((p) => {
|
|
||||||
const on = active.has(p.window);
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={p.window}
|
|
||||||
type="button"
|
|
||||||
onClick={() => toggle(p.window)}
|
|
||||||
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
|
||||||
on
|
|
||||||
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
|
||||||
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
|
||||||
}`}
|
|
||||||
aria-pressed={on}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="inline-block h-2 w-2 rounded-full"
|
|
||||||
style={{ backgroundColor: on ? p.color : "transparent", border: `1px solid ${p.color}` }}
|
|
||||||
/>
|
|
||||||
{p.label}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<span className="mx-1 text-zinc-700">|</span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setRsiOn((v) => !v)}
|
|
||||||
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
|
||||||
rsiOn
|
|
||||||
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
|
||||||
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
|
||||||
}`}
|
|
||||||
aria-pressed={rsiOn}
|
|
||||||
title="상대강도지수 (Relative Strength Index, 14일)"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="inline-block h-2 w-2 rounded-full"
|
|
||||||
style={{ backgroundColor: rsiOn ? "#e879f9" : "transparent", border: "1px solid #e879f9" }}
|
|
||||||
/>
|
|
||||||
RSI
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setMacdOn((v) => !v)}
|
|
||||||
className={`flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] transition ${
|
|
||||||
macdOn
|
|
||||||
? "border-zinc-600 bg-zinc-800/80 text-zinc-100"
|
|
||||||
: "border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"
|
|
||||||
}`}
|
|
||||||
aria-pressed={macdOn}
|
|
||||||
title="MACD (12/26/9) — 추세 전환 신호"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="inline-block h-2 w-2 rounded-full"
|
|
||||||
style={{ backgroundColor: macdOn ? "#60a5fa" : "transparent", border: "1px solid #60a5fa" }}
|
|
||||||
/>
|
|
||||||
MACD
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user