Files
openpylon/src/components/card-detail/AttachmentSection.tsx

69 lines
2.2 KiB
TypeScript

import { FileIcon, X, Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useBoardStore } from "@/stores/board-store";
import type { Attachment } from "@/types/board";
interface AttachmentSectionProps {
cardId: string;
attachments: Attachment[];
}
export function AttachmentSection({
cardId,
attachments,
}: AttachmentSectionProps) {
const removeAttachment = useBoardStore((s) => s.removeAttachment);
function handleAdd() {
// Placeholder: Tauri file dialog will be wired in a later task
console.log("Add attachment (file dialog not yet wired)");
}
return (
<div className="flex flex-col gap-2">
{/* Header */}
<div className="flex items-center justify-between">
<h4 className="font-mono text-xs uppercase tracking-widest text-pylon-text-secondary">
Attachments
</h4>
<Button
variant="ghost"
size="icon-xs"
onClick={handleAdd}
className="text-pylon-text-secondary hover:text-pylon-text"
>
<Plus className="size-3.5" />
</Button>
</div>
{/* Attachment list */}
{attachments.length > 0 ? (
<div className="flex flex-col gap-1">
{attachments.map((att) => (
<div
key={att.id}
className="group/att flex items-center gap-2 rounded px-1 py-1 hover:bg-pylon-column/60"
>
<FileIcon className="size-3.5 shrink-0 text-pylon-text-secondary" />
<span className="flex-1 truncate text-sm text-pylon-text">
{att.name}
</span>
<button
onClick={() => removeAttachment(cardId, att.id)}
className="shrink-0 rounded p-0.5 text-pylon-text-secondary opacity-0 transition-opacity hover:bg-pylon-danger/10 hover:text-pylon-danger group-hover/att:opacity-100"
aria-label="Remove attachment"
>
<X className="size-3" />
</button>
</div>
))}
</div>
) : (
<p className="text-xs italic text-pylon-text-secondary/60">
No attachments
</p>
)}
</div>
);
}