Add WebUI navigation improvements: keyboard shortcuts, hash routing, command palette, cross-entity links
- Keyboard shortcuts: Ctrl+1-4 for tab switching - URL hash routing: #tab/subtab format with browser back/forward support - Tab count badges: running targets and active profiles counts - Cross-entity quick links: clickable references navigate to related cards - Command palette (Ctrl+K): global search across all entities with keyboard navigation - Expand/collapse all sections: buttons in sub-tab bars - Sticky section headers: headers pin while scrolling long card grids - Improved section filter: better styling with reset button Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -46,10 +46,10 @@
|
||||
|
||||
<div class="tabs">
|
||||
<div class="tab-bar" role="tablist">
|
||||
<button class="tab-btn" data-tab="dashboard" onclick="switchTab('dashboard')" role="tab" aria-selected="true" aria-controls="tab-dashboard" id="tab-btn-dashboard"><span data-i18n="dashboard.title">📊 Dashboard</span></button>
|
||||
<button class="tab-btn" data-tab="profiles" onclick="switchTab('profiles')" role="tab" aria-selected="false" aria-controls="tab-profiles" id="tab-btn-profiles"><span data-i18n="profiles.title">📋 Profiles</span></button>
|
||||
<button class="tab-btn" data-tab="targets" onclick="switchTab('targets')" role="tab" aria-selected="false" aria-controls="tab-targets" id="tab-btn-targets"><span data-i18n="targets.title">⚡ Targets</span></button>
|
||||
<button class="tab-btn" data-tab="streams" onclick="switchTab('streams')" role="tab" aria-selected="false" aria-controls="tab-streams" id="tab-btn-streams"><span data-i18n="streams.title">📺 Sources</span></button>
|
||||
<button class="tab-btn" data-tab="dashboard" onclick="switchTab('dashboard')" role="tab" aria-selected="true" aria-controls="tab-dashboard" id="tab-btn-dashboard" title="Ctrl+1"><span data-i18n="dashboard.title">📊 Dashboard</span></button>
|
||||
<button class="tab-btn" data-tab="profiles" onclick="switchTab('profiles')" role="tab" aria-selected="false" aria-controls="tab-profiles" id="tab-btn-profiles" title="Ctrl+2"><span data-i18n="profiles.title">📋 Profiles</span><span class="tab-badge" id="tab-badge-profiles" style="display:none"></span></button>
|
||||
<button class="tab-btn" data-tab="targets" onclick="switchTab('targets')" role="tab" aria-selected="false" aria-controls="tab-targets" id="tab-btn-targets" title="Ctrl+3"><span data-i18n="targets.title">⚡ Targets</span><span class="tab-badge" id="tab-badge-targets" style="display:none"></span></button>
|
||||
<button class="tab-btn" data-tab="streams" onclick="switchTab('streams')" role="tab" aria-selected="false" aria-controls="tab-streams" id="tab-btn-streams" title="Ctrl+4"><span data-i18n="streams.title">📺 Sources</span></button>
|
||||
</div>
|
||||
|
||||
<div class="tab-panel" id="tab-dashboard" role="tabpanel" aria-labelledby="tab-btn-dashboard">
|
||||
@@ -79,7 +79,8 @@
|
||||
<script>
|
||||
// Apply saved tab immediately during parse to prevent visible jump
|
||||
(function() {
|
||||
var saved = localStorage.getItem('activeTab');
|
||||
var hash = location.hash.replace(/^#/, '');
|
||||
var saved = hash ? hash.split('/')[0] : localStorage.getItem('activeTab');
|
||||
if (saved === 'devices') saved = 'targets';
|
||||
if (!saved || !document.getElementById('tab-' + saved)) saved = 'dashboard';
|
||||
document.querySelectorAll('.tab-btn').forEach(function(btn) { btn.classList.toggle('active', btn.dataset.tab === saved); });
|
||||
@@ -124,6 +125,15 @@
|
||||
{% include 'partials/image-lightbox.html' %}
|
||||
{% include 'partials/display-picker.html' %}
|
||||
|
||||
<div id="command-palette" style="display:none">
|
||||
<div class="cp-backdrop"></div>
|
||||
<div class="cp-dialog">
|
||||
<input id="cp-input" class="cp-input" placeholder="Search..." autocomplete="off">
|
||||
<div id="cp-results" class="cp-results"></div>
|
||||
<div class="cp-footer">↑↓ navigate · Enter select · Esc close</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="/static/js/app.js"></script>
|
||||
<script>
|
||||
// Initialize theme
|
||||
|
||||
Reference in New Issue
Block a user