| 25-file-system |
02 |
ui |
| react |
| file-upload |
| drag-and-drop |
| clipboard |
| xhr |
| lucide |
|
| phase |
provides |
| 25-file-system-00 |
shared types (ChatFile, ChatFileUploadResponse), validators |
|
| phase |
provides |
| 25-file-system-01 |
server endpoint POST /api/conversations/:id/files |
|
|
| ChatFileDropZone component with drag-and-drop overlay |
| useChatFileUpload hook with upload lifecycle (uploading/done/error) |
| chatApi.uploadFile using XHR with progress callbacks |
| ChatInput updated with file picker button, paste handler, and pending file chips |
|
| 25-03 |
| 25-04 |
| chat-panel-integration |
|
| added |
patterns |
|
|
| XHR for upload progress tracking (not fetch, which lacks upload progress) |
| PendingFile client-side state lifecycle before server confirmation |
| ChatFileDropZone wraps children with drag overlay without breaking layout |
|
|
| created |
modified |
| ui/src/components/ChatFileDropZone.tsx |
| ui/src/hooks/useChatFileUpload.ts |
|
| ui/src/api/chat.ts |
| ui/src/components/ChatInput.tsx |
| ui/src/components/ChatInput.test.tsx |
|
|
| Used XHR instead of fetch for chatApi.uploadFile to enable upload progress events (fetch lacks upload.onprogress) |
| ChatFileDropZone checks e.currentTarget.contains(e.relatedTarget) to avoid false drag-leave when crossing child elements |
| onFilesPicked is optional — ChatInput works without file support when prop not provided (backward compatible) |
|
| PendingFile pattern: temp client ID assigned immediately, replaced with server ChatFile.id on completion |
| Drop zone overlay uses bg-primary/10 and border-primary for theme-neutral visual feedback |
|
|
15min |
2026-04-01 |