first commit
This commit is contained in:
81
src/components/owliver/OwliverComposer.tsx
Normal file
81
src/components/owliver/OwliverComposer.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { SendHorizonal } from "lucide-react"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
/* ===========================================================================
|
||||
Section 24 — the composer.
|
||||
Enter sends, Shift+Enter adds a newline, send is disabled when empty, and the
|
||||
textarea grows with the content up to a cap.
|
||||
=========================================================================== */
|
||||
|
||||
export function OwliverComposer({
|
||||
onSend,
|
||||
disabled,
|
||||
}: {
|
||||
onSend: (text: string) => void
|
||||
disabled?: boolean
|
||||
}) {
|
||||
const [value, setValue] = useState("")
|
||||
const ref = useRef<HTMLTextAreaElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current
|
||||
if (!el) return
|
||||
el.style.height = "auto"
|
||||
el.style.height = `${Math.min(el.scrollHeight, 120)}px`
|
||||
}, [value])
|
||||
|
||||
const canSend = value.trim().length > 0 && !disabled
|
||||
|
||||
function submit() {
|
||||
if (!canSend) return
|
||||
onSend(value.trim())
|
||||
setValue("")
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="owliver-composer border-t border-line bg-surface p-2.5">
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-end gap-1.5 rounded-[14px] border border-line bg-surface-soft px-2.5 py-1.5",
|
||||
"transition-colors focus-within:border-primary focus-within:bg-surface"
|
||||
)}
|
||||
>
|
||||
<textarea
|
||||
ref={ref}
|
||||
rows={1}
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
submit()
|
||||
}
|
||||
}}
|
||||
placeholder="Ask Owliver anything..."
|
||||
aria-label="Ask Owliver anything"
|
||||
className={cn(
|
||||
"max-h-[120px] min-h-[24px] flex-1 resize-none bg-transparent py-1 text-[13px] leading-snug text-ink",
|
||||
"placeholder:text-ink-3 focus:outline-none disabled:opacity-60"
|
||||
)}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={submit}
|
||||
disabled={!canSend}
|
||||
aria-label="Send message"
|
||||
className={cn(
|
||||
"mb-0.5 grid size-7 shrink-0 place-items-center rounded-[9px] transition-colors",
|
||||
canSend
|
||||
? "bg-primary text-white hover:bg-[#1a45c0]"
|
||||
: "bg-surface-sunk text-ink-3"
|
||||
)}
|
||||
>
|
||||
<SendHorizonal className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user