Browse Source

feat(ui): add in-app modals for user guide and shortcuts.

Create `shortcuts.html` as a standalone reference page.
Implement `#shortcuts-modal` in `index.html` to display key bindings.
 Implement `#guide-modal` with an iframe to embed `User_Manual.html` directly in the app.
 Refactor header navigation into color-coded buttons (Green/Blue/Amber-Indigo).
 Update `src/dom.js` and `src/ui.js` to handle modal visibili and interactions (ESC key, 'k' key, click-to-close).
 Improve visual consistency of header button heights and moda styling.
refactor/sync-centralize
RUSHIL AMBARISH KADU 6 months ago
parent
commit
f03bbbeeb0
  1. 155
      steps/index.html
  2. 137
      steps/shortcuts.html
  3. 7
      steps/src/dom.js
  4. 64
      steps/src/ui.js

155
steps/index.html

@ -177,6 +177,48 @@
} }
/* --- END: CSS for Resizable/Draggable Panel --- */ /* --- END: CSS for Resizable/Draggable Panel --- */
/* --- Keyboard Shortcuts Modal Styling --- */
kbd {
background-color: #e2e8f0;
/* slate-200 */
border: 1px solid #cbd5e1;
/* slate-300 */
border-bottom-width: 2px;
color: #334155;
/* slate-700 */
border-radius: 0.375rem;
padding: 0.125rem 0.5rem;
font-family: monospace;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 600;
display: inline-block;
margin: 0 0.125rem;
}
/* Dark mode support for kbd */
.dark kbd {
background-color: #475569;
/* slate-600 */
border-color: #64748b;
/* slate-500 */
color: #f1f5f9;
/* slate-100 */
}
.feature-card {
/* Inherits bg-white/dark:bg-gray-800 from parent or class */
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
}
.dark .feature-card {
border-color: #4b5563;
/* gray-600 */
box-shadow: none;
}
</style> </style>
</head> </head>
@ -203,11 +245,15 @@
(i) (i)
</span> </span>
</button> </button>
<a href="User_Manual.html" target="_blank" id="user-manual-btn"
class="bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 shadow-sm hover:bg-gray-200 dark:hover:bg-gray-600 active:scale-95 active:shadow-inner font-medium rounded-lg text-xs px-4 py-2 transition-all text-center">
<button id="user-manual-btn" type="button"
class="bg-green-100 dark:bg-green-700 text-green-800 dark:text-green-100 border border-green-300 dark:border-green-600 shadow-sm hover:bg-green-200 dark:hover:bg-green-600 active:scale-95 active:shadow-inner font-medium rounded-lg text-xs px-4 py-2 transition-all text-center">
Quick-Start<br>Guide Quick-Start<br>Guide
</a>
<button id="theme-toggle" type="button" class="bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 shadow-sm hover:bg-gray-200 dark:hover:bg-gray-600 active:scale-95 active:shadow-inner flex flex-row items-center gap-2 rounded-lg text-sm p-2.5 transition-all">
</button>
<button id="shortcuts-btn" type="button"
class="bg-blue-100 dark:bg-blue-700 text-blue-800 dark:text-blue-100 border border-blue-300 dark:border-blue-600 shadow-sm hover:bg-blue-200 dark:hover:bg-blue-600 active:scale-95 active:shadow-inner font-medium rounded-lg text-xs px-4 py-2 transition-all text-center">
Keyboard<br>Shortcuts
</button>
<button id="theme-toggle" type="button" class="bg-amber-100 dark:bg-indigo-900 text-amber-800 dark:text-indigo-100 border border-amber-300 dark:border-indigo-700 shadow-sm hover:bg-amber-200 dark:hover:bg-indigo-800 active:scale-95 active:shadow-inner flex flex-row items-center gap-2 rounded-lg text-xs px-4 py-3.5 transition-all">
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path> <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg> </svg>
@ -217,7 +263,7 @@
fill-rule="evenodd" clip-rule="evenodd"></path> fill-rule="evenodd" clip-rule="evenodd"></path>
</svg> </svg>
<span <span
class="text-xs font-mono bg-gray-200 dark:bg-gray-600 text-gray-700 dark:text-gray-200 px-1.5 py-0.5 rounded">
class="text-xs font-mono bg-amber-200 dark:bg-indigo-800 text-amber-900 dark:text-indigo-200 px-1.5 py-0.5 rounded">
(q) (q)
</span> </span>
</button> </button>
@ -483,6 +529,80 @@
</div> </div>
</footer> </footer>
<!-- SHORTCUTS MODAL -->
<div id="shortcuts-modal" class="fixed inset-0 z-50 flex items-center justify-center hidden bg-black bg-opacity-80 backdrop-blur-sm p-4">
<div class="bg-white dark:bg-gray-900 rounded-2xl shadow-2xl w-full max-w-5xl max-h-[90vh] overflow-y-auto relative flex flex-col">
<!-- Header -->
<div class="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700 sticky top-0 bg-white dark:bg-gray-900 z-10">
<div class="flex items-center gap-3">
<span class="text-3xl">⌨️</span>
<div>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">Keyboard Shortcuts</h2>
<p class="text-sm text-gray-500 dark:text-gray-400">Press <kbd>ESC</kbd> or click outside to close</p>
</div>
</div>
<button id="shortcuts-modal-close-btn" class="text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full p-2 transition-colors">
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- Content Grid -->
<div class="p-8 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Playback -->
<div class="feature-card p-6 bg-gray-50 dark:bg-gray-800">
<h3 class="mb-4 text-lg font-bold text-blue-600 dark:text-blue-400 border-b pb-2 border-gray-200 dark:border-gray-700">Playback & Navigation</h3>
<ul class="space-y-3 text-sm text-gray-700 dark:text-gray-300">
<li class="flex justify-between items-center"><span>Play / Pause</span> <kbd>Space</kbd></li>
<li class="flex justify-between items-center"><span>Next Frame</span> <kbd></kbd></li>
<li class="flex justify-between items-center"><span>Prev Frame</span> <kbd></kbd></li>
<li class="flex justify-between items-center"><span>Video Frame Step</span> <kbd></kbd> / <kbd></kbd></li>
<li class="flex justify-between items-center"><span>Scroll Seek</span> <kbd>Mouse Wheel</kbd></li>
<li class="flex justify-between items-center"><span>Reset Frame 0</span> <kbd>R</kbd></li>
</ul>
</div>
<!-- View & Toggles -->
<div class="feature-card p-6 bg-gray-50 dark:bg-gray-800">
<h3 class="mb-4 text-lg font-bold text-emerald-600 dark:text-emerald-400 border-b pb-2 border-gray-200 dark:border-gray-700">View & UI Toggles</h3>
<ul class="space-y-3 text-sm text-gray-700 dark:text-gray-300">
<li class="flex justify-between items-center"><span>Sidebar Menu</span> <kbd>M</kbd></li>
<li class="flex justify-between items-center"><span>Data Explorer</span> <kbd>I</kbd></li>
<li class="flex justify-between items-center"><span>GOD MODE Zoom</span> <kbd>G</kbd></li>
<li class="flex justify-between items-center"><span>Dark/Light Theme</span> <kbd>Q</kbd></li>
<li class="flex justify-between items-center"><span>Adv. Debug Info</span> <kbd>A</kbd></li>
<li class="flex justify-between items-center"><span>Fullscreen</span> <kbd>F11</kbd></li>
</ul>
</div>
<!-- Data Display -->
<div class="feature-card p-6 bg-gray-50 dark:bg-gray-800">
<h3 class="mb-4 text-lg font-bold text-pink-600 dark:text-pink-400 border-b pb-2 border-gray-200 dark:border-gray-700">Data Visualization</h3>
<ul class="space-y-3 text-sm text-gray-700 dark:text-gray-300">
<li class="flex justify-between items-center"><span>Toggle Tracks</span> <kbd>T</kbd></li>
<li class="flex justify-between items-center"><span>Object Details</span> <kbd>D</kbd></li>
<li class="flex justify-between items-center"><span>Predicted Pos</span> <kbd>P</kbd></li>
<li class="flex justify-between items-center"><span>Confirmed Only</span> <kbd>C</kbd></li>
<li class="flex justify-between items-center"><span>Color by SNR</span> <kbd>1</kbd></li>
<li class="flex justify-between items-center"><span>Color by Cluster</span> <kbd>2</kbd></li>
<li class="flex justify-between items-center"><span>Color by Inlier</span> <kbd>3</kbd></li>
<li class="flex justify-between items-center"><span>Color by Stationary</span> <kbd>4</kbd></li>
</ul>
</div>
</div>
<!-- Footer Tip -->
<div class="p-6 bg-gray-50 dark:bg-gray-800 text-center border-t border-gray-200 dark:border-gray-700 rounded-b-2xl">
<p class="text-sm text-gray-500">Pro Tip: You can also press <kbd>K</kbd> anytime to toggle this screen.</p>
</div>
</div>
</div>
<div id="modal-container" class="fixed inset-0 z-50 flex items-center justify-center hidden"> <div id="modal-container" class="fixed inset-0 z-50 flex items-center justify-center hidden">
<div id="modal-overlay" class="absolute inset-0 bg-black bg-opacity-50"></div> <div id="modal-overlay" class="absolute inset-0 bg-black bg-opacity-50"></div>
<div id="modal-content" <div id="modal-content"
@ -502,6 +622,31 @@
</div> </div>
</div> </div>
<!-- USER GUIDE MODAL -->
<div id="guide-modal" class="fixed inset-0 z-50 flex items-center justify-center hidden bg-black bg-opacity-80 backdrop-blur-sm p-4">
<div class="bg-white dark:bg-gray-900 rounded-2xl shadow-2xl w-full h-full mx-8 my-4 relative flex flex-col">
<!-- Header -->
<div class="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700 sticky top-0 bg-white dark:bg-gray-900 z-10 rounded-t-2xl">
<div class="flex items-center gap-3">
<span class="text-3xl">📚</span>
<div>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">User Manual</h2>
<p class="text-sm text-gray-500 dark:text-gray-400">Quick-Start Guide & Reference</p>
</div>
</div>
<button id="guide-modal-close-btn" class="text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full p-2 transition-colors">
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- Iframe Content -->
<iframe id="user-manual-iframe" src="User_Manual.html" class="flex-grow w-full border-0 rounded-b-2xl" style="min-height: 400px;"></iframe>
</div>
</div>
<input type="file" id="json-file-input" class="hidden" accept=".json" /> <input type="file" id="json-file-input" class="hidden" accept=".json" />
<input type="file" id="video-file-input" class="hidden" accept="video/*" /> <input type="file" id="video-file-input" class="hidden" accept="video/*" />
<input type="file" id="session-file-input" class="hidden" accept=".json" /> <input type="file" id="session-file-input" class="hidden" accept=".json" />

