diff --git a/apps/x/apps/renderer/src/App.tsx b/apps/x/apps/renderer/src/App.tsx index f37e3322..4a45f419 100644 --- a/apps/x/apps/renderer/src/App.tsx +++ b/apps/x/apps/renderer/src/App.tsx @@ -5252,14 +5252,18 @@ function App() { checkOnboarding() }, []) - // Handler for onboarding completion - const handleOnboardingComplete = useCallback(async () => { + // Handler for onboarding completion. When the user accepts the tour offer + // on the final step, hand off to the mascot tour once the modal's exit + // animation has cleared. + const handleOnboardingComplete = useCallback(async (opts?: { startTour?: boolean }) => { try { await window.ipc.invoke('onboarding:markComplete', null) - setShowOnboarding(false) } catch (err) { console.error('Failed to mark onboarding complete:', err) - setShowOnboarding(false) + } + setShowOnboarding(false) + if (opts?.startTour) { + window.setTimeout(() => setTourActive(true), 400) } }, []) @@ -5475,11 +5479,14 @@ function App() { case 'agents': openBgTasksView() break + case 'apps': + openAppsView() + break case 'workspaces': knowledgeActions.openWorkspaceAt() break } - }, [navigateToView, openEmailView, openMeetingsView, openCodeView, knowledgeActions, openBgTasksView]) + }, [navigateToView, openEmailView, openMeetingsView, openCodeView, knowledgeActions, openBgTasksView, openAppsView]) // Handler for when a voice note is created/updated const handleVoiceNoteCreated = useCallback(async (notePath: string) => { diff --git a/apps/x/apps/renderer/src/assets/tour/apps.mp3 b/apps/x/apps/renderer/src/assets/tour/apps.mp3 new file mode 100644 index 00000000..b7ae862a Binary files /dev/null and b/apps/x/apps/renderer/src/assets/tour/apps.mp3 differ diff --git a/apps/x/apps/renderer/src/components/onboarding/index.tsx b/apps/x/apps/renderer/src/components/onboarding/index.tsx index 2fb7426e..ae83e4fa 100644 --- a/apps/x/apps/renderer/src/components/onboarding/index.tsx +++ b/apps/x/apps/renderer/src/components/onboarding/index.tsx @@ -19,7 +19,7 @@ import { CompletionStep } from "./steps/completion-step" interface OnboardingModalProps { open: boolean - onComplete: () => void + onComplete: (opts?: { startTour?: boolean }) => void } export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { diff --git a/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx b/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx index 2f5d550c..53472d12 100644 --- a/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx +++ b/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx @@ -1,14 +1,17 @@ -import { CheckCircle2 } from "lucide-react" +import { CheckCircle2, Volume2 } from "lucide-react" import { motion } from "motion/react" import { Button } from "@/components/ui/button" +import { TalkingHead } from "@/components/talking-head" import type { OnboardingState } from "../use-onboarding-state" interface CompletionStepProps { state: OnboardingState } +const zeroLevel = () => 0 + export function CompletionStep({ state }: CompletionStepProps) { - const { connectedProviders, gmailConnected, googleCalendarConnected, handleComplete } = state + const { connectedProviders, gmailConnected, googleCalendarConnected, handleComplete, handleCompleteWithTour } = state const hasConnections = connectedProviders.length > 0 || gmailConnected || googleCalendarConnected return ( @@ -37,7 +40,7 @@ export function CompletionStep({ state }: CompletionStepProps) { initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.35 }} - className="text-base text-muted-foreground leading-relaxed max-w-sm mb-8" + className="text-base text-muted-foreground leading-relaxed max-w-sm mb-6" > {hasConnections ? ( <>Give me 30 minutes to build your context graph. I can still help with other things on your computer.> @@ -52,7 +55,7 @@ export function CompletionStep({ state }: CompletionStepProps) { initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.45 }} - className="w-full max-w-sm rounded-xl border bg-muted/30 p-4 mb-8" + className="w-full max-w-sm rounded-xl border bg-muted/30 p-4 mb-6" >
Connected
Want the captain's tour?
++ A one-minute guided voyage through everything you just set up + {hasConnections ? <> — perfect while I chart your data> : null}. +
+
+