mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 13:06:20 +02:00
Two related cleanups to the issue comment/reply/edit composer: - Drop the trigger-preview "context" copy added in #4147 (chip prefix `trigger_context_*` and per-context popover titles `trigger_preview_title_*`). The actual "align context" fix in #4147 was the backend/hook work; the copy was redundant decoration. Removes the `context` prop, the dead i18n keys across en/zh/ja/ko, and the corresponding test assertions; the popover title falls back to the original single `trigger_preview_title`. - Edit-comment footer: lay the trigger chip on a single row with the action cluster (📎 Cancel Save) on the right, attachments on their own full-width row above. The 📎 now sits with the action buttons, matching the new-comment and reply composers. - Unify composer buttons on shadcn `Button`: `FileUploadButton` renders a ghost icon button instead of a hand-rolled circle, and the reply submit button uses `Button` (icon-xs, ghost-when-empty / primary-when-typed) instead of a hand-rolled element. Sizes: 📎 and reply submit are both icon-xs (24px). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
1.7 KiB
TypeScript
65 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useRef } from "react";
|
|
import { Paperclip } from "lucide-react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Button } from "@multica/ui/components/ui/button";
|
|
import { cn } from "@multica/ui/lib/utils";
|
|
|
|
interface FileUploadButtonProps {
|
|
/** Called with the selected File — caller handles upload. */
|
|
onSelect: (file: File) => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
size?: "sm" | "default";
|
|
multiple?: boolean;
|
|
}
|
|
|
|
function FileUploadButton({
|
|
onSelect,
|
|
disabled,
|
|
className,
|
|
size = "default",
|
|
multiple = false,
|
|
}: FileUploadButtonProps) {
|
|
const { t } = useTranslation("ui");
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
const attachLabel = t(($) => $.attach_file);
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const files = Array.from(e.target.files ?? []);
|
|
if (files.length === 0) return;
|
|
e.target.value = "";
|
|
for (const file of files) onSelect(file);
|
|
};
|
|
|
|
const iconSize = size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4";
|
|
const buttonSize = size === "sm" ? "icon-xs" : "icon-sm";
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size={buttonSize}
|
|
onClick={() => inputRef.current?.click()}
|
|
disabled={disabled}
|
|
aria-label={attachLabel}
|
|
title={attachLabel}
|
|
className={cn("text-muted-foreground", className)}
|
|
>
|
|
<Paperclip className={iconSize} />
|
|
</Button>
|
|
<input
|
|
ref={inputRef}
|
|
type="file"
|
|
multiple={multiple}
|
|
className="hidden"
|
|
onChange={handleChange}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export { FileUploadButton, type FileUploadButtonProps };
|