Add notes preview/edit toggle to group session dialog

- Notes now default to a rendered markdown preview instead of the raw
  editor, reducing visual noise when scanning group context.
- A pencil/eye icon button next to the label flips between the two modes.
- Preview panel is styled with the group tint and a distinct border so it
  reads as group-level notes rather than another to-do row.
- Todo row edit toggle also swaps to an Eye icon while editing for
  consistent affordance.
This commit is contained in:
Brian Fertig 2026-09-29 08:21:53 -06:00
parent ba4e7f3803
commit 0a8f374506
1 changed files with 46 additions and 9 deletions

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { ChevronDown, ChevronRight, Pencil, Plus, Sparkles, Trash2, X, XIcon } from "lucide-react"; import { ChevronDown, ChevronRight, Eye, Pencil, Plus, Sparkles, Trash2, X, XIcon } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@ -113,6 +113,10 @@ export function GroupSessionDialog({
const [noteDraft, setNoteDraft] = useState(group.noteContent); const [noteDraft, setNoteDraft] = useState(group.noteContent);
const [todoDrafts, setTodoDrafts] = useState<TodoDraft[]>(() => toDrafts(group.todos)); const [todoDrafts, setTodoDrafts] = useState<TodoDraft[]>(() => toDrafts(group.todos));
// Notes default to a rendered markdown preview; the pencil by the label
// flips into the full editor (and back). Kept out of the todo row state
// so it never collides with per-row edit toggles.
const [notesEditing, setNotesEditing] = useState(false);
const [aiOpen, setAiOpen] = useState(false); const [aiOpen, setAiOpen] = useState(false);
const [todoAiOpen, setTodoAiOpen] = useState(false); const [todoAiOpen, setTodoAiOpen] = useState(false);
const [savingAll, setSavingAll] = useState(false); const [savingAll, setSavingAll] = useState(false);
@ -133,6 +137,7 @@ export function GroupSessionDialog({
if (next) { if (next) {
setNoteDraft(group.noteContent); setNoteDraft(group.noteContent);
setTodoDrafts(toDrafts(group.todos)); setTodoDrafts(toDrafts(group.todos));
setNotesEditing(false);
} else { } else {
// Fire-and-forget: close immediately, flush any pending autosaves in // Fire-and-forget: close immediately, flush any pending autosaves in
// the background. board-context's mutators already toast on failure, // the background. board-context's mutators already toast on failure,
@ -247,13 +252,45 @@ export function GroupSessionDialog({
<div className="flex-1 space-y-6 overflow-y-auto overscroll-contain p-4"> <div className="flex-1 space-y-6 overflow-y-auto overscroll-contain p-4">
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center gap-2">
<Label className="text-sm font-medium">Notes</Label> <Label className="text-sm font-medium">Notes</Label>
<Button
type="button"
variant="ghost"
size="icon-sm"
onClick={() => setNotesEditing((v) => !v)}
aria-label={notesEditing ? "Preview notes" : "Edit notes"}
>
{notesEditing ? <Eye className="size-4" /> : <Pencil className="size-4" />}
</Button>
</div>
{notesEditing ? (
<MDEditor <MDEditor
value={noteDraft} value={noteDraft}
onChange={(v) => setNoteDraft(v ?? "")} onChange={(v) => setNoteDraft(v ?? "")}
height={280} height={280}
preview="edit" preview="edit"
/> />
) : (
// Rendered as a distinct group-note panel -- full group tint,
// stronger rule, no indent -- so it reads as notes for the
// whole group rather than another to-do row.
<div
className="max-h-72 overflow-y-auto rounded-lg border p-4"
style={{
borderColor: ruleColor,
backgroundColor: panelBackground,
}}
>
{noteDraft.trim() ? (
<MarkdownPreview source={noteDraft} />
) : (
<p className="text-sm text-muted-foreground">
No notes yet — use the pencil above to add some.
</p>
)}
</div>
)}
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@ -556,7 +593,7 @@ function SessionTodoRow({
onClick={() => setEditingDetails((v) => !v)} onClick={() => setEditingDetails((v) => !v)}
aria-label={`${editingDetails ? "Preview" : "Edit"} details for "${draft.title || "new to-do"}"`} aria-label={`${editingDetails ? "Preview" : "Edit"} details for "${draft.title || "new to-do"}"`}
> >
<Pencil className="size-4" /> {editingDetails ? <Eye className="size-4" /> : <Pencil className="size-4" />}
</Button> </Button>
{onCollapse && ( {onCollapse && (
<Button <Button