a tool for shared writing and social publishing
1"use client";
2import { Separator } from "./Layout";
3import { CommentTiny } from "./Icons/CommentTiny";
4import { QuoteTiny } from "./Icons/QuoteTiny";
5import { useSmoker } from "./Toast";
6import { Tag } from "./Tags";
7import { Popover } from "./Popover";
8import { TagTiny } from "./Icons/TagTiny";
9import { SpeedyLink } from "./SpeedyLink";
10
11export const InteractionPreview = (props: {
12 quotesCount: number;
13 commentsCount: number;
14 tags?: string[];
15 postUrl: string;
16 showComments: boolean;
17 showMentions: boolean;
18
19 share?: boolean;
20}) => {
21 let smoker = useSmoker();
22 let interactionsAvailable =
23 (props.quotesCount > 0 && props.showMentions) ||
24 (props.showComments !== false && props.commentsCount > 0);
25
26 const tagsCount = props.tags?.length || 0;
27
28 return (
29 <div
30 className={`flex gap-2 text-tertiary text-sm items-center self-start`}
31 >
32 {tagsCount === 0 ? null : (
33 <>
34 <TagPopover tags={props.tags!} />
35 {interactionsAvailable || props.share ? (
36 <Separator classname="h-4!" />
37 ) : null}
38 </>
39 )}
40
41 {!props.showMentions || props.quotesCount === 0 ? null : (
42 <SpeedyLink
43 aria-label="Post quotes"
44 href={`${props.postUrl}?interactionDrawer=quotes`}
45 className="relative flex flex-row gap-1 text-sm items-center hover:text-accent-contrast hover:no-underline! text-tertiary"
46 >
47 <QuoteTiny /> {props.quotesCount}
48 </SpeedyLink>
49 )}
50 {!props.showComments || props.commentsCount === 0 ? null : (
51 <SpeedyLink
52 aria-label="Post comments"
53 href={`${props.postUrl}?interactionDrawer=comments`}
54 className="relative flex flex-row gap-1 text-sm items-center hover:text-accent-contrast hover:no-underline! text-tertiary"
55 >
56 <CommentTiny /> {props.commentsCount}
57 </SpeedyLink>
58 )}
59 {interactionsAvailable && props.share ? (
60 <Separator classname="h-4! !min-h-0" />
61 ) : null}
62 {props.share && (
63 <>
64 <button
65 id={`copy-post-link-${props.postUrl}`}
66 className="flex gap-1 items-center hover:text-accent-contrast relative"
67 onClick={(e) => {
68 e.stopPropagation();
69 e.preventDefault();
70 let mouseX = e.clientX;
71 let mouseY = e.clientY;
72
73 if (!props.postUrl) return;
74 navigator.clipboard.writeText(`leaflet.pub${props.postUrl}`);
75
76 smoker({
77 text: <strong>Copied Link!</strong>,
78 position: {
79 y: mouseY,
80 x: mouseX,
81 },
82 });
83 }}
84 >
85 Share
86 </button>
87 </>
88 )}
89 </div>
90 );
91};
92
93const TagPopover = (props: { tags: string[] }) => {
94 return (
95 <Popover
96 className="p-2! max-w-xs"
97 trigger={
98 <div className="relative flex gap-1 items-center hover:text-accent-contrast">
99 <TagTiny /> {props.tags.length}
100 </div>
101 }
102 >
103 <TagList tags={props.tags} className="text-secondary!" />
104 </Popover>
105 );
106};
107
108const TagList = (props: { tags: string[]; className?: string }) => {
109 return (
110 <div className="flex gap-1 flex-wrap">
111 {props.tags.map((tag, index) => (
112 <Tag name={tag} key={index} className={props.className} />
113 ))}
114 </div>
115 );
116};