diff --git a/frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx b/frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx
index 796097c3..85edbcf0 100644
--- a/frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx
+++ b/frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx
@@ -62,12 +62,34 @@ const IS_WIN = typeof navigator !== 'undefined' && navigator.userAgent.includes(
// before the next step's instant write lands.
const WIN_EASE_MS = 420;
+// A little spark when the cursor pops into existence: short orange lines shoot out from the
+// tip and fade. Re-keyed on each pop so it replays. One-shot per mount (no infinite loop).
+const BURST_SPOKES = 8;
+const CursorBurst: React.FC<{ color: string }> = ({ color }) => (
+ <>
+ {Array.from({ length: BURST_SPOKES }).map((_, i) => (
+
+
+
+ ))}
+ >
+);
+
const AgenticCursor = forwardRef((_props, ref) => {
const c = useClaudeTokens();
const controls = useAnimationControls();
const storePos = useCursorPosition();
const posRef = useRef({ x: 0, y: 0 });
const [visible, setVisible] = useState(false);
+ const [burstKey, setBurstKey] = useState(0);
const [popup, setPopup] = useState(null);
const [multiChoice, setMultiChoice] = useState(null);
@@ -97,6 +119,7 @@ const AgenticCursor = forwardRef((_props, ref) => {
writePos(from.x, from.y, true);
controls.set({ x: from.x, y: from.y, opacity: 0, scale: 0.3 });
setVisible(true);
+ setBurstKey((k) => k + 1); // replay the orange spark on each pop
// A little "pop!": scale overshoots past 1 then settles, while opacity snaps in.
await controls.start({
opacity: 1,
@@ -308,22 +331,28 @@ const AgenticCursor = forwardRef((_props, ref) => {
}}
>
{visible && (
-
-
-
+ <>
+ {/* Orange spark behind the arrow, replays each pop via burstKey. */}
+
+
+
+
+
+
+ >
)}
diff --git a/frontend/src/app/pages/AgentChat/WelcomeQuickReplies.tsx b/frontend/src/app/pages/AgentChat/WelcomeQuickReplies.tsx
index 0e3795f3..d6a917b4 100644
--- a/frontend/src/app/pages/AgentChat/WelcomeQuickReplies.tsx
+++ b/frontend/src/app/pages/AgentChat/WelcomeQuickReplies.tsx
@@ -8,19 +8,23 @@ import { STARTER_CATEGORIES } from '@/shared/starterCategories';
const GREETING = "Hi, I'm your AI team. What do you want done?";
-// One-shot typewriter for a fixed string (no infinite loop; stops at the end).
-function useTypewriter(text: string, speedMs = 26): { shown: string; done: boolean } {
+// One-shot typewriter for a fixed string (no infinite loop; stops at the end). startDelayMs
+// holds the start so the header title can stream first (sequential reveal).
+function useTypewriter(text: string, speedMs = 45, startDelayMs = 0): { shown: string; done: boolean } {
const [shown, setShown] = React.useState('');
React.useEffect(() => {
setShown('');
- let i = 0;
- const id = window.setInterval(() => {
- i += 1;
- setShown(text.slice(0, i));
- if (i >= text.length) window.clearInterval(id);
- }, speedMs);
- return () => window.clearInterval(id);
- }, [text, speedMs]);
+ let interval: number | undefined;
+ const startTimer = window.setTimeout(() => {
+ let i = 0;
+ interval = window.setInterval(() => {
+ i += 1;
+ setShown(text.slice(0, i));
+ if (i >= text.length) window.clearInterval(interval);
+ }, speedMs);
+ }, startDelayMs);
+ return () => { window.clearTimeout(startTimer); if (interval) window.clearInterval(interval); };
+ }, [text, speedMs, startDelayMs]);
return { shown, done: shown.length >= text.length };
}
@@ -32,7 +36,9 @@ const WelcomeQuickReplies: React.FC<{
onPick: (prompt: string) => void;
onPickBuilder: (prompt: string) => void;
}> = ({ c, onPick, onPickBuilder }) => {
- const { shown: greeting, done: greetingDone } = useTypewriter(GREETING);
+ // Slow + delayed so it reads as a sequence: card pops, the header title streams, THEN
+ // the greeting types, THEN the chips pop in.
+ const { shown: greeting, done: greetingDone } = useTypewriter(GREETING, 46, 650);
const [expanded, setExpanded] = React.useState(null);
const currentCategory = STARTER_CATEGORIES.find((cat) => cat.id === expanded);
const isAppBuilder = currentCategory?.target === 'app-builder';
@@ -82,7 +88,7 @@ const WelcomeQuickReplies: React.FC<{
onClick={() => setExpanded(cat.id)}
initial={{ opacity: 0, scale: 0.82 }}
animate={{ opacity: 1, scale: 1 }}
- transition={{ type: 'spring', stiffness: 520, damping: 24, delay: 0.08 + i * 0.07 }}
+ transition={{ type: 'spring', stiffness: 420, damping: 22, delay: 0.18 + i * 0.14 }}
style={{
display: 'flex', alignItems: 'center', gap: 8,
padding: '10px 14px',