File size: 3,737 Bytes
65d68f5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | "use client";
import { Paperclip, Plus } from "lucide-react";
import { uploadMenuItems } from "./constants";
import type { SourceDraftMode, UploadMenuAction } from "./types";
function nextDraftModeForAction(action: UploadMenuAction): SourceDraftMode {
if (action === "link") return "link";
if (action === "syllabus") return "syllabus";
if (action === "text") return "text";
return null;
}
export function ComposerPlusMenu({
plusOpen,
onPlusOpenChange,
onOpenMaterialPicker,
onOpenPaperPicker,
onSourceDraftModeChange,
}: {
plusOpen: boolean;
onPlusOpenChange: (open: boolean) => void;
onOpenMaterialPicker: () => void;
onOpenPaperPicker: () => void;
onSourceDraftModeChange: (mode: SourceDraftMode) => void;
}) {
function handleMenuAction(action: UploadMenuAction, enabled: boolean) {
if (!enabled) return;
if (action === "material") {
onPlusOpenChange(false);
onOpenMaterialPicker();
return;
}
if (action === "paper") {
onPlusOpenChange(false);
onOpenPaperPicker();
return;
}
const draftMode = nextDraftModeForAction(action);
if (draftMode) {
onSourceDraftModeChange(draftMode);
onPlusOpenChange(false);
}
}
return (
<div className="relative flex items-center gap-1 text-white/54">
<button
type="button"
onClick={() => onPlusOpenChange(!plusOpen)}
aria-expanded={plusOpen}
aria-label="Open add source menu"
className="inline-flex size-9 items-center justify-center rounded-full border border-white/[0.1] bg-white/[0.04] transition hover:border-white/[0.2] hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/22"
>
<Plus className="size-[1.05rem]" />
</button>
<button
type="button"
onClick={onOpenMaterialPicker}
aria-label="Attach file"
className="inline-flex size-9 items-center justify-center rounded-full transition hover:bg-white/[0.06] hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/22"
>
<Paperclip className="size-[1.05rem]" />
</button>
{plusOpen ? (
<div className="absolute bottom-12 left-0 z-30 max-h-[18rem] w-[min(21rem,88vw)] overflow-y-auto rounded-2xl border border-white/[0.1] bg-[#090909] p-2 shadow-[0_24px_80px_rgba(0,0,0,0.62)] [scrollbar-width:none] sm:max-h-[28rem] [&::-webkit-scrollbar]:hidden">
{uploadMenuItems.map((item) => {
const Icon = item.icon;
return (
<button
key={item.label}
type="button"
disabled={!item.enabled}
onClick={() => handleMenuAction(item.action, item.enabled)}
className="flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left transition hover:bg-white/[0.055] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 disabled:cursor-not-allowed disabled:opacity-38"
>
<span className="grid size-9 shrink-0 place-items-center rounded-xl border border-white/[0.08] bg-white/[0.035] text-white/60">
<Icon className="size-4" />
</span>
<span className="min-w-0 flex-1">
<span className="block text-sm font-semibold text-white/82">{item.label}</span>
<span className="block truncate text-xs text-white/38">{item.description}</span>
</span>
{!item.enabled ? <span className="text-[10px] font-bold uppercase text-white/28">Soon</span> : null}
</button>
);
})}
</div>
) : null}
</div>
);
}
|