Files
storkit/frontend/src/components/ChatInput.tsx

192 lines
4.0 KiB
TypeScript
Raw Normal View History

import * as React from "react";
const { useEffect, useRef, useState } = React;
interface ChatInputProps {
loading: boolean;
queuedMessages: { id: string; text: string }[];
onSubmit: (message: string) => void;
onCancel: () => void;
onRemoveQueuedMessage: (id: string) => void;
}
export function ChatInput({
loading,
queuedMessages,
onSubmit,
onCancel,
onRemoveQueuedMessage,
}: ChatInputProps) {
const [input, setInput] = useState("");
const inputRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
const handleSubmit = () => {
if (!input.trim()) return;
onSubmit(input);
setInput("");
};
return (
<div
style={{
padding: "24px",
background: "#171717",
display: "flex",
justifyContent: "center",
}}
>
<div
style={{
maxWidth: "768px",
width: "100%",
display: "flex",
flexDirection: "column",
gap: "8px",
}}
>
{/* Queued message indicators */}
{queuedMessages.map(({ id, text }) => (
<div
key={id}
data-testid="queued-message-indicator"
style={{
display: "flex",
alignItems: "center",
gap: "8px",
padding: "8px 12px",
background: "#1e1e1e",
border: "1px solid #3a3a3a",
borderRadius: "12px",
fontSize: "0.875rem",
}}
>
<span
style={{
color: "#666",
flexShrink: 0,
fontSize: "0.7rem",
fontWeight: 700,
letterSpacing: "0.05em",
textTransform: "uppercase",
}}
>
Queued
</span>
<span
style={{
color: "#888",
flex: 1,
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{text}
</span>
<button
type="button"
title="Edit queued message"
onClick={() => {
setInput(text);
onRemoveQueuedMessage(id);
inputRef.current?.focus();
}}
style={{
background: "none",
border: "none",
color: "#666",
cursor: "pointer",
padding: "2px 6px",
fontSize: "0.8rem",
flexShrink: 0,
borderRadius: "4px",
}}
>
Edit
</button>
<button
type="button"
title="Cancel queued message"
onClick={() => onRemoveQueuedMessage(id)}
style={{
background: "none",
border: "none",
color: "#666",
cursor: "pointer",
padding: "2px 4px",
fontSize: "0.875rem",
flexShrink: 0,
borderRadius: "4px",
}}
>
</button>
</div>
))}
{/* Input row */}
<div
style={{
display: "flex",
gap: "8px",
alignItems: "center",
}}
>
<textarea
ref={inputRef}
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSubmit();
}
}}
placeholder="Send a message..."
rows={1}
style={{
flex: 1,
padding: "14px 20px",
borderRadius: "24px",
border: "1px solid #333",
outline: "none",
fontSize: "1rem",
fontWeight: "500",
background: "#2f2f2f",
color: "#ececec",
boxShadow: "0 2px 6px rgba(0,0,0,0.02)",
resize: "none",
overflowY: "auto",
fontFamily: "inherit",
}}
/>
<button
type="button"
onClick={loading && !input.trim() ? onCancel : handleSubmit}
disabled={!loading && !input.trim()}
style={{
background: "#ececec",
color: "black",
border: "none",
borderRadius: "50%",
width: "32px",
height: "32px",
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
opacity: !loading && !input.trim() ? 0.5 : 1,
flexShrink: 0,
}}
>
{loading && !input.trim() ? "■" : "↑"}
</button>
</div>
</div>
</div>
);
}