JavaScript가 꺼져 있습니다. 아래 코드가 예제 전체입니다.
App.jsximport { useEffect, useState } from 'react';
import {
MotionHeight,
MotionList,
MotionStream,
MotionSwap,
motionTokens,
} from '@kkwaenggwari/animated-chorus';
import './styles.css';
const replies = {
'Plan a launch':
'Start with the date, then work back: freeze features two weeks before, write the notes one week before, and keep launch day for fixes and replies.',
'Name a color':
'Try Forest: a deep green that reads as calm and trustworthy, with a lighter mint for highlights and white for everything else.',
'Explain springs':
'A spring moves toward its target with the speed it already has. If the target changes halfway, it bends toward the new one instead of stopping.',
};
export default function App({ speed = 120, spring = 'default' }) {
const [messages, setMessages] = useState([]);
const [received, setReceived] = useState(0);
const transition = motionTokens.spring[spring];
const latest = messages[messages.length - 1];
const busy = latest?.role === 'bot' && received < latest.text.length;
useEffect(() => {
if (!busy) return;
const timer = setTimeout(() => setReceived(received + Math.ceil(latest.text.length / 3)), 600);
return () => clearTimeout(timer);
}, [busy, received, latest]);
const ask = (question) => {
const id = messages.length;
setMessages([
...messages,
{ id, role: 'user', text: question },
{ id: id + 1, role: 'bot', text: replies[question] },
]);
setReceived(0);
};
return (
<div className="chat">
{/* Like a chat app, the newest message stays in view as answers grow. */}
<div className="history">
<MotionList
className="messages"
itemClassName="row"
items={messages}
effect="rise"
transition={transition}
renderItem={(message) => (
<p className={`bubble ${message.role}`}>
{message.role === 'bot' ? (
<MotionStream
text={message === latest ? message.text.slice(0, received) : message.text}
speed={speed}
/>
) : (
message.text
)}
</p>
)}
/>
</div>
<MotionHeight open={!busy} transition={transition}>
<div className="suggestions">
{Object.keys(replies).map((question) => (
<button key={question} onClick={() => ask(question)}>
{question}
</button>
))}
</div>
</MotionHeight>
<div className="status">
<MotionSwap value={busy ? 'busy' : 'idle'} effect="up" transition={transition}>
{busy ? 'Answering…' : 'Pick a question'}
</MotionSwap>
</div>
</div>
);
}