Skip to content

Commit e53fa88

Browse files
azizmejri1claude
andcommitted
Address PR review comments
- Add type="button" and focus-visible ring styles to dialog buttons - Prevent submit while attachment type dialog is open - Clear pendingFiles in clearAttachments to avoid orphaned state - Deduplicate confirmPendingFiles by reusing addAttachments - Add i18n translations for FileAttachmentTypeDialog (en, pt-BR, zh-CN) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5e2fe9e commit e53fa88

7 files changed

Lines changed: 59 additions & 28 deletions

File tree

src/components/chat/ChatInput.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ export function ChatInput({ chatId }: { chatId?: number }) {
245245
if (
246246
(!inputValue.trim() && attachments.length === 0) ||
247247
isStreaming ||
248-
!chatId
248+
!chatId ||
249+
pendingFiles
249250
) {
250251
return;
251252
}

src/components/chat/FileAttachmentTypeDialog.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
DialogTitle,
77
DialogDescription,
88
} from "@/components/ui/dialog";
9+
import { useTranslation } from "react-i18next";
910

1011
interface FileAttachmentTypeDialogProps {
1112
pendingFiles: File[] | null;
@@ -18,6 +19,7 @@ export function FileAttachmentTypeDialog({
1819
onConfirm,
1920
onCancel,
2021
}: FileAttachmentTypeDialogProps) {
22+
const { t } = useTranslation("chat");
2123
const isOpen = !!pendingFiles && pendingFiles.length > 0;
2224
const fileCount = pendingFiles?.length ?? 0;
2325

@@ -31,38 +33,47 @@ export function FileAttachmentTypeDialog({
3133
<DialogContent className="sm:max-w-md">
3234
<DialogHeader>
3335
<DialogTitle>
34-
How would you like to attach{" "}
35-
{fileCount === 1 ? "this file" : `these ${fileCount} files`}?
36+
{fileCount === 1
37+
? t("attachmentTypeDialog.titleSingular")
38+
: t("attachmentTypeDialog.titlePlural", { count: fileCount })}
3639
</DialogTitle>
3740
<DialogDescription>
38-
Choose how the {fileCount === 1 ? "file" : "files"} should be used.
41+
{fileCount === 1
42+
? t("attachmentTypeDialog.descriptionSingular")
43+
: t("attachmentTypeDialog.descriptionPlural")}
3944
</DialogDescription>
4045
</DialogHeader>
4146
<div className="flex flex-col gap-2">
4247
<button
43-
className="flex items-start gap-3 rounded-lg border border-border p-4 text-left hover:bg-muted/50 transition-colors"
48+
type="button"
49+
className="flex items-start gap-3 rounded-lg border border-border p-4 text-left hover:bg-muted/50 transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
4450
onClick={() => onConfirm("chat-context")}
4551
>
4652
<MessageSquare
4753
size={20}
4854
className="mt-0.5 text-green-500 flex-shrink-0"
4955
/>
5056
<div>
51-
<div className="font-medium text-sm">Attach as chat context</div>
57+
<div className="font-medium text-sm">
58+
{t("attachFileContext")}
59+
</div>
5260
<div className="text-xs text-muted-foreground mt-0.5">
53-
Provide context for the AI (e.g. screenshots, references)
61+
{t("attachFileContextExample")}
5462
</div>
5563
</div>
5664
</button>
5765
<button
58-
className="flex items-start gap-3 rounded-lg border border-border p-4 text-left hover:bg-muted/50 transition-colors"
66+
type="button"
67+
className="flex items-start gap-3 rounded-lg border border-border p-4 text-left hover:bg-muted/50 transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
5968
onClick={() => onConfirm("upload-to-codebase")}
6069
>
6170
<Upload size={20} className="mt-0.5 text-blue-500 flex-shrink-0" />
6271
<div>
63-
<div className="font-medium text-sm">Upload to codebase</div>
72+
<div className="font-medium text-sm">
73+
{t("uploadFileCodebase")}
74+
</div>
6475
<div className="text-xs text-muted-foreground mt-0.5">
65-
Add files to your project (e.g. images, assets)
76+
{t("uploadFileCodebaseExample")}
6677
</div>
6778
</div>
6879
</button>

src/components/chat/HomeChatInput.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ export function HomeChatInput({
5959

6060
// Custom submit function that wraps the provided onSubmit
6161
const handleCustomSubmit = () => {
62-
if ((!inputValue.trim() && attachments.length === 0) || isStreaming) {
62+
if (
63+
(!inputValue.trim() && attachments.length === 0) ||
64+
isStreaming ||
65+
pendingFiles
66+
) {
6367
return;
6468
}
6569

src/hooks/useAttachments.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,25 @@ export function useAttachments() {
6868
}
6969
};
7070

71+
const addAttachments = (
72+
files: File[],
73+
type: "chat-context" | "upload-to-codebase" = "chat-context",
74+
) => {
75+
const fileAttachments: FileAttachment[] = files.map((file) => ({
76+
file,
77+
type,
78+
}));
79+
setAttachments((attachments) => [...attachments, ...fileAttachments]);
80+
};
81+
7182
const confirmPendingFiles = useCallback(
7283
(type: "chat-context" | "upload-to-codebase") => {
7384
if (pendingFiles) {
74-
const fileAttachments: FileAttachment[] = pendingFiles.map((file) => ({
75-
file,
76-
type,
77-
}));
78-
setAttachments((prev) => [...prev, ...fileAttachments]);
85+
addAttachments(pendingFiles, type);
7986
setPendingFiles(null);
8087
}
8188
},
82-
[pendingFiles, setAttachments],
89+
[pendingFiles, addAttachments],
8390
);
8491

8592
const cancelPendingFiles = useCallback(() => {
@@ -88,17 +95,7 @@ export function useAttachments() {
8895

8996
const clearAttachments = () => {
9097
setAttachments([]);
91-
};
92-
93-
const addAttachments = (
94-
files: File[],
95-
type: "chat-context" | "upload-to-codebase" = "chat-context",
96-
) => {
97-
const fileAttachments: FileAttachment[] = files.map((file) => ({
98-
file,
99-
type,
100-
}));
101-
setAttachments((attachments) => [...attachments, ...fileAttachments]);
98+
setPendingFiles(null);
10299
};
103100

104101
const handlePaste = async (e: React.ClipboardEvent) => {

src/i18n/locales/en/chat.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@
126126
"uploadFileCodebase": "Upload file to codebase",
127127
"uploadFileCodebaseExample": "Example use case: add an image to use for your app",
128128
"dropFilesToAttach": "Drop files to attach",
129+
"attachmentTypeDialog": {
130+
"titleSingular": "How would you like to attach this file?",
131+
"titlePlural": "How would you like to attach these {{count}} files?",
132+
"descriptionSingular": "Choose how the file should be used.",
133+
"descriptionPlural": "Choose how the files should be used."
134+
},
129135
"selectedComponents": "Selected Components ({{count}})",
130136
"clearAllComponents": "Clear all selected components",
131137
"deselectComponent": "Deselect component",

src/i18n/locales/pt-BR/chat.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@
126126
"uploadFileCodebase": "Enviar arquivo para a base de código",
127127
"uploadFileCodebaseExample": "Exemplo de uso: adicionar uma imagem para usar no seu app",
128128
"dropFilesToAttach": "Solte os arquivos para anexar",
129+
"attachmentTypeDialog": {
130+
"titleSingular": "Como você gostaria de anexar este arquivo?",
131+
"titlePlural": "Como você gostaria de anexar estes {{count}} arquivos?",
132+
"descriptionSingular": "Escolha como o arquivo deve ser usado.",
133+
"descriptionPlural": "Escolha como os arquivos devem ser usados."
134+
},
129135
"selectedComponents": "Componentes Selecionados ({{count}})",
130136
"clearAllComponents": "Limpar todos os componentes selecionados",
131137
"deselectComponent": "Desmarcar componente",

src/i18n/locales/zh-CN/chat.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@
126126
"uploadFileCodebase": "上传文件到代码库",
127127
"uploadFileCodebaseExample": "示例用途:添加图片供应用使用",
128128
"dropFilesToAttach": "拖放文件以附加",
129+
"attachmentTypeDialog": {
130+
"titleSingular": "您想如何附加此文件?",
131+
"titlePlural": "您想如何附加这 {{count}} 个文件?",
132+
"descriptionSingular": "选择文件的使用方式。",
133+
"descriptionPlural": "选择文件的使用方式。"
134+
},
129135
"selectedComponents": "已选择的组件 ({{count}})",
130136
"clearAllComponents": "清除所有已选择的组件",
131137
"deselectComponent": "取消选择组件",

0 commit comments

Comments
 (0)