From 1d33d967a16482994ee4bab18806a37fb4159ac1 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Tue, 14 Jul 2026 03:26:41 +0800 Subject: [PATCH] feat(console-ai): FAB becomes the ChatDock launcher when the dock is on (ADR-0057 P3b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ConsoleChatbotFab gains onOpenDock: when set (dock enabled), a click and a designer open-signal open the dock rail instead of arming the floating overlay, and the heavy floating chatbot is never mounted. ConsoleLayout passes dock.expand when dockEnabled and drops P3a's edge launcher (FAB is the launcher). Flag OFF → unchanged. Unit-tested. Co-Authored-By: Claude Opus 4.8 --- .changeset/adr-0057-p3b-fab-launcher.md | 13 +++++++++ .../src/layout/ConsoleChatbotFab.tsx | 29 ++++++++++++++----- .../app-shell/src/layout/ConsoleLayout.tsx | 12 ++++---- .../__tests__/ConsoleChatbotFab.test.tsx | 14 ++++++++- 4 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 .changeset/adr-0057-p3b-fab-launcher.md diff --git a/.changeset/adr-0057-p3b-fab-launcher.md b/.changeset/adr-0057-p3b-fab-launcher.md new file mode 100644 index 0000000000..810df07495 --- /dev/null +++ b/.changeset/adr-0057-p3b-fab-launcher.md @@ -0,0 +1,13 @@ +--- +"@object-ui/app-shell": patch +--- + +feat(console-ai): the FAB becomes the ChatDock launcher when the dock is on (ADR-0057 P3b) + +When `features.chatDock` is enabled, the console FAB opens the docked rail instead +of the floating overlay — one entry point, the ADR's "FAB → launcher" step. In +dock mode the FAB stays the lightweight button (it never mounts the heavy floating +chatbot; the rail loads the chat on demand), and a designer "Ask AI" open signal +(assistantBus) opens the dock too. With the flag OFF the FAB is unchanged (floating +overlay). Supersedes P3a's edge launcher (the dock is gated on the same +`showChatbot`, so the FAB is always present to launch it). diff --git a/packages/app-shell/src/layout/ConsoleChatbotFab.tsx b/packages/app-shell/src/layout/ConsoleChatbotFab.tsx index 9be3ae63c1..7d05b62b5f 100644 --- a/packages/app-shell/src/layout/ConsoleChatbotFab.tsx +++ b/packages/app-shell/src/layout/ConsoleChatbotFab.tsx @@ -26,25 +26,38 @@ const prefetchChatbot = () => { import type { ConsoleFloatingChatbotProps } from './ConsoleFloatingChatbot'; -export type ConsoleChatbotFabProps = ConsoleFloatingChatbotProps; +export type ConsoleChatbotFabProps = ConsoleFloatingChatbotProps & { + /** + * ADR-0057 P3b — when the ChatDock is enabled, the FAB becomes the dock's + * LAUNCHER: a click (and a designer "Ask AI" open signal) opens the docked + * rail instead of arming the floating overlay, and the heavy floating chatbot + * is never mounted (the dock owns the chat). Absent → unchanged floating-FAB + * behavior. + */ + onOpenDock?: () => void; +}; -export function ConsoleChatbotFab(props: ConsoleChatbotFabProps) { +export function ConsoleChatbotFab({ onOpenDock, ...props }: ConsoleChatbotFabProps) { const [armed, setArmed] = useState(false); const { t } = useObjectTranslation(); // A designer surface can ask the assistant to open (e.g. an "Ask AI" // button) via the assistant bus — arming the lazy chatbot just like a // click does. Once armed, the chatbot's own trigger owns open/close. + // When the dock is the target (P3b), the open signal opens the dock instead. const { openSeq } = useAssistant(); const seenOpenSeq = useRef(openSeq); useEffect(() => { if (openSeq !== seenOpenSeq.current) { seenOpenSeq.current = openSeq; - setArmed(true); + if (onOpenDock) onOpenDock(); + else setArmed(true); } - }, [openSeq]); + }, [openSeq, onOpenDock]); - if (armed) { + // Dock mode (P3b): stay the lightweight launcher — never mount the floating + // overlay; the click opens the rail, which loads the chat on demand. + if (armed && !onOpenDock) { return ( @@ -56,9 +69,9 @@ export function ConsoleChatbotFab(props: ConsoleChatbotFabProps) {