From 7a90f3aec052558328eb2bb8c342d3591425e6e9 Mon Sep 17 00:00:00 2001 From: Omri Katz <9701896+omridevk@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:58:20 +0300 Subject: [PATCH 1/3] fix(app): isolate pane query reads behind suspense islands so the route boundary never detaches the composer (#346) solid-router wraps every route Match in a Suspense with an undefined fallback. Solid registers a suspension when a solid-query `.data` read runs inside a non-user computation (a memo or a JSX render effect) while the query is pending with no cached data, and the nearest enclosing Suspense catches it. With no inner boundary that was the route Match, so the whole subtree detached: blank shell, composer unmounted, focus lost. Per the user's direction this uses the platform rather than guarding the reads: every query-reading island now sits in its own Suspense with a real loading state (session pill, context usage, view tabs, composer actions, thread) and the reads stay plain. The root FAB's working state became a real ring element inside its own boundary, so the button, its ref and the mascot rig never suspend. The composer input shares a boundary with no query read at all. Co-Authored-By: Claude Fable 5 --- apps/conciv/src/pane/chat-pane.tsx | 5 +- apps/conciv/src/routes/panel.$sessionId.tsx | 63 ++++++++++++--------- apps/conciv/src/routes/quick.tsx | 21 ++++--- apps/conciv/src/shell/fab-robot.tsx | 2 +- apps/conciv/src/shell/fab.tsx | 17 ++++-- apps/conciv/src/shell/pending.tsx | 45 +++++++++++++++ apps/conciv/src/styles.css | 2 +- 7 files changed, 111 insertions(+), 44 deletions(-) create mode 100644 apps/conciv/src/shell/pending.tsx diff --git a/apps/conciv/src/pane/chat-pane.tsx b/apps/conciv/src/pane/chat-pane.tsx index 167a41f52..23c48eb66 100644 --- a/apps/conciv/src/pane/chat-pane.tsx +++ b/apps/conciv/src/pane/chat-pane.tsx @@ -42,6 +42,7 @@ import {ToolFallbackCard} from './tool-fallback-card.js' import {useComposerTriggerSources} from './trigger-sources.js' import {GrabReference} from './grab-reference.js' import {CompactSpinner, ConversationSkeleton, Divider, ThinkingBubble} from './indicators.js' +import {ComposerActionsPending} from '../shell/pending.js' import {EmptyStateSlot} from '../shell/empty-state.js' import {ExtensionSurface} from '../extension/extension-slots.js' import {makePaneGrabApi} from '../extension/pane-grab.js' @@ -313,7 +314,7 @@ export function ChatPane(props: {sessionId: string}): JSX.Element { > - + }> }> : undefined} triggers={triggerSources} > - + }>