mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-20 12:13:38 +08:00
Merge pull request #451 from cloud-of-equality/fix/message-growth-animation
fix(web): stabilize Message Growth animation and fit chips on one line
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
const FLOW_STEPS = [
|
const FLOW_STEPS = [
|
||||||
{ role: "user", label: "user", color: "bg-blue-500" },
|
{ role: "user", label: "user", color: "bg-blue-500" },
|
||||||
@@ -16,20 +16,22 @@ const FLOW_STEPS = [
|
|||||||
|
|
||||||
export function MessageFlow() {
|
export function MessageFlow() {
|
||||||
const [count, setCount] = useState(0);
|
const [count, setCount] = useState(0);
|
||||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
intervalRef.current = setInterval(() => {
|
// Single self-scheduling timer: only ever one timeout is pending, so a
|
||||||
setCount((prev) => {
|
// completed cycle can't queue multiple resets that snap the count back.
|
||||||
if (prev >= FLOW_STEPS.length) {
|
const step = (current: number) => {
|
||||||
setTimeout(() => setCount(0), 1500);
|
const next = current >= FLOW_STEPS.length ? 0 : current + 1;
|
||||||
return prev;
|
setCount(next);
|
||||||
}
|
// Hold on the full array before restarting the cycle.
|
||||||
return prev + 1;
|
const delay = next >= FLOW_STEPS.length ? 1500 : 800;
|
||||||
});
|
timeoutRef.current = setTimeout(() => step(next), delay);
|
||||||
}, 800);
|
};
|
||||||
|
|
||||||
|
timeoutRef.current = setTimeout(() => step(0), 800);
|
||||||
return () => {
|
return () => {
|
||||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -43,22 +45,21 @@ export function MessageFlow() {
|
|||||||
len={count}
|
len={count}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1.5 overflow-x-auto pb-1">
|
<div className="flex flex-wrap gap-1 pb-1">
|
||||||
<AnimatePresence>
|
{FLOW_STEPS.slice(0, count).map((step, i) => (
|
||||||
{FLOW_STEPS.slice(0, count).map((step, i) => (
|
<motion.div
|
||||||
<motion.div
|
key={i}
|
||||||
key={i}
|
layout
|
||||||
initial={{ opacity: 0, scale: 0.7, width: 0 }}
|
initial={{ opacity: 0, scale: 0.6 }}
|
||||||
animate={{ opacity: 1, scale: 1, width: "auto" }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
transition={{ duration: 0.25 }}
|
transition={{ duration: 0.25 }}
|
||||||
className={`flex shrink-0 items-center rounded-md px-2.5 py-1.5 ${step.color}`}
|
className={`flex shrink-0 items-center rounded-md px-1.5 py-1.5 ${step.color}`}
|
||||||
>
|
>
|
||||||
<span className="whitespace-nowrap font-mono text-[10px] font-medium text-white">
|
<span className="whitespace-nowrap font-mono text-[10px] font-medium text-white">
|
||||||
{step.label}
|
{step.label}
|
||||||
</span>
|
</span>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</AnimatePresence>
|
|
||||||
{count === 0 && (
|
{count === 0 && (
|
||||||
<div className="flex h-7 items-center text-xs text-[var(--color-text-secondary)]">
|
<div className="flex h-7 items-center text-xs text-[var(--color-text-secondary)]">
|
||||||
[]
|
[]
|
||||||
|
|||||||
Reference in New Issue
Block a user