feat: add typing indicator with ChatBubble component
- Add ChatBubble component for reusable chat bubble styling - Add TypingIndicator component with animated dots (. .. ...) - Show typing indicator after 500ms delay while waiting for AI response - Refactor ChatMessage to use ChatBubble component - Add isWaitingForResponse state to ChatStore
This commit is contained in:
28
apps/client/src/components/ChatBubble.tsx
Normal file
28
apps/client/src/components/ChatBubble.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { View, ViewStyle } from "react-native";
|
||||
import colors from "../Themes";
|
||||
|
||||
type BubbleSide = "left" | "right";
|
||||
|
||||
type ChatBubbleProps = {
|
||||
side: BubbleSide;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
style?: ViewStyle;
|
||||
};
|
||||
|
||||
export function ChatBubble({ side, children, className = "", style }: ChatBubbleProps) {
|
||||
const borderColor = side === "left" ? colors.chatBot : colors.primeFg;
|
||||
const sideClass =
|
||||
side === "left"
|
||||
? "self-start ml-2 rounded-bl-sm"
|
||||
: "self-end mr-2 rounded-br-sm";
|
||||
|
||||
return (
|
||||
<View
|
||||
className={`bg-white border-2 border-solid rounded-xl my-2 ${sideClass} ${className}`}
|
||||
style={[{ borderColor, elevation: 8 }, style]}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
30
apps/client/src/components/TypingIndicator.tsx
Normal file
30
apps/client/src/components/TypingIndicator.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Text } from "react-native";
|
||||
import colors from "../Themes";
|
||||
import { ChatBubble } from "./ChatBubble";
|
||||
|
||||
const DOTS = [".", "..", "..."];
|
||||
const INTERVAL_MS = 400;
|
||||
|
||||
export default function TypingIndicator() {
|
||||
const [dotIndex, setDotIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setDotIndex((prev) => (prev + 1) % DOTS.length);
|
||||
}, INTERVAL_MS);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ChatBubble side="left" className="px-4 py-2">
|
||||
<Text
|
||||
className="text-lg font-bold tracking-widest"
|
||||
style={{ color: colors.textMuted }}
|
||||
>
|
||||
{DOTS[dotIndex]}
|
||||
</Text>
|
||||
</ChatBubble>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user