text highlight and og image
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
"use client";
|
||||
|
||||
import { useCopyFeedback } from "./shared";
|
||||
import { buildHighlightUrl } from "@/lib/text-highlight";
|
||||
import { createPortal } from "react-dom";
|
||||
import { X, MessageSquare, ExternalLink } from "lucide-react";
|
||||
import {
|
||||
Drawer,
|
||||
DrawerClose,
|
||||
DrawerContent,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
} from "@/components/ui/drawer";
|
||||
|
||||
export function ShareModal({
|
||||
open,
|
||||
onClose,
|
||||
selectedText,
|
||||
isMobile,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
selectedText: string;
|
||||
isMobile: boolean;
|
||||
}) {
|
||||
const { copied, copy } = useCopyFeedback();
|
||||
|
||||
const shareOptions = [
|
||||
{
|
||||
key: "feed",
|
||||
label: "Share to Feed",
|
||||
icon: <MessageSquare className="size-4" />,
|
||||
description: "Post this quote to your feed",
|
||||
onClick: () => {
|
||||
// TODO: Implement share to feed
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "link",
|
||||
label: "Share Link",
|
||||
icon: <ExternalLink className="size-4" />,
|
||||
description: "Copy a shareable link",
|
||||
onClick: () => {
|
||||
copy(buildHighlightUrl(selectedText));
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer open={open} onOpenChange={(o) => !o && onClose()}>
|
||||
<DrawerContent className="bg-black dark:bg-[#1a1a1a] border-white/10">
|
||||
<DrawerHeader className="text-left border-b border-white/10 pb-4">
|
||||
<DrawerTitle className="text-white">Share</DrawerTitle>
|
||||
{selectedText && (
|
||||
<p className="text-sm text-white/50 mt-1 line-clamp-2">
|
||||
“{selectedText.slice(0, 120)}
|
||||
{selectedText.length > 120 ? "…" : ""}”
|
||||
</p>
|
||||
)}
|
||||
</DrawerHeader>
|
||||
<div className="p-4 space-y-1">
|
||||
{shareOptions.map((opt) => (
|
||||
<button
|
||||
key={opt.key}
|
||||
onClick={opt.onClick}
|
||||
className="flex items-center gap-3 w-full px-3 py-3 rounded-lg text-left hover:bg-white/10 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-center size-9 rounded-lg bg-amber-400/15 text-amber-400">
|
||||
{opt.icon}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-white/90">
|
||||
{opt.key === "link" && copied ? "Link Copied!" : opt.label}
|
||||
</p>
|
||||
<p className="text-xs text-white/50">{opt.description}</p>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="p-4 pt-0">
|
||||
<DrawerClose asChild>
|
||||
<button className="w-full py-2.5 rounded-lg border border-white/15 text-sm font-medium text-white/60 hover:bg-white/10 transition-colors">
|
||||
Cancel
|
||||
</button>
|
||||
</DrawerClose>
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
// Desktop modal
|
||||
if (!open) return null;
|
||||
|
||||
return createPortal(
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 z-100 bg-black/60 animate-in fade-in-0"
|
||||
onClick={onClose}
|
||||
/>
|
||||
<div className="fixed left-1/2 top-1/2 z-101 w-full max-w-sm -translate-x-1/2 -translate-y-1/2 rounded-xl border border-white/10 bg-black shadow-2xl animate-in fade-in-0 zoom-in-95 dark:bg-[#1a1a1a] dark:border-white/15">
|
||||
<div className="flex items-center justify-between px-5 py-4 border-b border-white/10">
|
||||
<h2 className="text-lg font-semibold text-white">Share</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="flex items-center justify-center size-8 rounded-lg text-white/50 hover:bg-white/10 hover:text-white transition-colors"
|
||||
>
|
||||
<X className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
{selectedText && (
|
||||
<div className="px-5 py-3 border-b border-white/10">
|
||||
<p className="text-sm text-white/50 line-clamp-2">
|
||||
“{selectedText.slice(0, 120)}
|
||||
{selectedText.length > 120 ? "…" : ""}”
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="p-3 space-y-1">
|
||||
{shareOptions.map((opt) => (
|
||||
<button
|
||||
key={opt.key}
|
||||
onClick={opt.onClick}
|
||||
className="flex items-center gap-3 w-full px-3 py-3 rounded-lg text-left hover:bg-white/10 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-center size-9 rounded-lg bg-amber-400/15 text-amber-400">
|
||||
{opt.icon}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-white/90">
|
||||
{opt.key === "link" && copied ? "Link Copied!" : opt.label}
|
||||
</p>
|
||||
<p className="text-xs text-white/50">{opt.description}</p>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>,
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user