Spaces:
Running
Running
| 'use client' | |
| import React from 'react' | |
| import { motion, AnimatePresence } from 'framer-motion' | |
| import { | |
| Info, | |
| Image | |
| } from '@phosphor-icons/react' | |
| interface ContextMenuProps { | |
| isOpen: boolean | |
| position: { x: number; y: number } | |
| onClose: () => void | |
| onAction: (action: string) => void | |
| } | |
| export function ContextMenu({ isOpen, position, onClose, onAction }: ContextMenuProps) { | |
| const menuItems = [ | |
| { id: 'change-wallpaper', label: 'Change Background', icon: Image }, | |
| { id: 'get-info', label: 'Get Info', icon: Info }, | |
| ] | |
| const handleAction = (actionId: string) => { | |
| onAction(actionId) | |
| onClose() | |
| } | |
| return ( | |
| <AnimatePresence> | |
| {isOpen && ( | |
| <> | |
| {/* Invisible backdrop to detect outside clicks */} | |
| <div | |
| className="fixed inset-0 z-[79]" | |
| onClick={onClose} | |
| /> | |
| {/* Context Menu */} | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.95 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.95 }} | |
| transition={{ duration: 0.1 }} | |
| className="fixed glass rounded-lg shadow-xl py-1 z-[80] min-w-[200px]" | |
| style={{ | |
| left: position.x, | |
| top: position.y, | |
| // Prevent menu from going off-screen | |
| maxWidth: `calc(100vw - ${position.x}px - 20px)`, | |
| maxHeight: `calc(100vh - ${position.y}px - 20px)` | |
| }} | |
| > | |
| {menuItems.map((item) => { | |
| const Icon = item.icon | |
| return ( | |
| <button | |
| key={item.id} | |
| onClick={() => handleAction(item.id)} | |
| className="w-full text-left px-4 py-1.5 hover:bg-blue-500 hover:text-white transition-colors flex items-center gap-3 text-sm" | |
| > | |
| <Icon size={16} weight="regular" /> | |
| <span>{item.label}</span> | |
| </button> | |
| ) | |
| })} | |
| </motion.div> | |
| </> | |
| )} | |
| </AnimatePresence> | |
| ) | |
| } |