Sifa professional network frontend (Next.js, React, TailwindCSS) sifa.id/
at main 86 lines 2.9 kB view raw
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}