diff --git a/js/desktop/src/features/onboarding/onboarding-keyboard.tsx b/js/desktop/src/features/onboarding/onboarding-keyboard.tsx index 8307229..8d31893 100644 --- a/js/desktop/src/features/onboarding/onboarding-keyboard.tsx +++ b/js/desktop/src/features/onboarding/onboarding-keyboard.tsx @@ -29,7 +29,7 @@ function KeyCap({
- +
- +
- +
diff --git a/js/desktop/src/features/onboarding/onboarding-overlay.tsx b/js/desktop/src/features/onboarding/onboarding-overlay.tsx index a0d0cf1..cee5ffd 100644 --- a/js/desktop/src/features/onboarding/onboarding-overlay.tsx +++ b/js/desktop/src/features/onboarding/onboarding-overlay.tsx @@ -1,7 +1,6 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { WindowControls } from '@/components/window-controls'; import { KeyHint } from '@/components/key-hint'; -import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { OnboardingKeyboard } from './onboarding-keyboard'; import { OnboardingStep } from './onboarding-step'; @@ -10,14 +9,7 @@ import { ToggleStep } from './toggle-step'; import { TapStep } from './tap-step'; import { PermissionStep } from './permission-step'; -const STEPS = [ - 'welcome', - 'hold', - 'toggle', - 'tap', - 'permission', - 'done', -] as const; +const STEPS = ['welcome', 'hold', 'tap', 'toggle', 'permission'] as const; type Step = (typeof STEPS)[number]; /** @@ -34,6 +26,10 @@ export function OnboardingOverlay({ onComplete }: { onComplete: () => void }) { setStep((cur) => STEPS[Math.min(STEPS.indexOf(cur) + 1, STEPS.length - 1)]); }, []); + const goBack = useCallback(() => { + setStep((cur) => STEPS[Math.max(0, STEPS.indexOf(cur) - 1)]); + }, []); + // Focus the panel on the gesture steps so window-level key handling has a // home; the static steps autofocus their primary button instead, which lets // Enter activate it natively (no duplicate window handler). @@ -43,17 +39,27 @@ export function OnboardingOverlay({ onComplete }: { onComplete: () => void }) { } }, [step]); - // Esc skips the wizard from anywhere. + // Esc skips the wizard from anywhere; ← (and Backspace) steps back. useEffect(() => { const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { e.preventDefault(); onComplete(); + } else if (e.key === 'Enter' && step === 'welcome') { + e.preventDefault(); + goNext(); + } else if ( + e.key === 'ArrowLeft' || + e.key === 'Backspace' || + e.key === 'Delete' + ) { + e.preventDefault(); + goBack(); } }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); - }, [onComplete]); + }, [onComplete, goNext, step, goBack]); return (
@@ -80,17 +86,7 @@ export function OnboardingOverlay({ onComplete }: { onComplete: () => void }) { {step === 'welcome' && ( - - - to begin - - - } + subtitle="To use llink, you must learn the keyboard shortcuts. Don't worry, once you learn them, you'll feel like your flowing." > @@ -98,33 +94,7 @@ export function OnboardingOverlay({ onComplete }: { onComplete: () => void }) { {step === 'hold' && } {step === 'toggle' && } {step === 'tap' && } - {step === 'permission' && } - {step === 'done' && ( - - - - for all shortcuts - - - } - > -
- - to talk - - switch audio / video - - to start and stop - -
-
- )} + {step === 'permission' && }
{STEPS.map((s, i) => ( @@ -141,6 +111,28 @@ export function OnboardingOverlay({ onComplete }: { onComplete: () => void }) { /> ))}
+ +
+ {index > 0 && ( + + back + + )} + {step === 'welcome' && ( + + continue + + )} +
diff --git a/js/desktop/src/features/onboarding/onboarding-step.tsx b/js/desktop/src/features/onboarding/onboarding-step.tsx index 2f9b9e2..33447ca 100644 --- a/js/desktop/src/features/onboarding/onboarding-step.tsx +++ b/js/desktop/src/features/onboarding/onboarding-step.tsx @@ -1,7 +1,7 @@ import type { ReactNode } from 'react'; /** How long a success state lingers before the wizard auto-advances, in ms. */ -export const SUCCESS_DWELL_MS = 800; +export const SUCCESS_DWELL_MS = 2000; interface OnboardingStepProps { title: ReactNode;