# Chat response placeholder design ## Goal Show immediate, accessible feedback after a user submits a chat turn and before the model service returns response headers or content. ## User experience - The existing optimistic user message remains visible immediately. - An assistant row appears directly after it in the same render cycle. - Until response content arrives, the row shows the AI avatar and animated dots with the accessible label `Модель формирует ответ`. - The composer continues to show its stop control while generation is active. - The placeholder is replaced in place by the authoritative assistant message; it is never rendered alongside a duplicate server message. - A failure or stop before response headers converts the same placeholder into the existing error or stopped state while keeping the user message. ## State and reconciliation `useChat` creates a client-only assistant message together with every new optimistic user turn. Both messages use client-prefixed IDs. The optimistic turn descriptor carries both IDs. When `/api/chat` returns authoritative conversation, user-message, and assistant-message IDs, reconciliation updates the optimistic IDs and replaces the placeholder's status/content with the server assistant state. Streaming chunks then update that reconciled message as they do today. If the request fails before authoritative headers arrive, the hook updates the client assistant placeholder to `error` or `stopped`. Client-only failed assistant messages remain non-retryable because no server turn exists. ## Rendering and accessibility `ChatMessage` treats an empty `streaming` assistant as pending. It renders three animated dots instead of textual filler. The animation is decorative and hidden from assistive technology; a screen-reader label describes the state. Reduced-motion users receive static dots through the existing Tailwind motion variant. Once content is non-empty, normal assistant text replaces the dots. Complete, error, and stopped rendering remains unchanged. ## Testing - Hook test: before `/api/chat` resolves, the conversation contains optimistic user and assistant messages in order. - Hook test: authoritative response IDs replace the optimistic IDs without a duplicate assistant message. - Hook test: a pre-header error updates the existing placeholder rather than appending another assistant message. - Component test: an empty streaming assistant exposes the accessible pending label and animated-dot markup; content hides the pending indicator. - Existing focused and full corp-ui suites, lint, typecheck, production build, minikube rollout, health check, and browser smoke remain required. ## Scope No API, database, Gateway, FinOps, model-adapter, or persisted-message schema changes are required. The change is limited to optimistic client state, assistant rendering, tests, and the resulting corp-ui deployment.