fix viz layout stability

This commit is contained in:
2025-08-24 17:43:46 +01:00
parent 45105e0b77
commit ffecb9e591
4 changed files with 32 additions and 42 deletions

View File

@@ -68,7 +68,7 @@ export default async function PatternDetailPage({ params }: PageProps) {
: null; : null;
return ( return (
<div className="max-w-4xl mx-auto space-y-8"> <div className="mx-auto space-y-8">
{/* Header */} {/* Header */}
<div> <div>
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">

View File

@@ -66,7 +66,7 @@ export function MonotonicStackVisualization({
/> />
)} )}
<div className="flex items-end gap-6"> <div className="flex min-h-[180px] items-end gap-6">
{/* Stack (left side) */} {/* Stack (left side) */}
{stack && <StackView stack={stack} />} {stack && <StackView stack={stack} />}

View File

@@ -36,60 +36,50 @@ export function ExplanationPanel({
return ( return (
<div <div
className={cn( className={cn(
'h-28 overflow-y-auto rounded-lg border border-border bg-surface p-4', 'flex h-28 gap-4 rounded-lg border border-border bg-surface p-3',
className className
)} )}
> >
<div className="mb-3 flex items-center gap-2"> {/* Left side: phase badge + explanation */}
<div className="flex flex-1 flex-col overflow-hidden">
<span <span
className={cn( className={cn(
'rounded-full px-2.5 py-0.5 text-xs font-medium', 'mb-1.5 w-fit rounded-full px-2 py-0.5 text-xs font-medium',
PHASE_COLORS[phase] PHASE_COLORS[phase]
)} )}
> >
{PHASE_LABELS[phase]} {PHASE_LABELS[phase]}
</span> </span>
<AnimatePresence mode="wait">
<motion.p
key={explanation}
initial={{ opacity: 0, y: 5 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -5 }}
transition={{ duration: 0.15 }}
className="text-sm leading-snug text-foreground"
>
{explanation}
</motion.p>
</AnimatePresence>
</div> </div>
<AnimatePresence mode="wait"> {/* Right side: decision point (full height) */}
<motion.div
key={explanation}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<p className="text-base leading-relaxed text-foreground">
{explanation}
</p>
{decision && ( {decision && (
<motion.div <motion.div
initial={{ opacity: 0, scale: 0.95 }} key={decision.question}
animate={{ opacity: 1, scale: 1 }} initial={{ opacity: 0, x: 10 }}
className="mt-4 rounded-lg border border-primary/30 bg-primary/5 p-4" animate={{ opacity: 1, x: 0 }}
className="flex w-72 shrink-0 flex-col justify-center rounded-lg border border-primary/30 bg-primary/5 px-3 py-2 text-xs"
> >
<div className="mb-2 text-sm font-medium text-primary"> <div className="mb-1 font-medium text-primary">Decision Point</div>
Decision Point <div className="flex items-center gap-1">
</div>
<div className="space-y-2 text-sm">
<div className="flex items-start gap-2">
<span className="font-medium text-foreground-muted">Q:</span>
<span className="text-foreground">{decision.question}</span> <span className="text-foreground">{decision.question}</span>
</div>
<div className="flex items-start gap-2">
<span className="font-medium text-foreground-muted">A:</span>
<span className="font-mono text-primary">{decision.answer}</span> <span className="font-mono text-primary">{decision.answer}</span>
</div> </div>
<div className="flex items-start gap-2"> <div className="mt-0.5 text-success"> {decision.action}</div>
<span className="font-medium text-foreground-muted"></span>
<span className="text-success">{decision.action}</span>
</div>
</div>
</motion.div> </motion.div>
)} )}
</motion.div>
</AnimatePresence>
</div> </div>
); );
} }

View File

@@ -69,7 +69,7 @@ export function VisualizationContainer({
</span> </span>
</header> </header>
<div className="grid gap-3 lg:grid-cols-[1fr_1.5fr]"> <div className="grid gap-3 lg:grid-cols-[1fr_2fr]">
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
<CodePanel <CodePanel
code={code} code={code}