Add chart navigation controls with keyboard shortcuts

- Navigation buttons (<, >, >>) appear when mouse within 30px of bottom
- Left/Right arrows shift timeline 0.8 window width
- Up arrow jumps to most recent candle
- Buttons: < move left, > move right, >> go to recent
This commit is contained in:
BTC Bot
2026-02-18 12:43:08 +01:00
parent c3cf0578f5
commit 09ec51c185
2 changed files with 111 additions and 1 deletions

View File

@ -567,6 +567,51 @@
color: white; color: white;
} }
/* Navigation Controls */
.nav-controls {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 10px;
display: flex;
flex-direction: row;
gap: 4px;
z-index: 10;
opacity: 0;
transition: opacity 0.2s;
}
.chart-wrapper.show-nav .nav-controls {
opacity: 1;
}
.nav-btn {
width: 28px;
height: 28px;
background: rgba(42, 46, 57, 0.9);
border: 1px solid #363c4e;
color: #d1d4dc;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.2s;
padding: 0;
}
.nav-btn:hover {
background: #363c4e;
border-color: #4a4f5e;
}
.nav-btn:active {
background: #2962ff;
border-color: #2962ff;
color: white;
}
.ha-header { .ha-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -995,12 +1040,17 @@
<div class="main-container"> <div class="main-container">
<div class="chart-area"> <div class="chart-area">
<div class="chart-wrapper"> <div class="chart-wrapper" id="chartWrapper">
<div id="chart"></div> <div id="chart"></div>
<div class="price-scale-controls" id="priceScaleControls"> <div class="price-scale-controls" id="priceScaleControls">
<button class="ps-control-btn auto-scale active" id="btnAutoScale" title="Auto Scale (A)">A</button> <button class="ps-control-btn auto-scale active" id="btnAutoScale" title="Auto Scale (A)">A</button>
<button class="ps-control-btn log-scale" id="btnLogScale" title="Logarithmic Scale">L</button> <button class="ps-control-btn log-scale" id="btnLogScale" title="Logarithmic Scale">L</button>
</div> </div>
<div class="nav-controls" id="navControls">
<button class="nav-btn" id="navLeft" title="Navigate Left (←)">&#8249;</button>
<button class="nav-btn" id="navRight" title="Navigate Right (→)">&#8250;</button>
<button class="nav-btn" id="navRecent" title="Go to Recent (↑)">&#187;</button>
</div>
</div> </div>
<div class="ta-panel" id="taPanel"> <div class="ta-panel" id="taPanel">

View File

@ -105,6 +105,7 @@ export class TradingDashboard {
}); });
this.initPriceScaleControls(); this.initPriceScaleControls();
this.initNavigationControls();
this.chart.timeScale().subscribeVisibleLogicalRangeChange(this.onVisibleRangeChange.bind(this)); this.chart.timeScale().subscribeVisibleLogicalRangeChange(this.onVisibleRangeChange.bind(this));
@ -204,6 +205,57 @@ export class TradingDashboard {
}); });
} }
initNavigationControls() {
const chartWrapper = document.getElementById('chartWrapper');
const navLeft = document.getElementById('navLeft');
const navRight = document.getElementById('navRight');
const navRecent = document.getElementById('navRecent');
if (!chartWrapper || !navLeft || !navRight || !navRecent) return;
chartWrapper.addEventListener('mousemove', (e) => {
const rect = chartWrapper.getBoundingClientRect();
const distanceFromBottom = rect.bottom - e.clientY;
chartWrapper.classList.toggle('show-nav', distanceFromBottom < 30);
});
chartWrapper.addEventListener('mouseleave', () => {
chartWrapper.classList.remove('show-nav');
});
navLeft.addEventListener('click', () => this.navigateLeft());
navRight.addEventListener('click', () => this.navigateRight());
navRecent.addEventListener('click', () => this.navigateToRecent());
}
navigateLeft() {
const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
if (!visibleRange) return;
const visibleBars = visibleRange.to - visibleRange.from;
const shift = visibleBars * 0.8;
const newFrom = visibleRange.from - shift;
const newTo = visibleRange.to - shift;
this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
}
navigateRight() {
const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
if (!visibleRange) return;
const visibleBars = visibleRange.to - visibleRange.from;
const shift = visibleBars * 0.8;
const newFrom = visibleRange.from + shift;
const newTo = visibleRange.to + shift;
this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
}
navigateToRecent() {
this.chart.timeScale().scrollToRealTime();
}
initEventListeners() { initEventListeners() {
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return; if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
@ -217,6 +269,14 @@ export class TradingDashboard {
if (shortcuts[e.key]) { if (shortcuts[e.key]) {
this.switchTimeframe(shortcuts[e.key]); this.switchTimeframe(shortcuts[e.key]);
} }
if (e.key === 'ArrowLeft') {
this.navigateLeft();
} else if (e.key === 'ArrowRight') {
this.navigateRight();
} else if (e.key === 'ArrowUp') {
this.navigateToRecent();
}
}); });
} }