Add interactive getting-started tutorial for first-time users
Auto-starts on first visit with a 9-step walkthrough covering header, tabs, settings, search, theme, and language controls. Stores completion in localStorage; restart via ? button in the header. Includes en/ru/zh translations for all tour steps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,20 @@ const calibrationTutorialSteps = [
|
||||
{ selector: '#cal-skip-end', textKey: 'calibration.tip.skip_leds_end', position: 'top' }
|
||||
];
|
||||
|
||||
const TOUR_KEY = 'tour_completed';
|
||||
|
||||
const gettingStartedSteps = [
|
||||
{ selector: 'header .header-title', textKey: 'tour.welcome', position: 'bottom' },
|
||||
{ selector: '#tab-btn-dashboard', textKey: 'tour.dashboard', position: 'bottom' },
|
||||
{ selector: '#tab-btn-targets', textKey: 'tour.targets', position: 'bottom' },
|
||||
{ selector: '#tab-btn-streams', textKey: 'tour.sources', position: 'bottom' },
|
||||
{ selector: '#tab-btn-profiles', textKey: 'tour.profiles', position: 'bottom' },
|
||||
{ selector: '[onclick*="openSettingsModal"]', textKey: 'tour.settings', position: 'bottom' },
|
||||
{ selector: '[onclick*="openCommandPalette"]', textKey: 'tour.search', position: 'bottom' },
|
||||
{ selector: '.theme-toggle', textKey: 'tour.theme', position: 'bottom' },
|
||||
{ selector: '#locale-select', textKey: 'tour.language', position: 'bottom' }
|
||||
];
|
||||
|
||||
const deviceTutorialSteps = [
|
||||
{ selector: '.card-subtitle', textKey: 'device.tip.metadata', position: 'bottom' },
|
||||
{ selector: '.brightness-control', textKey: 'device.tip.brightness', position: 'bottom' },
|
||||
@@ -40,7 +54,8 @@ export function startTutorial(config) {
|
||||
mode: config.mode,
|
||||
step: 0,
|
||||
resolveTarget: config.resolveTarget,
|
||||
container: config.container
|
||||
container: config.container,
|
||||
onClose: config.onClose || null
|
||||
});
|
||||
|
||||
overlay.classList.add('active');
|
||||
@@ -86,8 +101,20 @@ export function startDeviceTutorial(deviceId) {
|
||||
});
|
||||
}
|
||||
|
||||
export function startGettingStartedTutorial() {
|
||||
startTutorial({
|
||||
steps: gettingStartedSteps,
|
||||
overlayId: 'getting-started-overlay',
|
||||
mode: 'fixed',
|
||||
container: null,
|
||||
resolveTarget: (step) => document.querySelector(step.selector) || null,
|
||||
onClose: () => localStorage.setItem(TOUR_KEY, '1')
|
||||
});
|
||||
}
|
||||
|
||||
export function closeTutorial() {
|
||||
if (!activeTutorial) return;
|
||||
const onClose = activeTutorial.onClose;
|
||||
activeTutorial.overlay.classList.remove('active');
|
||||
document.querySelectorAll('.tutorial-target').forEach(el => {
|
||||
el.classList.remove('tutorial-target');
|
||||
@@ -95,6 +122,7 @@ export function closeTutorial() {
|
||||
});
|
||||
document.removeEventListener('keydown', handleTutorialKey);
|
||||
setActiveTutorial(null);
|
||||
if (onClose) onClose();
|
||||
}
|
||||
|
||||
export function tutorialNext() {
|
||||
|
||||
Reference in New Issue
Block a user