tahamajs's picture
download
raw
3.57 kB
import { useEffect, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Home } from "lucide-react";
import { useWindowManager } from "./WindowContainer";
interface TaskbarProps {
onLaunchApp?: (appId: string) => void;
apps?: Array<{ id: string; name: string; icon: React.ReactNode; action: () => void }>;
}
export function Taskbar({ onLaunchApp, apps = [] }: TaskbarProps) {
const { windows, activeWindowId, bringToFront, restoreWindow } = useWindowManager();
const [currentTime, setCurrentTime] = useState(new Date());
const [showStartMenu, setShowStartMenu] = useState(false);
useEffect(() => {
const timer = setInterval(() => setCurrentTime(new Date()), 1000);
return () => clearInterval(timer);
}, []);
const formatTime = (date: Date) => date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
return (
<>
<AnimatePresence>
{showStartMenu && (
<motion.div
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 16 }}
className="fixed bottom-12 left-0 z-50 w-64 rounded-2xl bg-white p-2 shadow-2xl dark:bg-gray-800"
>
<div className="space-y-1">
{apps.map((app) => (
<button
key={app.id}
onClick={() => {
app.action();
onLaunchApp?.(app.id);
setShowStartMenu(false);
}}
className="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left transition hover:bg-gray-100 dark:hover:bg-gray-700"
>
{app.icon}
<span>{app.name}</span>
</button>
))}
</div>
</motion.div>
)}
</AnimatePresence>
<div className="fixed bottom-0 left-0 right-0 z-50 flex items-center justify-between rounded-t-2xl bg-white/80 px-3 py-2 backdrop-blur dark:bg-gray-900/80">
<div className="flex items-center gap-2">
<button
onClick={() => setShowStartMenu((prev) => !prev)}
className="rounded-full bg-white p-2 transition hover:bg-white/80 dark:bg-gray-800"
>
<Home className="h-5 w-5 text-primary" />
</button>
<div className="ml-2 flex gap-1">
{apps.slice(0, 3).map((app) => (
<button
key={app.id}
onClick={app.action}
className="rounded-lg bg-white p-1.5 transition hover:bg-white/80 dark:bg-gray-800"
title={app.name}
>
{app.icon}
</button>
))}
</div>
</div>
<div className="flex max-w-[60%] gap-1 overflow-x-auto px-2">
{windows
.filter((w) => w.isOpen)
.map((window) => (
<button
key={window.id}
onClick={() => (window.isMinimized ? restoreWindow(window.id) : bringToFront(window.id))}
className={`rounded-full px-3 py-1 text-xs transition whitespace-nowrap ${
activeWindowId === window.id ? "bg-primary/20 text-primary" : "bg-white/70 dark:bg-gray-800"
}`}
>
{window.title}
</button>
))}
</div>
<span className="rounded-full bg-white px-3 py-1 text-xs dark:bg-gray-800">{formatTime(currentTime)}</span>
</div>
</>
);
}

Xet Storage Details

Size:
3.57 kB
·
Xet hash:
6622b61bf33b787ef6f61ba40f83956f18de84194d1b6d1baa4ddd078f789130

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.