import * as React from 'react'; import { AnimatePresence, motion } from 'framer-motion'; import { cn } from '@/lib/utils'; import KrowAssistant from './KrowAssistant'; import { useAssistantPanel } from './AssistantPanelContext'; /** Panel width, plus the gutter separating it from the dashboard. */ const PANEL_WIDTH = 380; const GUTTER = 24; /** * AssistantPanel — the sliding column the layout renders. * * Animating the aside's `width` (rather than overlaying) is what makes the * dashboard reflow smoothly instead of being covered, and what lets closing * restore the original layout exactly. * * Two things about the structure matter, and both were bugs before: * * 1. The clip lives *inside* the sticky element, not around it. An ancestor with * `overflow: hidden` becomes the nearest scroll container, which silently * disables `position: sticky` on everything beneath it — the panel computed * as sticky but never actually stuck. * * 2. The aside must stretch to the shell's full height. As a flex item under * `items-start` it collapsed to its own height, so its sticky context ended * partway down the page and the panel scrolled away, leaving empty space * beside a long dashboard. * * With both fixed the panel stays pinned for the whole scroll, and because the * assistant is a fixed-height frame, only its conversation scrolls. */ export function AssistantPanel({ stickyClassName, panelHeightClassName }) { const { context, isOpen, close } = useAssistantPanel(); return ( {isOpen && context && (
{/* The clip: contains the slide-in and the fixed panel width while the track animates open, without breaking the sticky above it. */}
{/* Keyed on the context so switching pages gives a clean panel and aborts any response still streaming for the last one. */}
)}
); } export default AssistantPanel;