137
steps/shortcuts.html

@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Keyboard Shortcuts - Radar & Video Synchronizer</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f8fafc; /* slate-50 */
color: #1e293b; /* slate-800 */
}
.font-mono { font-family: 'Roboto Mono', monospace; }
/* Infographic Palette */
:root {
--c-primary: #0284c7; /* sky-600 */
--c-primary-light: #f0f9ff; /* sky-50 */
--c-secondary: #059669; /* emerald-600 */
--c-accent: #db2777; /* pink-600 */
--c-dark: #334155; /* slate-700 */
--c-light: #f1f5f9; /* slate-100 */
--c-text: #374151; /* gray-700 */
--c-text-light: #64748b; /* slate-500 */
}
h1, h2, h3 { font-weight: 700; letter-spacing: -0.025em; color: var(--c-dark); }
h1 { font-size: 2.25rem; line-height: 2.5rem; font-weight: 800; }
h2 { font-size: 1.875rem; line-height: 2.25rem; border-bottom: 2px solid var(--c-light); padding-bottom: 0.5rem; }
h3 { font-size: 1.25rem; line-height: 1.75rem; color: var(--c-primary); }
.section-icon {
font-size: 2rem;
line-height: 1;
background-color: var(--c-primary-light);
color: var(--c-primary);
padding: 0.75rem;
border-radius: 0.5rem;
display: inline-block;
margin-bottom: 0.5rem;
}
.feature-card {
background-color: white;
border: 1px solid #e2e8f0; /* slate-200 */
border-radius: 0.75rem;
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05), 0 2px 4px -2px rgba(0,0,0,0.05);
transition: all 0.2s ease-in-out;
}
.feature-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.07), 0 4px 6px -2px rgba(0,0,0,0.05);
border-color: var(--c-primary);
}
/* Keyboard Shortcut Styling */
kbd {
background-color: #e2e8f0; /* slate-200 */
border: 1px solid #cbd5e1; /* slate-300 */
border-bottom-width: 2px;
color: #334155; /* slate-700 */
border-radius: 0.375rem;
padding: 0.125rem 0.5rem;
font-family: 'Roboto Mono', monospace;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
display: inline-block;
margin: 0 0.125rem;
}
</style>
</head>
<body class="antialiased">
<div class="container mx-auto px-4 py-12 max-w-6xl space-y-16">
<section class="text-center">
<div class="section-icon">⌨️</div>
<h1 class="text-4xl md:text-5xl">Keyboard Shortcuts</h1>
<p class="text-xl text-slate-600 max-w-3xl mx-auto mt-4">
Quick reference guide for controlling the Radar & Video Synchronizer.
</p>
</section>
<section>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Playback -->
<div class="feature-card p-6">
<h3 class="mb-3">Playback & Navigation</h3>
<ul class="space-y-2 text-sm">
<li><kbd>Spacebar</kbd> - Play / Pause</li>
<li><kbd>ArrowRight</kbd> - Next Frame (pauses)</li>
<li><kbd>ArrowLeft</kbd> - Previous Frame (pauses)</li>
<li><kbd>R</kbd> - Reset to Frame 0</li>
</ul>
</div>
<!-- View & Toggles -->
<div class="feature-card p-6">
<h3 class="mb-3">View & UI Toggles</h3>
<ul class="space-y-2 text-sm">
<li><kbd>M</kbd> - Toggle Sidebar Menu</li>
<li><kbd>I</kbd> - Toggle Data Explorer</li>
<li><kbd>G</kbd> - Toggle "GOD MODE" Zoom</li>
<li><kbd>Q</kbd> - Toggle Dark/Light Theme</li>
<li><kbd>A</kbd> - Toggle Advanced Debug Info</li>
<li><kbd>F11</kbd> - Toggle Fullscreen</li>
</ul>
</div>
<!-- Data Display -->
<div class="feature-card p-6">
<h3 class="mb-3">Data Display Toggles</h3>
<ul class="space-y-2 text-sm">
<li><kbd>T</kbd> - Toggle Tracks</li>
<li><kbd>D</kbd> - Toggle Object Details</li>
<li><kbd>P</kbd> - Toggle Predicted Position</li>
<li><kbd>C</kbd> - Toggle Confirmed Tracks Only</li>
<li><kbd>1</kbd> / <kbd>S</kbd> - Color by SNR</li>
<li><kbd>2</kbd> - Color by Cluster</li>
<li><kbd>3</kbd> - Color by Inlier</li>
<li><kbd>4</kbd> - Color by Stationary</li>
</ul>
</div>
</div>
</section>
<footer class="text-center mt-12 text-slate-500 text-sm">
<p>Pro Tip: Keep this tab open for quick reference while using the visualizer.</p>
</footer>
</div>
</body>
</html>

