| 1 | import { ArrowUp } from "lucide-react"; |
| 2 | import { Suspense, lazy } from "react"; |
| 3 | |
| 4 | import type { ComposerProps } from "./editor"; |
| 5 | |
| 6 | // The editor (components/chat/editor.tsx) is loaded with the first composer, |
| 7 | // so pages without one never fetch it. |
| 8 | const ChatEditor = lazy(() => import("./editor")); |
| 9 | |
| 10 | /** |
| 11 | * Where a message is written: the formatting editor, with what it looks |
| 12 | * like for the moment it takes to load. See components/chat/editor.tsx. |
| 13 | */ |
| 14 | export function Composer(props: ComposerProps) { |
| 15 | return ( |
| 16 | <Suspense fallback={<Loading placeholder={props.placeholder} compact={props.compact} />}> |
| 17 | <ChatEditor {...props} /> |
| 18 | </Suspense> |
| 19 | ); |
| 20 | } |
| 21 | |
| 22 | /** The composer's frame, still, while the editor loads. */ |
| 23 | function Loading({ placeholder, compact }: { placeholder: string; compact?: boolean }) { |
| 24 | return ( |
| 25 | <div aria-busy="true" className="rounded-xl border border-line-strong bg-surface"> |
| 26 | <p className={`px-3.5 text-[0.9375rem] leading-6 text-faint ${compact ? "pt-2.5 pb-1" : "pt-3 pb-1.5"}`}>{placeholder}</p> |
| 27 | <div className="flex items-center gap-1 px-2 pb-2"> |
| 28 | <span className="h-7" /> |
| 29 | <span aria-hidden="true" className="ml-auto flex size-8 items-center justify-center rounded-lg bg-line text-faint"> |
| 30 | <ArrowUp size={16} strokeWidth={2.4} /> |
| 31 | </span> |
| 32 | </div> |
| 33 | </div> |
| 34 | ); |
| 35 | } |