diff --git a/.changeset/layout-mode-parity.md b/.changeset/layout-mode-parity.md
new file mode 100644
index 000000000..0db8295c3
--- /dev/null
+++ b/.changeset/layout-mode-parity.md
@@ -0,0 +1,5 @@
+---
+'@truefoundry/trueforge-ui': patch
+---
+
+Bring Agents, Sessions, and Schedules chrome to drawer/dock/widget, keep overlay back/close controls (including widget Close), reopen compact Agent Config after close, and stack sessions list/detail on compact and mobile widths.
diff --git a/.changeset/withrouter-default-true.md b/.changeset/withrouter-default-true.md
new file mode 100644
index 000000000..a5f8d7db3
--- /dev/null
+++ b/.changeset/withrouter-default-true.md
@@ -0,0 +1,5 @@
+---
+'@truefoundry/trueforge-ui': patch
+---
+
+Default `TrueForgeUI` `withRouter` to `true`; pass `withRouter={false}` for embeds that must not own the URL.
diff --git a/packages/trueforge-ui/README.md b/packages/trueforge-ui/README.md
index d74ca22ca..70e72ec4d 100644
--- a/packages/trueforge-ui/README.md
+++ b/packages/trueforge-ui/README.md
@@ -398,12 +398,12 @@ show the title text (see [Custom layouts](#custom-layouts)).
`agentConfig` controls library chrome, draft composer, and how New Chat / Clear Chat behave.
-| Mode | Layout chrome | Agent selection / New Chat |
-| -------------------------------------- | ------------------------------- | --------------------------------------------------------- |
-| `AgentLibraryWithComposer` _(default)_ | Agents + draft builder | New Chat opens draft; library picks a named agent |
-| `SingleAgent` | Named-only, plain composer | Locked to `name`; New Chat / Clear Chat = new thread |
-| `AgentLibrary` | Agents only (no draft) | Empty until pick; no New Chat; Clear Chat after selection |
-| `AgentComposer` | Draft builder only (no library) | Always draft; New Chat / Clear Chat = fresh draft |
+| Mode | Layout chrome | Agent selection / New Chat |
+| -------------------------------------- | ------------------------------- | ------------------------------------------------------------------------ |
+| `AgentLibraryWithComposer` _(default)_ | Agents + draft builder | New Chat opens draft; library picks a named agent |
+| `SingleAgent` | Named-only, plain composer | Locked to `name`; New Chat / Clear Chat = new thread |
+| `AgentLibrary` | Agents only (no draft) | Opens Agents Library by default; no New Chat; Clear Chat after selection |
+| `AgentComposer` | Draft builder only (no library) | Always draft; New Chat / Clear Chat = fresh draft |
In library modes, picking an agent from Agents switches to a named chat for that agent **and remounts the runtime** so the new agent starts from a clean conversation. Draft chats can be promoted via **Save agent** (`server.saveAgent` on the resolved `AgentUIServer`). **Clear Chat** (thread header) resets the current named or draft session.
@@ -446,12 +446,14 @@ Mutable composers expose **Agent Config** for live model parameters, instruction
Built-in `layout` values:
-| Value | Description |
-| --------- | ---------------------------------------------------- |
-| `sidebar` | Icon rail + recent session history + active thread |
-| `drawer` | Full-bleed thread; sessions open in a slide-over |
-| `dock` | Fixed-width right panel; list XOR thread stack |
-| `widget` | Same stack as `dock`, opened from a bottom-right FAB |
+| Value | Description |
+| --------- | -------------------------------------------------------------------------------------------------- |
+| `sidebar` | Icon rail (New Chat / Build Agent / Agents / Sessions / Schedules) + recent chats + active thread |
+| `drawer` | Full-bleed thread; Recents top tab opens Chat History on the right; overlays replace the main pane |
+| `dock` | Fixed-width right panel; thread stack with toolbar nav and overlay back navigation |
+| `widget` | Same stack as `dock`, opened from a bottom-right FAB; Close stays available on overlays |
+
+In every layout, Agents / Sessions / Schedules entry points appear when the host `agentConfig` mode and server ports enable them. Compact and mobile sessions use list → detail stack navigation; desktop sidebar/drawer keep the resizable split.
---
diff --git a/packages/trueforge-ui/docs/customization.md b/packages/trueforge-ui/docs/customization.md
index 2bfba623f..1e9fd7dbc 100644
--- a/packages/trueforge-ui/docs/customization.md
+++ b/packages/trueforge-ui/docs/customization.md
@@ -84,13 +84,16 @@ Public override surface (primitives stay theme/CSS — not slots):
## URL routing (`withRouter`)
-Opt in to browser-URL sync for shell navigation. Requires `react-router-dom`
-(v6 or v7) in the host; it is an optional peer and stays out of the bundle
-unless `withRouter` is set, so dock/widget embeds and hosts that own their own
-router should leave it off (the default).
+Browser-URL sync for shell navigation is on by default. Requires `react-router-dom`
+(v6 or v7) in the host; it is an optional peer. Pass `withRouter={false}` for
+dock/widget embeds and hosts that own their own router (keeps `react-router` out
+of the bundle for that mount).
```tsx
-
+;
+{
+ /* or explicitly: withRouter={false} for embeds */
+}
```
Places mirrored to the URL:
diff --git a/packages/trueforge-ui/src/atoms/AgentsLibraryButton.tsx b/packages/trueforge-ui/src/atoms/AgentsLibraryButton.tsx
index d5349a4dd..0aeaa6eef 100644
--- a/packages/trueforge-ui/src/atoms/AgentsLibraryButton.tsx
+++ b/packages/trueforge-ui/src/atoms/AgentsLibraryButton.tsx
@@ -11,10 +11,13 @@ import { SEARCH_AGENTS_PAGE_SIZE } from './lib/useSearchAgentsList.js';
export type AgentsLibraryButtonProps = {
className?: string;
+ /** Sidebar rail: icon + label stacked. */
compact?: boolean;
+ /** Header/footer chrome: icon-only control. */
+ toolbar?: boolean;
};
-export function AgentsLibraryButton({ className, compact = false }: AgentsLibraryButtonProps) {
+export function AgentsLibraryButton({ className, compact = false, toolbar = false }: AgentsLibraryButtonProps) {
const server = useOptionalServer();
const shell = useOptionalShellMode();
const [countLabel, setCountLabel] = useState(null);
@@ -22,10 +25,11 @@ export function AgentsLibraryButton({ className, compact = false }: AgentsLibrar
const enabled = shell?.isLibraryEnabled === true && server != null;
const libraryOpen = shell?.libraryOpen === true;
const agentsListEpoch = shell?.agentsListEpoch ?? 0;
+ const skipCount = compact || toolbar;
useEffect(() => {
- // Compact rail has no count badge; skip the catalog request.
- if (!enabled || !server || compact) return;
+ // Rail / toolbar have no count badge; skip the catalog request.
+ if (!enabled || !server || skipCount) return;
let cancelled = false;
void server
.searchAgents({ limit: SEARCH_AGENTS_PAGE_SIZE })
@@ -38,10 +42,33 @@ export function AgentsLibraryButton({ className, compact = false }: AgentsLibrar
return () => {
cancelled = true;
};
- }, [enabled, server, agentsListEpoch, compact]);
+ }, [enabled, server, agentsListEpoch, skipCount]);
if (!enabled) return null;
+ if (toolbar) {
+ return (
+
+ );
+ }
+
return (
>
)}
- {/* Stable mount: only ShellActions needs to survive Settings / list / thread; host end chrome stays in the thread header. */}
+ {/* Stable mount: ShellActions + nav survive Settings / list / thread; widget close stays visible on overlays. */}
{shell?.agentConfigOpen ? (