Sifa professional network frontend (Next.js, React, TailwindCSS)
sifa.id/
1'use client';
2
3import { DotsThreeVertical, PencilSimple, Plus, Trash } from '@phosphor-icons/react';
4import { Menu } from '@base-ui/react/menu';
5import { Button } from '@/components/ui/button';
6
7interface SectionEditorProps {
8 isOwnProfile?: boolean;
9 sectionTitle: string;
10 onAdd?: () => void;
11 children: React.ReactNode;
12}
13
14export function SectionEditor({ isOwnProfile, sectionTitle, onAdd, children }: SectionEditorProps) {
15 if (!isOwnProfile) return <>{children}</>;
16
17 return (
18 <div className="group relative">
19 {children}
20 {onAdd && (
21 <div className="mt-2">
22 <Button variant="ghost" size="sm" onClick={onAdd} aria-label={`Add ${sectionTitle}`}>
23 <Plus className="mr-1 h-4 w-4" weight="bold" aria-hidden="true" />
24 Add
25 </Button>
26 </div>
27 )}
28 </div>
29 );
30}
31
32interface EditableEntryProps {
33 isOwnProfile?: boolean;
34 onEdit: () => void;
35 onDelete: () => void;
36 entryLabel: string;
37 children: React.ReactNode;
38 /** Optional content (e.g. star toggle) to render before the kebab menu */
39 trailingContent?: React.ReactNode;
40}
41
42export function EditableEntry({
43 isOwnProfile,
44 onEdit,
45 onDelete,
46 entryLabel,
47 children,
48 trailingContent,
49}: EditableEntryProps) {
50 if (!isOwnProfile) return <>{children}</>;
51
52 return (
53 <div className="flex items-start gap-2">
54 <div className="min-w-0 flex-1">{children}</div>
55 {trailingContent}
56 <Menu.Root>
57 <Menu.Trigger
58 className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
59 aria-label={`${entryLabel} options`}
60 >
61 <DotsThreeVertical className="h-4 w-4" weight="bold" aria-hidden="true" />
62 </Menu.Trigger>
63 <Menu.Portal>
64 <Menu.Positioner align="end" sideOffset={4}>
65 <Menu.Popup className="z-[60] min-w-[140px] rounded-md border border-border bg-card py-1 shadow-md">
66 <Menu.Item
67 className="flex w-full cursor-pointer items-center gap-2 px-3 py-1.5 text-sm text-foreground outline-none hover:bg-accent focus:bg-accent"
68 onClick={onEdit}
69 >
70 <PencilSimple className="h-3.5 w-3.5" weight="bold" aria-hidden="true" />
71 Edit
72 </Menu.Item>
73 <Menu.Item
74 className="flex w-full cursor-pointer items-center gap-2 px-3 py-1.5 text-sm text-destructive outline-none hover:bg-destructive/10 focus:bg-destructive/10"
75 onClick={onDelete}
76 >
77 <Trash className="h-3.5 w-3.5" weight="bold" aria-hidden="true" />
78 Delete
79 </Menu.Item>
80 </Menu.Popup>
81 </Menu.Positioner>
82 </Menu.Portal>
83 </Menu.Root>
84 </div>
85 );
86}