Submatter/apps/web/components/chat/chat-composer.tsx

62 lines
1.6 KiB
TypeScript
Raw Permalink Normal View History

"use client";
import { useId, useState, type FormEvent, type KeyboardEvent } from "react";
import { Send } from "lucide-react";
import { Button } from "@/components/ui/button";
export function ChatComposer({
onSend,
disabled = false,
label = "Message",
}: {
onSend: (body: string) => void;
disabled?: boolean;
label?: string;
}) {
const [body, setBody] = useState("");
const id = useId();
const submit = (event?: FormEvent) => {
event?.preventDefault();
const text = body.trim();
if (!text || disabled) return;
onSend(text);
setBody("");
};
const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
if (
event.key === "Enter" &&
!event.shiftKey &&
!event.nativeEvent.isComposing
) {
event.preventDefault();
submit();
}
};
return (
<form onSubmit={submit} className="flex items-end gap-2 border-t p-3">
<label className="sr-only" htmlFor={id}>
{label}
</label>
<textarea
id={id}
value={body}
onChange={(event) => setBody(event.target.value)}
onKeyDown={onKeyDown}
disabled={disabled}
maxLength={10000}
rows={2}
placeholder={`${label} (Enter to send, Shift+Enter for a new line)`}
className="min-h-12 max-h-36 flex-1 resize-y rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
/>
<Button
type="submit"
disabled={disabled || !body.trim()}
aria-label="Send message"
>
<Send aria-hidden="true" /> Send
</Button>
</form>
);
}