Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions archon-ui-main/src/components/layout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ export function MainLayout({ children, className }: MainLayoutProps) {
}, [isBackendError, backendError, showToast]);

return (
<div className={cn("relative min-h-screen bg-white dark:bg-black overflow-hidden", className)}>
<div className={cn("relative min-h-screen overflow-hidden", className)}>
{/* TEMPORARY: Show backend startup error using old component */}
{backendStartupFailed && <BackendStartupError />}

{/* Fixed full-page background grid that doesn't scroll */}
{/* Fixed full-page background - grid pattern on dark background */}
<div className="fixed inset-0 bg-white dark:bg-black pointer-events-none -z-10" />
<div className="fixed inset-0 neon-grid pointer-events-none z-0" />

{/* Floating Navigation */}
Expand All @@ -143,7 +144,7 @@ export function MainLayout({ children, className }: MainLayoutProps) {
</div>

{/* Main Content Area - matches old layout exactly */}
<div className="relative flex-1 pl-[100px] z-10">
<div className="relative flex-1 pl-[100px]">
<div className="container mx-auto px-8 relative">
<div className="min-h-screen pt-8 pb-16">{children}</div>
</div>
Expand Down
48 changes: 13 additions & 35 deletions archon-ui-main/src/features/projects/components/ProjectCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { motion } from "framer-motion";
import { Activity, CheckCircle2, ListTodo } from "lucide-react";
import type React from "react";
import { isOptimistic } from "@/features/shared/utils/optimistic";
import { OptimisticIndicator } from "../../ui/primitives/OptimisticIndicator";
import { SelectableCard } from "../../ui/primitives/selectable-card";
import { cn } from "../../ui/primitives/styles";
import type { Project } from "../types";
import { ProjectCardActions } from "./ProjectCardActions";
Expand Down Expand Up @@ -33,46 +33,24 @@ export const ProjectCard: React.FC<ProjectCardProps> = ({
const optimistic = isOptimistic(project);

return (
<motion.div
tabIndex={0}
aria-label={`Select project ${project.title}`}
aria-current={isSelected ? "true" : undefined}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
onSelect(project);
}
}}
onClick={() => onSelect(project)}
<SelectableCard
isSelected={isSelected}
isPinned={project.pinned}
showAuroraGlow={isSelected}
onSelect={() => onSelect(project)}
blur="xl"
transparency="light"
size="none"
className={cn(
"relative rounded-xl backdrop-blur-md w-72 min-h-[180px] cursor-pointer overflow-visible group flex flex-col",
"transition-all duration-300",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-purple-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-zinc-900",
"w-72 min-h-[180px] flex flex-col shrink-0",
project.pinned
? "bg-gradient-to-b from-purple-100/80 via-purple-50/30 to-purple-100/50 dark:from-purple-900/30 dark:via-purple-900/20 dark:to-purple-900/10"
: isSelected
? "bg-gradient-to-b from-white/70 via-purple-50/20 to-white/50 dark:from-white/5 dark:via-purple-900/5 dark:to-black/20"
: "bg-gradient-to-b from-white/80 to-white/60 dark:from-white/10 dark:to-black/30",
"border",
project.pinned
? "border-purple-500/80 dark:border-purple-500/80 shadow-[0_0_15px_rgba(168,85,247,0.3)]"
: isSelected
? "border-purple-400/60 dark:border-purple-500/60"
: "border-gray-200 dark:border-zinc-800/50",
isSelected
? "shadow-[0_0_15px_rgba(168,85,247,0.4),0_0_10px_rgba(147,51,234,0.3)] dark:shadow-[0_0_20px_rgba(168,85,247,0.5),0_0_15px_rgba(147,51,234,0.4)]"
: "shadow-[0_10px_30px_-15px_rgba(0,0,0,0.1)] dark:shadow-[0_10px_30px_-15px_rgba(0,0,0,0.7)]",
"hover:shadow-[0_15px_40px_-15px_rgba(0,0,0,0.2)] dark:hover:shadow-[0_15px_40px_-15px_rgba(0,0,0,0.9)]",
isSelected ? "scale-[1.02]" : "hover:scale-[1.01]", // Use scale instead of translate to avoid clipping
optimistic && "opacity-80 ring-1 ring-cyan-400/30",
)}
>
{/* Subtle aurora glow effect for selected card */}
{isSelected && (
<div className="absolute inset-0 rounded-xl overflow-hidden opacity-30 dark:opacity-40 pointer-events-none">
<div className="absolute -inset-[100px] bg-[radial-gradient(circle,rgba(168,85,247,0.8)_0%,rgba(147,51,234,0.6)_40%,transparent_70%)] blur-3xl animate-[pulse_8s_ease-in-out_infinite]"></div>
</div>
)}

{/* Main content area with padding */}
<div className="flex-1 p-4 pb-2">
Expand All @@ -94,7 +72,7 @@ export const ProjectCard: React.FC<ProjectCardProps> = ({
</div>

{/* Task count pills */}
<div className="flex items-stretch gap-2 w-full">
<div className="flex flex-col sm:flex-row items-stretch gap-2 w-full">
{/* Todo pill */}
<div className="relative flex-1">
<div
Expand Down Expand Up @@ -253,7 +231,7 @@ export const ProjectCard: React.FC<ProjectCardProps> = ({
<div className="flex items-center justify-between px-3 py-2 mt-auto border-t border-gray-200/30 dark:border-gray-700/20">
{/* Pinned indicator badge */}
{project.pinned ? (
<div className="px-2 py-0.5 bg-purple-500 text-white text-[10px] font-bold rounded-full shadow-lg shadow-purple-500/30">
<div className="px-2 py-0.5 bg-purple-500 dark:bg-purple-600 text-white text-[10px] font-bold rounded-full shadow-lg shadow-purple-500/30">
DEFAULT
</div>
) : (
Expand All @@ -275,6 +253,6 @@ export const ProjectCard: React.FC<ProjectCardProps> = ({
}}
/>
</div>
</motion.div>
</SelectableCard>
);
};
79 changes: 73 additions & 6 deletions archon-ui-main/src/features/projects/components/ProjectHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { motion } from "framer-motion";
import { Plus } from "lucide-react";
import { LayoutGrid, List, Plus, Search, X } from "lucide-react";
import type React from "react";
import { ReactNode } from "react";
import { Button } from "../../ui/primitives/button";
import { Input } from "../../ui/primitives/input";
import { cn } from "../../ui/primitives/styles";

interface ProjectHeaderProps {
onNewProject: () => void;
layoutMode?: "horizontal" | "sidebar";
onLayoutModeChange?: (mode: "horizontal" | "sidebar") => void;
rightContent?: ReactNode;
searchQuery?: string;
onSearchChange?: (query: string) => void;
}

const titleVariants = {
Expand All @@ -25,7 +33,14 @@ const itemVariants = {
},
};

export const ProjectHeader: React.FC<ProjectHeaderProps> = ({ onNewProject }) => {
export const ProjectHeader: React.FC<ProjectHeaderProps> = ({
onNewProject,
layoutMode,
onLayoutModeChange,
rightContent,
searchQuery,
onSearchChange,
}) => {
return (
<motion.div
className="flex items-center justify-between mb-8"
Expand All @@ -44,10 +59,62 @@ export const ProjectHeader: React.FC<ProjectHeaderProps> = ({ onNewProject }) =>
/>
Projects
</motion.h1>
<Button onClick={onNewProject} variant="cyan" className="shadow-lg shadow-cyan-500/20">
<Plus className="w-4 h-4 mr-2" />
New Project
</Button>
<div className="flex items-center gap-3">
{/* Search input */}
{searchQuery !== undefined && onSearchChange && (
<div className="relative w-64">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="text"
placeholder="Search projects..."
value={searchQuery}
onChange={(e) => onSearchChange(e.target.value)}
className="pl-9 pr-8"
aria-label="Search projects"
/>
{searchQuery && (
<button
type="button"
onClick={() => onSearchChange("")}
className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
aria-label="Clear search"
>
<X className="w-4 h-4" />
</button>
)}
</div>
)}
{/* Layout toggle - show if mode and change handler provided */}
{layoutMode && onLayoutModeChange && (
<div className="flex gap-1 p-1 bg-black/30 dark:bg-black/50 rounded-lg border border-white/10">
<Button
variant="ghost"
size="sm"
onClick={() => onLayoutModeChange("horizontal")}
className={cn("px-3", layoutMode === "horizontal" && "bg-purple-500/20 text-purple-400")}
aria-label="Switch to horizontal layout"
aria-pressed={layoutMode === "horizontal"}
>
<LayoutGrid className="w-4 h-4" aria-hidden="true" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => onLayoutModeChange("sidebar")}
className={cn("px-3", layoutMode === "sidebar" && "bg-purple-500/20 text-purple-400")}
aria-label="Switch to sidebar layout"
aria-pressed={layoutMode === "sidebar"}
>
<List className="w-4 h-4" aria-hidden="true" />
</Button>
</div>
)}
{rightContent}
<Button onClick={onNewProject} variant="cyan" className="shadow-lg shadow-cyan-500/20">
<Plus className="w-4 h-4 mr-2" />
New Project
</Button>
</div>
</motion.div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ProjectList: React.FC<ProjectListProps> = ({
}

return (
<motion.div initial="hidden" animate="visible" className="relative mb-10" variants={itemVariants}>
<motion.div initial="hidden" animate="visible" className="relative mb-10 w-full" variants={itemVariants}>
<div className="overflow-x-auto overflow-y-visible pb-4 pt-2 pr-6 md:pr-8 scrollbar-thin">
<ul className="flex gap-4 min-w-max pl-6 md:pl-8" aria-label="Projects">
{sortedProjects.map((project) => (
Expand Down
Loading