Update panel
This commit is contained in:
@@ -6,8 +6,6 @@ import {
|
||||
Clock,
|
||||
FileText,
|
||||
Code,
|
||||
Maximize2,
|
||||
Minimize2,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
@@ -22,6 +20,7 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
|
||||
import { makeRequest } from "@/lib/api";
|
||||
import { getTaskPanelClasses, getBackdropClasses } from "@/lib/responsive-config";
|
||||
import type {
|
||||
TaskStatus,
|
||||
TaskAttempt,
|
||||
@@ -39,8 +38,6 @@ interface TaskDetailsPanelProps {
|
||||
projectId: string;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
viewMode: "overlay" | "sideBySide";
|
||||
onViewModeChange: (mode: "overlay" | "sideBySide") => void;
|
||||
}
|
||||
|
||||
const statusLabels: Record<TaskStatus, string> = {
|
||||
@@ -153,8 +150,6 @@ export function TaskDetailsPanel({
|
||||
projectId,
|
||||
isOpen,
|
||||
onClose,
|
||||
viewMode,
|
||||
onViewModeChange,
|
||||
}: TaskDetailsPanelProps) {
|
||||
const [taskAttempts, setTaskAttempts] = useState<TaskAttempt[]>([]);
|
||||
const [selectedAttempt, setSelectedAttempt] = useState<TaskAttempt | null>(
|
||||
@@ -342,24 +337,15 @@ export function TaskDetailsPanel({
|
||||
<>
|
||||
{isOpen && (
|
||||
<>
|
||||
{/* Backdrop - only in overlay mode */}
|
||||
{viewMode === "overlay" && (
|
||||
<div
|
||||
className="fixed inset-0 z-40 bg-background/80 backdrop-blur-sm"
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
{/* Backdrop - only on smaller screens (overlay mode) */}
|
||||
<div
|
||||
className={getBackdropClasses()}
|
||||
onClick={onClose}
|
||||
/>
|
||||
|
||||
{/* Panel */}
|
||||
<div
|
||||
className={`
|
||||
${
|
||||
viewMode === "overlay"
|
||||
? "fixed inset-y-0 right-0 z-50 w-full sm:w-[800px]"
|
||||
: "w-full sm:w-[800px] h-full relative"
|
||||
}
|
||||
bg-background border-l shadow-lg overflow-hidden
|
||||
`}
|
||||
className={getTaskPanelClasses()}
|
||||
>
|
||||
<div className="flex flex-col h-full">
|
||||
{/* Header */}
|
||||
@@ -388,26 +374,6 @@ export function TaskDetailsPanel({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() =>
|
||||
onViewModeChange(
|
||||
viewMode === "overlay" ? "sideBySide" : "overlay"
|
||||
)
|
||||
}
|
||||
title={
|
||||
viewMode === "overlay"
|
||||
? "Switch to side-by-side view"
|
||||
: "Switch to overlay view"
|
||||
}
|
||||
>
|
||||
{viewMode === "overlay" ? (
|
||||
<Maximize2 className="h-4 w-4" />
|
||||
) : (
|
||||
<Minimize2 className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" onClick={onClose}>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
70
frontend/src/lib/responsive-config.ts
Normal file
70
frontend/src/lib/responsive-config.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Centralized responsive configuration for TaskDetailsPanel
|
||||
* Adjust these values to change when the panel switches between overlay and side-by-side modes
|
||||
*/
|
||||
|
||||
// The breakpoint at which we switch from overlay to side-by-side mode
|
||||
// Change this value to adjust when the panel switches to side-by-side mode:
|
||||
// 'sm' = 640px, 'md' = 768px, 'lg' = 1024px, 'xl' = 1280px, '2xl' = 1536px
|
||||
export const PANEL_SIDE_BY_SIDE_BREAKPOINT = "xl" as const;
|
||||
|
||||
// Panel widths for different screen sizes (in overlay mode)
|
||||
export const PANEL_WIDTHS = {
|
||||
base: "w-full", // < 640px
|
||||
sm: "sm:w-[560px]", // 640px+
|
||||
md: "md:w-[600px]", // 768px+
|
||||
lg: "lg:w-[650px]", // 1024px+ (smaller to start transitioning)
|
||||
xl: "xl:w-[750px]", // 1280px+
|
||||
"2xl": "2xl:w-[800px]", // 1536px+ (side-by-side mode)
|
||||
} as const;
|
||||
|
||||
// Generate classes for TaskDetailsPanel
|
||||
export const getTaskPanelClasses = () => {
|
||||
const overlayClasses = [
|
||||
"fixed inset-y-0 right-0 z-50",
|
||||
PANEL_WIDTHS.base,
|
||||
PANEL_WIDTHS.sm,
|
||||
PANEL_WIDTHS.md,
|
||||
PANEL_WIDTHS.lg,
|
||||
PANEL_WIDTHS.xl,
|
||||
].join(" ");
|
||||
|
||||
const sideBySideClasses = [
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:relative`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:inset-auto`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:z-auto`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:h-full`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:w-[800px]`,
|
||||
].join(" ");
|
||||
|
||||
return `${overlayClasses} ${sideBySideClasses} bg-background border-l shadow-lg overflow-hidden`;
|
||||
};
|
||||
|
||||
// Generate classes for backdrop (only show in overlay mode)
|
||||
export const getBackdropClasses = () => {
|
||||
return `fixed inset-0 z-40 bg-background/80 backdrop-blur-sm ${PANEL_SIDE_BY_SIDE_BREAKPOINT}:hidden`;
|
||||
};
|
||||
|
||||
// Generate classes for main container (enable flex layout in side-by-side mode)
|
||||
export const getMainContainerClasses = (isPanelOpen: boolean) => {
|
||||
if (!isPanelOpen) return "w-full";
|
||||
|
||||
return `w-full ${PANEL_SIDE_BY_SIDE_BREAKPOINT}:flex ${PANEL_SIDE_BY_SIDE_BREAKPOINT}:h-full`;
|
||||
};
|
||||
|
||||
// Generate classes for kanban section
|
||||
export const getKanbanSectionClasses = (isPanelOpen: boolean) => {
|
||||
if (!isPanelOpen) return "w-full transition-all duration-300";
|
||||
|
||||
const overlayClasses = "w-full opacity-50 pointer-events-none";
|
||||
const sideBySideClasses = [
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:flex-1`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:min-w-0`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:h-full`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:overflow-y-auto`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:opacity-100`,
|
||||
`${PANEL_SIDE_BY_SIDE_BREAKPOINT}:pointer-events-auto`,
|
||||
].join(" ");
|
||||
|
||||
return `${overlayClasses} ${sideBySideClasses} transition-all duration-300`;
|
||||
};
|
||||
@@ -6,6 +6,7 @@ import { ArrowLeft, Plus } from "lucide-react";
|
||||
import { makeRequest } from "@/lib/api";
|
||||
import { TaskFormDialog } from "@/components/tasks/TaskFormDialog";
|
||||
import { useKeyboardShortcuts } from "@/lib/keyboard-shortcuts";
|
||||
import { getMainContainerClasses, getKanbanSectionClasses } from "@/lib/responsive-config";
|
||||
|
||||
import { TaskKanbanBoard } from "@/components/tasks/TaskKanbanBoard";
|
||||
import { TaskDetailsPanel } from "@/components/tasks/TaskDetailsPanel";
|
||||
@@ -41,7 +42,6 @@ export function ProjectTasks() {
|
||||
// Panel state
|
||||
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
||||
const [viewMode, setViewMode] = useState<"overlay" | "sideBySide">("overlay");
|
||||
|
||||
// Define task creation handler
|
||||
const handleCreateNewTask = () => {
|
||||
@@ -237,9 +237,7 @@ export function ProjectTasks() {
|
||||
setSelectedTask(null);
|
||||
};
|
||||
|
||||
const handleViewModeChange = (mode: "overlay" | "sideBySide") => {
|
||||
setViewMode(mode);
|
||||
};
|
||||
|
||||
|
||||
const handleDragEnd = async (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
@@ -301,25 +299,11 @@ export function ProjectTasks() {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full ${
|
||||
viewMode === "sideBySide" && isPanelOpen ? "flex h-full" : ""
|
||||
}`}
|
||||
className={getMainContainerClasses(isPanelOpen)}
|
||||
>
|
||||
{/* Left Column - Kanban Section */}
|
||||
<div
|
||||
className={`
|
||||
${
|
||||
viewMode === "sideBySide" && isPanelOpen
|
||||
? "flex-1 min-w-0 h-full overflow-y-auto"
|
||||
: "w-full"
|
||||
}
|
||||
${
|
||||
viewMode === "overlay" && isPanelOpen
|
||||
? "opacity-50 pointer-events-none"
|
||||
: ""
|
||||
}
|
||||
transition-all duration-300
|
||||
`}
|
||||
className={getKanbanSectionClasses(isPanelOpen)}
|
||||
>
|
||||
<div className="space-y-6 max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
@@ -396,8 +380,6 @@ export function ProjectTasks() {
|
||||
projectId={projectId!}
|
||||
isOpen={isPanelOpen}
|
||||
onClose={handleClosePanel}
|
||||
viewMode={viewMode}
|
||||
onViewModeChange={handleViewModeChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user