Spaces:
Running
Running
File size: 5,992 Bytes
8af739b 7f20600 062c414 8af739b 734142c bc139ec 8af739b 062c414 8af739b 3c1a712 ad31128 bc139ec 8af739b 734142c 8af739b 734142c 8af739b 734142c 8af739b 7767652 8af739b 734142c 8af739b 7767652 b15ad2e 8af739b 734142c 8af739b 062c414 ad31128 3c1a712 bc139ec 8af739b 734142c 8af739b 5ab4f0a 8af739b ad31128 8af739b 2a1df12 8af739b ad31128 8af739b 062c414 8af739b bc139ec 8af739b ad31128 8af739b bc139ec 8af739b ad31128 8af739b 734142c b15ad2e 734142c 8af739b bc139ec 8af739b bc139ec 734142c 8af739b bc139ec 3c1a712 bc139ec 8af739b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
'use client'
import React, { useState } from 'react'
import {
Folder,
Calendar as CalendarIcon,
Clock as ClockIcon,
Sparkle,
Trash,
FolderOpen,
Compass,
Flask,
DeviceMobile,
Function,
ChatCircleDots
} from '@phosphor-icons/react'
import { motion } from 'framer-motion'
import { DynamicClockIcon } from './DynamicClockIcon'
import { DynamicCalendarIcon } from './DynamicCalendarIcon'
interface MinimizedApp {
id: string
label: string
icon: React.ReactNode
onRestore: () => void
}
interface DockProps {
onOpenFileManager: (path: string) => void
onOpenCalendar: () => void
onOpenClock: () => void
onOpenMessages: () => void
onOpenGeminiChat: () => void
onCloseAllApps?: () => void
openApps: { [key: string]: boolean }
minimizedApps?: MinimizedApp[]
}
interface DockItemProps {
icon: React.ReactNode
label: string
onClick: () => void
isActive?: boolean
className?: string
mouseX: React.MutableRefObject<number | null>
}
const DockItem: React.FC<DockItemProps> = ({ icon, label, onClick, isActive = false, className = '', mouseX }) => {
const [isHovered, setIsHovered] = useState(false)
const ref = React.useRef<HTMLDivElement>(null)
const handleClick = () => {
console.log('Dock item clicked:', label)
if (onClick) {
onClick()
}
}
return (
<div className="dock-item group" ref={ref}>
<motion.button
whileHover={{ scale: 1.2, y: -10 }}
whileTap={{ scale: 0.95 }}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={handleClick}
className={`app-icon w-10 h-10 sm:w-11 sm:h-11 md:w-12 md:h-12 rounded-xl shadow-lg flex items-center justify-center cursor-pointer border transition-all ${className}`}
title={label}
>
{icon}
</motion.button>
<div
className={`dock-dot ${isActive ? 'opacity-100' : ''}`}
id={`dot-${label.toLowerCase().replace(/\s+/g, '-')}`}
/>
</div>
)
}
export function Dock({
onOpenFileManager,
onOpenCalendar,
onOpenClock,
onOpenMessages,
onOpenGeminiChat,
onCloseAllApps,
openApps,
minimizedApps = []
}: DockProps) {
const mouseX = React.useRef<number | null>(null)
const dockItems = [
{
icon: (
<div className="bg-gradient-to-br from-blue-400 to-cyan-200 w-full h-full rounded-xl flex items-center justify-center border border-white/30">
<Folder size={24} weight="regular" className="text-blue-900 md:scale-110" />
</div>
),
label: 'Files',
onClick: () => onOpenFileManager(''),
isActive: openApps['files'],
className: ''
},
{
icon: (
<div className="bg-gradient-to-b from-white to-blue-50 w-full h-full rounded-xl flex items-center justify-center shadow-lg border-[0.5px] border-white/50 relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-white/40 to-transparent" />
<Sparkle size={24} weight="fill" className="text-blue-500 md:scale-110 drop-shadow-sm" />
</div>
),
label: 'Gemini',
onClick: onOpenGeminiChat,
isActive: openApps['gemini'],
className: ''
},
{
icon: (
<div className="bg-gradient-to-b from-[#4CD964] to-[#2E8B57] w-full h-full rounded-xl flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<ChatCircleDots size={24} weight="fill" className="text-white md:scale-110 drop-shadow-md" />
</div>
),
label: 'Messages',
onClick: onOpenMessages,
isActive: openApps['messages'],
className: ''
},
{
icon: (
<div className="w-full h-full">
<DynamicClockIcon />
</div>
),
label: 'Clock',
onClick: onOpenClock,
isActive: openApps['clock'],
className: 'rounded-full'
},
{
icon: (
<div className="w-full h-full">
<DynamicCalendarIcon />
</div>
),
label: 'Calendar',
onClick: onOpenCalendar,
isActive: openApps['calendar'],
className: ''
}
]
return (
<div className="dock-container">
<div
className="dock-glass px-1 pb-1 pt-1.5 sm:px-2 sm:pb-1.5 sm:pt-2 md:px-3 md:pb-2 md:pt-3 rounded-t-2xl md:rounded-2xl flex items-end gap-1 sm:gap-2 md:gap-3 shadow-2xl border border-white/20 transition-all duration-300 overflow-x-auto max-w-full"
onMouseMove={(e) => mouseX.current = e.pageX}
onMouseLeave={() => mouseX.current = null}
>
{dockItems.map((item, index) => (
<DockItem key={item.label} {...item} mouseX={mouseX} />
))}
{/* Minimized apps section */}
{minimizedApps.length > 0 && (
<>
<div className="w-px h-8 md:h-10 bg-gray-400/30 mx-0.5 md:mx-1" />
{minimizedApps.map((app) => (
<div key={app.id} className="relative">
<DockItem
icon={app.icon}
label={`${app.label} (minimized)`}
onClick={app.onRestore}
className="opacity-70 ring-2 ring-yellow-400/50"
mouseX={mouseX}
/>
</div>
))}
</>
)}
{/* Trash */}
<div className="w-px h-8 md:h-10 bg-gray-400/30 mx-0.5 md:mx-1" />
<DockItem
icon={
<div className="bg-gradient-to-b from-gray-200 to-gray-300 w-full h-full rounded-xl flex items-center justify-center border border-white/40">
<Trash size={20} weight="regular" className="text-gray-600 md:scale-110" />
</div>
}
label="Trash"
onClick={() => onCloseAllApps?.()}
className=""
mouseX={mouseX}
/>
</div>
</div>
)
} |