+```
+
+Also add a small progress bar under the header. Change lines 39-50 (the header section) to:
+
+```tsx
+ {/* Header + progress */}
+
+
+
+ Checklist
+
+ {checklist.length > 0 && (
+
+ {checked}/{checklist.length}
+
+ )}
+
+ {checklist.length > 0 && (
+
+ )}
+
+```
+
+**Step 2: Verify TypeScript compiles**
+
+Run: `npx tsc --noEmit`
+Expected: No errors
+
+**Step 3: Commit**
+
+```bash
+git add src/components/card-detail/ChecklistSection.tsx
+git commit -m "feat: add scroll containment and progress bar to checklist"
+```
+
+---
+
+### Task 4: Remove unused Separator import + visual verification
+
+**Files:**
+- Modify: `src/components/card-detail/CardDetailModal.tsx` (verify no stale imports)
+
+**Step 1: Verify the file has no unused imports**
+
+The rewrite in Task 1 already removed the `Separator` import. Confirm the import block does NOT include:
+- `import { Separator } from "@/components/ui/separator";`
+
+If it's still there, delete it.
+
+**Step 2: Run TypeScript check**
+
+Run: `npx tsc --noEmit`
+Expected: No errors
+
+**Step 3: Run the dev server and visually verify**
+
+Run: `npm run dev` (or `npx tauri dev` if checking in Tauri)
+
+Verify:
+- Card detail modal opens on card click
+- Full-width header shows cover color (or neutral bg)
+- Title is editable (click to edit, Enter/Escape)
+- Close button [x] works
+- 2x3 grid: Labels | Due Date / Checklist | Description / Cover | Attachments
+- Each cell has rounded-lg background
+- Checklist scrolls when > ~6 items
+- Description shows compact preview
+- All animations stagger in
+- Escape closes modal
+- Click outside closes modal
+
+**Step 4: Commit**
+
+```bash
+git add -A
+git commit -m "feat: card detail modal dashboard grid redesign complete"
+```
diff --git a/src/components/card-detail/CardDetailModal.tsx b/src/components/card-detail/CardDetailModal.tsx
index 35b0324..77d914b 100644
--- a/src/components/card-detail/CardDetailModal.tsx
+++ b/src/components/card-detail/CardDetailModal.tsx
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef } from "react";
import { AnimatePresence, motion } from "framer-motion";
-import { Separator } from "@/components/ui/separator";
+import { X } from "lucide-react";
import { useBoardStore } from "@/stores/board-store";
import { MarkdownEditor } from "@/components/card-detail/MarkdownEditor";
import { ChecklistSection } from "@/components/card-detail/ChecklistSection";
@@ -38,74 +38,112 @@ export function CardDetailModal({ cardId, onClose }: CardDetailModalProps) {
/>
{/* Modal */}
-
+
e.stopPropagation()}
>
- {/* Close on Escape */}
-
- {/* Hidden accessible description */}
Card detail editor
+ {/* Header: cover color background + title + close */}
+
+
+
+
+
+ {/* Dashboard grid body */}
- {/* Left panel: Title + Markdown (60%) */}
+ {/* Row 1: Labels + Due Date */}
-
-
-
-
-
-
-
- {/* Vertical separator */}
-
-
- {/* Right sidebar (40%) */}
-
-
-
-
-
+
-
-
+
+
-
-
+ {/* Row 2: Checklist + Description */}
+
+
-
+
+
+
+ {/* Row 3: Cover + Attachments */}
+
+
+
+
+
void;
+ hasColor: boolean;
}
-function InlineTitle({ cardId, title, updateCard }: InlineTitleProps) {
+function InlineTitle({ cardId, title, updateCard, hasColor }: InlineTitleProps) {
const [editing, setEditing] = useState(false);
const [draft, setDraft] = useState(title);
const inputRef = useRef(null);
@@ -177,6 +216,9 @@ function InlineTitle({ cardId, title, updateCard }: InlineTitleProps) {
}
}
+ const textColor = hasColor ? "text-white" : "text-pylon-text";
+ const hoverColor = hasColor ? "hover:text-white/80" : "hover:text-pylon-accent";
+
if (editing) {
return (
setDraft(e.target.value)}
onBlur={handleSave}
onKeyDown={handleKeyDown}
- className="font-heading text-xl text-pylon-text bg-transparent outline-none border-b border-pylon-accent pb-0.5"
+ className={`flex-1 font-heading text-xl bg-transparent outline-none border-b pb-0.5 ${
+ hasColor ? "text-white border-white/50" : "text-pylon-text border-pylon-accent"
+ }`}
/>
);
}
@@ -193,7 +237,7 @@ function InlineTitle({ cardId, title, updateCard }: InlineTitleProps) {
return (
setEditing(true)}
- className="cursor-pointer font-heading text-xl text-pylon-text transition-colors hover:text-pylon-accent"
+ className={`flex-1 cursor-pointer font-heading text-xl transition-colors ${textColor} ${hoverColor}`}
>
{title}
@@ -202,14 +246,25 @@ function InlineTitle({ cardId, title, updateCard }: InlineTitleProps) {
/* ---------- Cover color picker ---------- */
-function CoverColorPicker({ cardId, coverColor }: { cardId: string; coverColor: string | null }) {
+function CoverColorPicker({
+ cardId,
+ coverColor,
+}: {
+ cardId: string;
+ coverColor: string | null;
+}) {
const updateCard = useBoardStore((s) => s.updateCard);
const presets = [
- { hue: "160", label: "Teal" }, { hue: "240", label: "Blue" },
- { hue: "300", label: "Purple" }, { hue: "350", label: "Pink" },
- { hue: "25", label: "Red" }, { hue: "55", label: "Orange" },
- { hue: "85", label: "Yellow" }, { hue: "130", label: "Lime" },
- { hue: "200", label: "Cyan" }, { hue: "0", label: "Slate" },
+ { hue: "160", label: "Teal" },
+ { hue: "240", label: "Blue" },
+ { hue: "300", label: "Purple" },
+ { hue: "350", label: "Pink" },
+ { hue: "25", label: "Red" },
+ { hue: "55", label: "Orange" },
+ { hue: "85", label: "Yellow" },
+ { hue: "130", label: "Lime" },
+ { hue: "200", label: "Cyan" },
+ { hue: "0", label: "Slate" },
];
return (
@@ -232,7 +287,8 @@ function CoverColorPicker({ cardId, coverColor }: { cardId: string; coverColor:
className="size-6 rounded-full transition-transform hover:scale-110"
style={{
backgroundColor: `oklch(55% 0.12 ${hue})`,
- outline: coverColor === hue ? "2px solid currentColor" : "none",
+ outline:
+ coverColor === hue ? "2px solid currentColor" : "none",
outlineOffset: "1px",
}}
title={label}
diff --git a/src/components/card-detail/ChecklistSection.tsx b/src/components/card-detail/ChecklistSection.tsx
index 5c59d33..d03265f 100644
--- a/src/components/card-detail/ChecklistSection.tsx
+++ b/src/components/card-detail/ChecklistSection.tsx
@@ -37,20 +37,30 @@ export function ChecklistSection({ cardId, checklist }: ChecklistSectionProps) {
return (
- {/* Header */}
-
-
- Checklist
-
+ {/* Header + progress */}
+
+
+
+ Checklist
+
+ {checklist.length > 0 && (
+
+ {checked}/{checklist.length}
+
+ )}
+
{checklist.length > 0 && (
-
- {checked}/{checklist.length}
-
+
)}
{/* Items */}
-
+
{checklist.map((item) => (
) : (
setMode("edit")}
>
{draft ? (