7
steps/src/dom.js

@ -100,6 +100,13 @@ export const fullscreenExitIcon = document.getElementById("fullscreen-exit-icon"
export const menuScrim = document.getElementById("menu-scrim"); export const menuScrim = document.getElementById("menu-scrim");
export const toggleConfirmedOnly = document.getElementById("toggle-confirmed-only"); export const toggleConfirmedOnly = document.getElementById("toggle-confirmed-only");
export const explorerBtn = document.getElementById("explorer-btn"); export const explorerBtn = document.getElementById("explorer-btn");
export const shortcutsBtn = document.getElementById("shortcuts-btn");
export const shortcutsModal = document.getElementById("shortcuts-modal");
export const shortcutsModalCloseBtn = document.getElementById("shortcuts-modal-close-btn");
export const userManualBtn = document.getElementById("user-manual-btn");
export const guideModal = document.getElementById("guide-modal");
export const guideModalCloseBtn = document.getElementById("guide-modal-close-btn");
//----------------------Reset UI for New file Load----------------------// //----------------------Reset UI for New file Load----------------------//

64
steps/src/ui.js

@ -31,6 +31,12 @@ import {
menuScrim, menuScrim,
fullscreenBtn, fullscreenBtn,
toggleConfirmedOnly, toggleConfirmedOnly,
shortcutsBtn,
shortcutsModal,
shortcutsModalCloseBtn,
userManualBtn,
guideModal,
guideModalCloseBtn,
} from "./dom.js"; } from "./dom.js";
function toggleMenu(show) { function toggleMenu(show) {
@ -43,6 +49,22 @@ function toggleMenu(show) {
} }
} }
function toggleShortcutsModal(show) {
if (show) {
shortcutsModal.classList.remove("hidden");
} else {
shortcutsModal.classList.add("hidden");
}
}
function toggleGuideModal(show) {
if (show) {
guideModal.classList.remove("hidden");
} else {
guideModal.classList.add("hidden");
}
}
function handleColorToggles(e) { function handleColorToggles(e) {
const colorToggles = [ const colorToggles = [
toggleSnrColor, toggleSnrColor,
@ -60,6 +82,48 @@ function handleColorToggles(e) {
} }
export function initUIEventListeners() { export function initUIEventListeners() {
// --- Shortcuts Modal ---
shortcutsBtn.addEventListener("click", (e) => {
e.preventDefault();
toggleShortcutsModal(true);
});
shortcutsModalCloseBtn.addEventListener("click", () => toggleShortcutsModal(false));
shortcutsModal.addEventListener("click", (e) => {
// Close if clicking the background overlay (self), but not children
if (e.target === shortcutsModal) {
toggleShortcutsModal(false);
}
});
// --- Guide Modal ---
userManualBtn.addEventListener("click", (e) => {
e.preventDefault();
toggleGuideModal(true);
});
guideModalCloseBtn.addEventListener("click", () => toggleGuideModal(false));
guideModal.addEventListener("click", (e) => {
if (e.target === guideModal) {
toggleGuideModal(false);
}
});
// Global Key Listener for 'k' and 'ESC'
document.addEventListener("keydown", (e) => {
if (e.key.toLowerCase() === "k") {
// Toggle visibility
const isHidden = shortcutsModal.classList.contains("hidden");
toggleShortcutsModal(isHidden);
}
// Prioritize closing the guide modal if open, then shortcuts modal
if (e.key === "Escape") {
if (!guideModal.classList.contains("hidden")) {
toggleGuideModal(false);
} else if (!shortcutsModal.classList.contains("hidden")) {
toggleShortcutsModal(false);
}
}
});
// --- Menu and Fullscreen --- // --- Menu and Fullscreen ---
toggleMenuBtn.addEventListener("click", () => toggleMenu(true)); toggleMenuBtn.addEventListener("click", () => toggleMenu(true));
closeMenuBtn.addEventListener("click", () => toggleMenu(false)); closeMenuBtn.addEventListener("click", () => toggleMenu(false));

Loading…
Cancel
Save