fix(agent): contain the floating assistant panel on open and resize (#1575)
A persisted float rect saved at the viewport edge, or on a larger monitor, passes clampFloatRect (which only keeps 48px reachable so a live drag may deliberately hang off an edge) and renders the panel as a 48px sliver on every open. Add containFloatRect, which snaps the whole window inside the viewport, and an AgentSheet effect that validates the persisted rect on sheet mount and on viewport resize and persists the corrected position. The rect is read through a ref so drag commits do not re-trigger containment: parking the window half off-screen still works within a session. The live drag path and clampFloatRect are unchanged, and containFloatRect's output is always a fixpoint of clampFloatRect, so the render clamp stays a no-op. Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
78a581bca1
commit
7ccaab7a08
@@ -25,6 +25,7 @@ import {
|
||||
DOCK_WIDTH_MIN,
|
||||
clampDockWidth,
|
||||
clampFloatRect,
|
||||
containFloatRect,
|
||||
defaultFloatRect,
|
||||
expandedDockWidth,
|
||||
resizeFloatRect,
|
||||
@@ -251,6 +252,33 @@ export default function AgentSheet({
|
||||
)
|
||||
: null
|
||||
|
||||
// Open/resize-time validation of the persisted float rect: a rect saved at
|
||||
// the viewport edge (or on a larger monitor) passes clampFloatRect but
|
||||
// renders as a 48px sliver, so snap it fully on screen and persist the
|
||||
// corrected position. panelPrefs.float is read through a ref, NOT the deps:
|
||||
// putting it in the deps would re-run this on every drag commit and snap
|
||||
// the window back mid-session, killing the deliberate hang-off-the-edge
|
||||
// allowance of the live drag path. The effect fires on sheet mount (every
|
||||
// fresh open remounts, keyed by the provider) and on viewport resize only.
|
||||
const floatPrefRef = useRef(panelPrefs.float)
|
||||
useEffect(() => {
|
||||
floatPrefRef.current = panelPrefs.float
|
||||
}, [panelPrefs.float])
|
||||
useEffect(() => {
|
||||
if (!floating) return
|
||||
const rect = floatPrefRef.current
|
||||
if (!rect) return
|
||||
const contained = containFloatRect(rect, viewport.w, viewport.h)
|
||||
if (
|
||||
contained.x !== rect.x ||
|
||||
contained.y !== rect.y ||
|
||||
contained.w !== rect.w ||
|
||||
contained.h !== rect.h
|
||||
) {
|
||||
updatePanelPrefs({ float: contained })
|
||||
}
|
||||
}, [floating, viewport.w, viewport.h, updatePanelPrefs])
|
||||
|
||||
// Reserve page margin while docked, compact AND expanded: both reflow the
|
||||
// page beside the panel instead of covering it (the original complaint).
|
||||
// Floating and collapsed claim nothing; below md the margin variable is
|
||||
|
||||
Reference in New Issue
Block a user