Skip to content

Add docked chat workspace layout and refresh panel styling - #85

Open
tonyfresher wants to merge 18 commits into
mainfrom
workspace-defaults
Open

Add docked chat workspace layout and refresh panel styling#85
tonyfresher wants to merge 18 commits into
mainfrom
workspace-defaults

Conversation

@tonyfresher

Copy link
Copy Markdown
Collaborator

Summary

  • Add a resizable split layout for docking chat beside workspace content.
  • Persist docked chat width and support docking/undocking controls.
  • Prevent accidental popup dismissal when clicking outside.
  • Refresh panel headers, overlays, buttons, and workspace shell styling.
  • Add react-resizable-panels and reusable resizable UI primitives.

Testing

Not run (not requested)

@tonyfresher
tonyfresher requested a review from molefrog August 8, 2026 08:23
@tonyfresher
tonyfresher marked this pull request as ready for review August 8, 2026 08:23
@molefrog

molefrog commented Aug 8, 2026

Copy link
Copy Markdown
Owner

@claude brief me in without going too deep into details.

  • List new and changed user scenarios
  • High-level component composition and state flow
  • Has anything been changed on the server/data storage?
  • Help us find blind spots. What we might have missed here?

format: concise, easy to read and follow

@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown

Claude finished @molefrog's task in 1m 6s —— View job


PR brief

  • Gather context (PR diff, changed files)
  • Summarize new/changed user scenarios
  • Summarize component composition and state flow
  • Check server/data storage changes
  • Identify blind spots / risks
  • Post final summary

New/changed user scenarios

  • Docked chat: from a workspace with content open, "Dock agent" (IconLayoutSidebarRight) splits the screen — workspace content on the left, chat as a resizable column on the right (WorkspaceSplitLayout.tsx). Drag the handle to resize; width persists. "Undock agent" (chevron icon in the chat header) returns to full-screen tabs.
  • New default: brand-new workspaces now open in split mode with agent, widgets, scratchpad all open (previously: full-screen, agent, widgets only) — lib/workspace-layout.ts.
  • Responsive fallback: if the row is too narrow to fit both panes (measured live via useFitsSplitLayout), split silently falls back to full-screen even if layoutMode is saved as split — no dead/broken layout on small screens.
  • Floating chat popup fix: clicking outside the popup no longer dismisses it (ChatPopup.tsx cancels outside-press close events) — likely fixes accidental chat-loss while interacting with page content near the popup.
  • Visual refresh: panel headers, buttons, dialogs, dropdowns, hover cards, and popovers all got small styling passes (borders, sizes, transitions) — cosmetic, no new behavior.

Component composition & state flow

  • WorkspaceScreen.tsx is the orchestrator: computes mode (split vs fullscreen) from saved layoutMode + hasWorkspaceContent + canUseSplit (the last from useFitsSplitLayout, which observes the row's ResizeObserver width against CSS tokens --column-w/--chat-min/--chat-max).
  • When split, WorkspaceSplitLayout.tsx wraps react-resizable-panels (new dependency) around workspacePanel and a docked ChatPanel. It syncs panel size imperatively via a PanelImperativeHandle ref rather than fully controlled props, and reports user-driven resizes back up through onChatWidthChange.
  • Width persists via useUiStore (dockedChatWidth, Zustand + localStorage) — a per-browser preference, correctly not stored in .moi/.workspace.json per the repo's data-flow convention (workspace-shared state vs. per-device UI state).
  • layoutMode and default open tabs, by contrast, are workspace-shared state and live in .moi/.workspace.json via server/layout.ts.
  • Three ChatPanel instances now exist depending on context: dockedChat (split), tabbedChat (full-screen, agent tab active), and the popup instance (full-screen, other tab active) — same component, different docked/onClose wiring.

Server / data storage changes

Small but meaningful:

  • lib/workspace-layout.ts: default layoutMode changed from fullscreensplit; default tabs gained scratchpad. This changes what every new workspace looks like on first load.
  • server/layout.ts: normalizeLayout still validates layoutMode against 'split' | 'fullscreen' — logic unchanged, just the default value and test expectations updated (server/test/layout.test.ts).
  • No new persisted fields, no schema/version bump (version: 1 stays as-is) — this is a value-default change, not a shape change. Existing .workspace.json files with an explicit layoutMode/tabs are unaffected; only new/empty ones pick up the new defaults.

Possible blind spots

  • Existing workspaces silently unaffected: since defaults only apply to new workspaces, existing users won't see split mode or a scratchpad tab appear automatically — confirm that's intentional (a migration/prompt might be expected instead).
  • chatMinWidth shrank (--chat-min 380px → 320px in client/index.css) — worth eyeballing at 320px that the composer/turn content doesn't feel cramped.
  • Imperative panel sync (chatPanelRef.current.resize()/collapse() in useLayoutEffect) is a common source of resize-loop or flicker bugs with react-resizable-panels — worth confirming behavior when dockedChatWidth from storage exceeds the live chatMaxWidth/workspaceMinWidth constraints on a resized window.
  • Test coverage: WorkspaceSplitLayout.test.tsx is new, but I didn't see tests specifically for the ChatPopup outside-press fix or for the split→fullscreen responsive fallback transition — worth double-checking manually if not covered.
  • SidebarLayout.tsx dropped the panel prop ('default' | 'flat') entirely, moving the background/shadow styling elsewhere — confirm no other route still relied on panel="flat" (a grep across app/routes would catch stragglers quickly).

@molefrog

molefrog commented Aug 8, 2026

Copy link
Copy Markdown
Owner

@tonyfresher when chat is not in docked mode, would it make sense to remove the right border radius here?
image

@molefrog

molefrog commented Aug 8, 2026

Copy link
Copy Markdown
Owner

@tonyfresher when chat is not in docked mode, would it make sense to remove the right border radius here? image

wait, actually here is how I got to that point: when resizing the dock try moving it all the way to the right -> the dock gets collapsed but it doesn't automatically switch to 'undocked" mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants