매매 시그널 알림 우측패널 동작 수정
This commit is contained in:
@@ -22,12 +22,17 @@ export interface TradeNotificationHScrollPaneProps {
|
||||
/** 스크린리더용 영역 설명 */
|
||||
label: string;
|
||||
children: React.ReactNode;
|
||||
/** 스크롤 시 뷰포트에 완전히 보이지 않는 차트 카드 라벨 숨김 */
|
||||
clipPeekLabels?: boolean;
|
||||
}
|
||||
|
||||
const PEEK_LABEL_THRESHOLD = 0.99;
|
||||
|
||||
const TradeNotificationHScrollPane: React.FC<TradeNotificationHScrollPaneProps> = ({
|
||||
className = '',
|
||||
label,
|
||||
children,
|
||||
clipPeekLabels = false,
|
||||
}) => {
|
||||
const viewportRef = useRef<HTMLDivElement>(null);
|
||||
const [canScroll, setCanScroll] = useState(false);
|
||||
@@ -46,6 +51,31 @@ const TradeNotificationHScrollPane: React.FC<TradeNotificationHScrollPaneProps>
|
||||
setAtEnd(!overflow || el.scrollLeft >= max - 2);
|
||||
}, []);
|
||||
|
||||
const bindPeekLabelClip = useCallback(() => {
|
||||
const viewport = viewportRef.current;
|
||||
if (!viewport || !clipPeekLabels) return () => {};
|
||||
|
||||
const applyPeek = (card: HTMLElement, ratio: number) => {
|
||||
card.classList.toggle('tnl-chart-card--peek', ratio < PEEK_LABEL_THRESHOLD);
|
||||
};
|
||||
|
||||
const cards = Array.from(viewport.querySelectorAll<HTMLElement>('.tnl-chart-card'));
|
||||
if (cards.length === 0) return () => {};
|
||||
|
||||
const io = new IntersectionObserver(
|
||||
entries => {
|
||||
entries.forEach(entry => applyPeek(entry.target as HTMLElement, entry.intersectionRatio));
|
||||
},
|
||||
{ root: viewport, threshold: [0, 0.5, 0.99, 1] },
|
||||
);
|
||||
|
||||
cards.forEach(card => io.observe(card));
|
||||
return () => {
|
||||
io.disconnect();
|
||||
cards.forEach(card => card.classList.remove('tnl-chart-card--peek'));
|
||||
};
|
||||
}, [clipPeekLabels]);
|
||||
|
||||
useEffect(() => {
|
||||
const el = viewportRef.current;
|
||||
if (!el) return;
|
||||
@@ -60,6 +90,23 @@ const TradeNotificationHScrollPane: React.FC<TradeNotificationHScrollPaneProps>
|
||||
};
|
||||
}, [syncScrollState, children]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!clipPeekLabels) return;
|
||||
let cleanup = bindPeekLabelClip();
|
||||
const viewport = viewportRef.current;
|
||||
if (!viewport) return cleanup;
|
||||
|
||||
const mo = new MutationObserver(() => {
|
||||
cleanup();
|
||||
cleanup = bindPeekLabelClip();
|
||||
});
|
||||
mo.observe(viewport, { childList: true, subtree: true });
|
||||
return () => {
|
||||
mo.disconnect();
|
||||
cleanup();
|
||||
};
|
||||
}, [clipPeekLabels, bindPeekLabelClip, children]);
|
||||
|
||||
const scrollByStep = useCallback((dir: -1 | 1) => {
|
||||
const el = viewportRef.current;
|
||||
if (!el) return;
|
||||
|
||||
@@ -399,6 +399,7 @@ const TradeNotificationListRow: React.FC<Props> = ({
|
||||
indicatorScrollNeeded ? 'tnl-row-gallery-indicators--scroll' : '',
|
||||
].filter(Boolean).join(' ')}
|
||||
label="보조지표"
|
||||
clipPeekLabels={indicatorScrollNeeded}
|
||||
>
|
||||
<div className="tnl-charts-track tnl-charts-track--indicators-only">
|
||||
{indicatorCards.map(card => (
|
||||
|
||||
@@ -225,6 +225,7 @@ const TradeSignalMiniChart: React.FC<Props> = ({
|
||||
showHoverToolbar={false}
|
||||
seriesPriceLabelsEnabled={false}
|
||||
paneLayoutClamp
|
||||
showPaneLegend={false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user