Skip to content

Design updates: hidden-sidebar chrome, chat-everywhere title bars, panel design pass#4932

Open
andresdjasso wants to merge 88 commits into
mainfrom
design-updates
Open

Design updates: hidden-sidebar chrome, chat-everywhere title bars, panel design pass#4932
andresdjasso wants to merge 88 commits into
mainfrom
design-updates

Conversation

@andresdjasso

@andresdjasso andresdjasso commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

What this branch does

A design-engineering pass over the workspace shell: the sidebar, chat, and resource panel now behave as one coherent surface — chat is reachable from every page, the panel is a workspace-owned tab strip, and the chrome follows a single spacing system.

Highlights

Workspace-owned tab strip (browser-tab semantics)

  • Tabs belong to the workspace, not the chat: switching chats merges that chat's artifacts additively — your open tabs never get replaced. Closing/reordering is yours alone; re-entering a chat re-opens its artifacts.
  • Tabs activate in place (no repositioning on click), render at natural width (never truncated), and overflow into a +N dropdown that lists only the hidden tabs. Selecting from +N promotes the tab into the visible row.
  • The close × overlays the label on hover with a gradient fade — idle tabs reserve no width for it.
  • Agent-driven focus: when the agent touches a resource ("switch to Telecom_Leads_CRM"), the panel follows the conversation — including resources already open as tabs.

Chat everywhere

  • The sidebar's Chats section is gone; chat lives in every page's title bar via the switcher chip (bubble-clock icon, "Recents").
  • Opening a chat from a resource page keeps that page on screen as the focused panel tab — the chat slides in beside it instead of teleporting away.
  • The chat pane closes with × and reopens from the switcher; with chat closed, the tabs bar doubles as the title bar.
  • While a response streams, the switcher icon becomes a ThinkingLoader spinner (new emcn component) so work-in-progress reads even with messages off screen.
  • Failed orchestration turns now persist with an inline error block instead of vanishing on reload; chat titles fall back to local providers when the copilot backend rejects the title call.

Sidebar collapse

  • The toggle lives inside page title bars in both states; collapsing hides the sidebar completely (content full-bleed) and hovering the toggle opens a Claude-style floating menu under it.

Design system pass

  • One spacing grammar: 44px bars, 30px rounded-lg chrome pills at 7px edge insets, gap-1 toggle+switcher clusters pinned to identical positions across every bar (no shifting between pages/states).
  • Dropdowns aligned to the workspace-menu chrome: 6px inset, rounded-xl, 13px rows with 2px gaps, slim scrollbar pill hugging the edge.
  • Chat messages dissolve into the input with a gradient fade + slight progressive blur instead of hard-clipping.
  • Open-in-page (↗) panel actions retired — collapsing the chat is the expand; only Run/Export/Download remain.

Sync

  • Merged origin/main (136 commits, v0.7.3) into the branch.

🤖 Generated with Claude Code

andresdjasso and others added 8 commits June 8, 2026 17:03
…ar, stationary panel toggle

- Restructure the home input into a stacked card (grey tray behind the input)
  that hosts the All Chats launcher; the chat list expands inline within the tray
- Open existing chats inline with no route remount via adoptResolvedChatId
  (now exposed from useChat), with hover-prefetch and the slide-in morph
- Add a Codex-style chat title bar (title + action menu) to the open chat view
- Make the right resource-panel collapse/expand a single stationary toggle
  outside the animating panel, so it no longer moves on collapse
- Auto-hide the chat scrollbar; reveal it only while actively scrolling
- Bump the home input corner radius to 17px

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k, hover text reveal, dismiss-all

Component (apps/sim/components/emcn/components/toast/toast.tsx):
- Variants default/info/success/warning/error, each with a distinct outline
  icon (CircleAlert/TriangleAlert/CircleCheck/Info/Bell) rendered inline with
  the message in a neutral color — no badge; intent reads from icon + copy.
- Stacking modeled on Sonner/Base-UI: a collapsed pile that fans open upward
  only when the cards are hovered. One fixed-duration expo-out tween drives all
  cards so rapid arrivals move in unison (no lagging card); cards arrive
  collapsed (expand is scoped to a wrapper around the cards, not the dismiss
  control).
- Title vs subtext hierarchy: message is a medium, primary-color title; the
  optional description is lighter/smaller subtext.
- Truncated text reveals its hidden lines on hover (RevealText): only the
  previously hidden lines blur in; the card height tracks the content so the
  action button stays pinned (no clipping). Larger bottom gradient fade hints
  at more text.
- Concentric corner radius (16px = chip 8px + 8px padding); single-line cards
  use a tighter 12px so they don't read as pills.
- Dismiss-all control: a small circular chip just outside the stack's
  bottom-left, shown at 2+ toasts. Linear auto-dismiss ring that restarts on
  each new arrival, pauses on hover, click to clear all; spring 'pop' entrance.
- Bug fixes: route-scoped clearing (toasts no longer trail across navigation),
  dedup of the add/update double-fire, actionable toasts persist by default.

Source/usage:
- stores/terminal/console/store.ts: notifyBlockError now passes the block name
  as the title and the error as the description (title/subtext), plus the dedup
  window.
- app/playground/page.tsx: Toast section added to the EMCN gallery.
- New EMCN icons: circle-alert, circle-check, info, triangle-alert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…llery tooling

- New MessageCircle glyph in the emcn house style (24px viewBox, 1.55 stroke),
  filling a lucide-only gap from the audit; now used for the chat surfaces
- Icon design worklist + lucide->emcn migration map docs for the redesign pass
- render-icon-gallery script + generated gallery for side-by-side review

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…page wiring

- Activity view components (agent identity, parallel agents, shimmer status)
  with model + tests, plus a standalone /activity-preview render harness
- Chat resource persistence/types extended through the copilot contract,
  post handler, and resource tool handlers
- Embedded pages (Tables, Knowledge, Integrations) accept open-callbacks so
  the chat resource panel can navigate within tabs instead of routing away
- Chat history list extracted into a shared searchable, recency-bucketed
  component used by the All Chats tray and the title-bar switcher

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…anel design pass

Sidebar / chrome:
- Remove the sidebar's Chats section and the collapsed icon rail entirely;
  collapsing now hides the menu to zero width and the content goes full-bleed
- Single SidebarToggle lives at the top-left of page title bars (both states);
  hovering it while collapsed opens the menu as a popover-styled, content-fit
  flyout anchored below the bar; clicking pins the sidebar open
- Flyout pins open while popups launched from it (workspace menu) are showing
- "New chat" nav item swaps the house icon for the new MessageCircle

Chat view:
- ChatTitleBar always renders (incl. new-chat view) with a "Chats / {title}"
  breadcrumb switcher; close (x) hides the chat pane while the resource panel
  takes full width and the switcher moves inline into the tabs bar
- ChatSwitcher promoted to a workspace-level control rendered on every page
  header (Tables/Files/Knowledge/Scheduled/Logs via ResourceHeader) and
  floating on the workflow canvas, so chats are reachable from anywhere
- Guardrails: chat pane restores when the resource panel closes; embedded
  pages suppress duplicate chrome via SidebarToggleHidden context

Design pass:
- Resource tabs become ghost chips (30px, rounded-lg, active surface) in a
  44px bar matching the chat title bar; icon buttons unified at 30px with
  surface-active hover; 7px equal-distance edge insets for all pill controls
- Chat dropdown matches the flyout anchor rhythm (6px below bar, 8px inset);
  emcn PopoverContent gains an alignOffset passthrough

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Fixed 44px bar (was padding-derived) with a unified 16px gutter across the
  breadcrumb and title-only variants
- Sidebar toggle and right-edge actions pull out 9px so their hover pills sit
  7px from the panel edge, equal to the pill's vertical clearance
- Action/create buttons standardized to the 30px rounded-lg pill with
  surface-active hover, matching every other title-bar control

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rumb group

The sidebar toggle's 9px pull-out was clipped by the breadcrumb container's
overflow-hidden; the toggle and chat switcher now sit beside it instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 13, 2026 4:07am

Request Review

andresdjasso and others added 20 commits June 10, 2026 00:27
…pty state

The home page's title chip fell back to the most recently updated chat; that
fallback is now scoped to non-chat pages via an isNewChat flag the title bar
sets whenever no chat is open.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Orchestration failures previously persisted nothing for the assistant turn —
the post-stream history refetch then silently erased the streamed activity,
leaving the user staring at their own message with no explanation.

- withErrorContentBlock mirrors the cancelled-turn pattern: keeps partial
  content/tool blocks and appends an inline <mothership-error> tag (already
  understood by the message renderer) plus a terminal error-status block
- Both failure paths persist: orchestration-returned failures keep their
  partial work; thrown errors persist a minimal errored turn

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, never replace

Switching chats no longer swaps the resource panel's tab set. Tabs now behave
like browser tabs, owned by the user per workspace; chats relate to artifacts
by provenance, not containment:

- New persisted mothership-tabs store (tabs + active per workspace); entering
  a chat merges its artifacts additively (deduped) and focuses its last-touched
  one, never closing what's already open
- Tabs the active chat surfaced carry a provenance dot (hidden on hover/active)
- Closing/reordering tabs is session-only and no longer mutates the chat's
  persisted resources; closed tabs stay closed for the rest of the chat visit
  and re-open on re-entry
- Manual attaches (+ dropdown, context chips) still record provenance on the
  open chat via the existing persistence path
- Ephemeral resources (streaming previews) stay chat-scoped and unpersisted;
  panel expand/collapse + chat-pane guardrails now key off the strip

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… scroll the strip

Horizontal trackpad swipes carry a small deltaY, so the deltaY-only handler
preventDefault()'d the native pan and scrolled by the jitter amount instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mpressed tabs, switcher dropdown

The panel bar now mirrors the chat pane: one prominent identity chip per pane.

- Active resource renders as a title chip (icon + full name + chevron) whose
  dropdown lists every open tab, grouped "From this chat" / "Other open tabs"
  with hover close controls — provenance moved here from the per-tab dots
- Inactive tabs compress browser-style (max-width truncation, icon always
  visible); beyond five they collapse into a +N chip instead of scroll-clipping;
  the strip's scroll/edge-scroll machinery is gone
- Dots now mean "changed while unfocused": a chat's artifacts merge in marked
  unseen except the focused one, and viewing or closing a tab clears it
- Standalone pages (ResourceHeader, workflow canvas) demote the chat switcher
  to an icon-only chip so the page title owns the bar

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y for the true remainder

Replaces the fixed five-tab cap with measured capacity: the strip and the
name-dependent title chip are observed (ResizeObserver, with a window-resize
fallback), and whole tab slots are fitted into the remaining width. Zero-width
measurements (panel collapsed or mid-expand-animation) are ignored so a bogus
early measure can't collapse everything into the dropdown, and capacity starts
permissive until the first trustworthy layout pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…down, +N lists only hidden tabs

The all-tabs switcher dropdown duplicated the strip and made +N feel like a
third concept. Now every tab lives in exactly one place: the active resource
is a plain title chip, visible tabs switch by clicking, and the +N chip is the
only dropdown, listing just the tabs that didn't fit. Selecting one promotes
it to active, so it leaves the overflow naturally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…asured width, overflow the rest

Replaces the fixed 84px slot estimate (which squeezed labels even with room to
spare) with real per-tab measurement: a hidden measuring row renders every
inactive tab at natural width, and the capacity pass greedily fits whole tabs
into the strip, sending only the true remainder to +N. Inline labels keep a
240px ceiling purely as a pathological-name guard, mirrored in measurement so
render and fitting agree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lumbing

Removes the unfocused-change indicator from inline tabs and switcher rows,
along with the updatedTabKeys state, marking, and clearing in home. Also
escapes a literal NUL byte that had crept into the namesKey join separator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…between bars

The pair rendered as loose children of each bar, inheriting whichever gap that
bar used (gap-1 in the chat title bar, gap-1.5 in the tab strip, gap-2 in the
resource header) — so the switcher drifted a couple of pixels when the chat
pane closed or across pages. It now lives in its own gap-1 cluster everywhere,
keeping the toggle at 7px and the switcher at 41px in every state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ons the strip

Drops the spotlight-first layout (clicking a tab yanked it to the left edge).
Tabs now render in strip order with the active one highlighted where it sits.
The width fit runs over the ordered list; if the active tab lands beyond the
fit (e.g. picked from the +N dropdown), it surfaces at the end of the visible
row with its width reserved, since it has no inline position to keep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…'s chrome

Container now keeps the popover's canonical 6px inset and rounded-xl instead
of a p-0 override with its own 8px padding; rows drop to the canonical 13px
text with the 2px row gap; the forced 240px min-width goes down to 180 so the
dropdown hugs its content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…used panel tab

Selecting a chat from a resource page used to teleport to the chat view with
whatever the strip last held — the one thing missing was the page you were on.
The switcher now derives the page's resource from the pathname (page tabs for
tables/knowledge/logs/scheduled-tasks, item tabs for table/KB/workflow detail
routes), opens it focused in the workspace strip, and navigates with
?resource= pinned. The chat-entry merge respects that pin: a URL-pinned
resource that isn't one of the chat's artifacts keeps focus instead of being
displaced by the chat's most recent artifact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…no reserved tab width

Tabs carried a permanent 20px right padding for the hover ×, leaving dead
space on idle tabs. The × now overlays the label's tail on hover, sitting on
a gradient fade of the hover fill so it stays readable; idle tabs keep the
chip's symmetric padding and their width never changes on hover. The hidden
measuring row drops the same padding so fitting stays in sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rive the panel again

Asking the agent to "switch to Telecom_Leads_CRM" answered in prose but never
moved the panel. use-chat still carried the old focus-on-touch logic via its
internal setActiveResourceId, but the workspace tab-store migration orphaned
that state — nothing rendered it. Adds an onResourceTouched(resource) callback
fired at the three touch sites (stream resource ops, successful Read tool
calls, workflow activation), regardless of whether the resource was already an
artifact; home bridges it to the tab store with openTabs + focus, so the panel
follows the conversation. File-streaming suppression is respected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…clipping

Wraps the message scroller in a relative container and overlays a 40px
bottom strip — a bg gradient plus the faintest backdrop blur, both masked to
ramp in toward the edge — so scrolled content dissolves above the input
rather than cutting off at the scroller boundary. Applies to both chat
layouts; pointer-events pass through.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the icon system with self-hosted Hugeicons (free, stroke-rounded)
vendored into @/components/emcn/icons — zero runtime icon deps.

- Vendor 150+ icons from @hugeicons/core-free-icons into the emcn barrel via
  scripts/hugeicons-map.ts + scripts/hugeicons-generate.ts (dev-only source).
  Icons gain a `size` prop; 4 bespoke animated icons (Loader, RefreshCw,
  Download, Layout) kept custom.
- Migrate ~172 consumers off lucide-react to the emcn barrel; remove
  lucide-react dependency entirely (Github brand logo -> @/components/icons).
- Fix chevron sizing: replace ~24 non-square classes (h-[6px] w-[10px], tuned
  to the dead 10x6 viewBox) with canonical size-[14px].
- Sidebar/chat icon updates: Table->TableIcon, knowledge base->DatabaseIcon,
  Files nav->File, scheduled tasks->CalendarClock, Logs->ThirdBracketSquare,
  PanelLeft/PanelRight, BubbleChatDelay/Spark for the two chat bubbles.
- Send buttons -> ArrowUp02; integration row arrows -> ArrowRight02.
- Workflow icon -> WorkflowSquare04; Integrations -> Plug02.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…et thumb

The list scroller sat inside the panel's 8px gutter, so the full-width global
scrollbar floated mid-panel and read as a fat dead column. The scroller now
bleeds to the dropdown edge (-mx-2/px-2, the workspace dropdown's pattern) so
the scrollbar occupies the former padding, and the thumb is clipped to a 4px
pill inset 2px from the edge (transparent border + content-box clip), with
scrollbar-width:thin for Firefox. Row alignment is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the icon system with self-hosted Hugeicons (free, stroke-rounded)
vendored into @/components/emcn/icons — zero runtime icon deps.

- Vendor 150+ icons from @hugeicons/core-free-icons into the emcn barrel via
  scripts/hugeicons-map.ts + scripts/hugeicons-generate.ts (dev-only source).
  Icons gain a `size` prop; 4 bespoke animated icons (Loader, RefreshCw,
  Download, Layout) kept custom.
- Migrate ~172 consumers off lucide-react to the emcn barrel; remove
  lucide-react dependency entirely (Github brand logo -> @/components/icons).
- Fix chevron sizing: replace ~24 non-square classes (h-[6px] w-[10px], tuned
  to the dead 10x6 viewBox) with canonical size-[14px].
- Sidebar/chat icon updates: Table->TableIcon, knowledge base->DatabaseIcon,
  Files nav->File, scheduled tasks->CalendarClock, Logs->ThirdBracketSquare,
  PanelLeft/PanelRight, BubbleChatDelay/Spark for the two chat bubbles.
- Send buttons -> ArrowUp02; integration row arrows -> ArrowRight02.
- Workflow icon -> WorkflowSquare08; Integrations -> Plug02.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
andresdjasso and others added 23 commits June 12, 2026 12:58
Staging a workspace page (Tables, Knowledge Base, Logs, Scheduled Tasks)
or a knowledge base in the chat's resource panel showed two stacked
headers: the panel's title bar plus the page's own Resource.Header. Now
views that bring their own header keep it as the single header — the
panel skips its bar and injects its chrome instead:

- PanelChromeProvider/usePanelChrome: the panel provides its leading
  cluster and trailing controls; Resource.Header absorbs them, compacts
  to the 44px panel rhythm, and swaps its standalone chrome cluster for
  the panel's (SidebarToggleRevealed escapes the content's hidden scope
  while the chat pane is collapsed)
- PanelTrailingControls extracted (close + collapse-toggle spacer),
  shared by PanelHeader and the injected page headers
- PanelHeader title restyled to Resource.Header's treatment (chip
  geometry, 14px icon, body text) so every staged view reads identically

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…are nav

files.tsx gets the navigation abstraction Tables/Knowledge already had:
an `embedded` prop routes folder browsing through component state instead
of `?folderId=`, and opening a file is delegated to the host via
`onOpenFile` instead of pushing the detail route. Standalone-only flows
(`?new=1`, `/files/[fileId]`, the hidden-tab redirect) are gated off and
unreachable embedded; downloads keep their direct URLs.

- `files` registered in MOTHERSHIP_PAGES + page icon + EmbeddedPage case
  (opening a file stages it as a panel file resource)
- the sidebar Files item becomes chat-aware like the other pages, and the
  chat switcher maps the file detail route to a file resource when
  opening a chat from it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opening the resource panel with nothing staged showed a blank pane. It
is now a quick-open surface: a search across every stageable workspace
resource (pages, workflows, tables, files, knowledge bases), the
resources most recently on stage, and the workspace area pages as
browse entries. Selecting anything stages it in place.

- the stage store tracks per-workspace recents (newest first, deduped,
  capped at 8, persisted) alongside the staged resource
- enter animation staggers the list 75ms behind the search via
  animation-fill-mode: both, so content stays visible when animations
  never run (reduced motion, hidden tabs)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the brand logotype (the "Sim" word, new SimLogotype icon drawn in
currentColor so themes drive the color) centered above the empty
state's search in --text-subtle — a soft grey brand moment in both
modes. Decorative only: aria-hidden, sized via height + w-auto.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
--text-subtle read too heavy for a decorative mark; half opacity tracks
both themes toward the brand asset's original #EAEAEA feel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
py-[7px] derived the height from content, and a 31px action chip pushed
the row to 45px — leaving the header divider 1px below the chat title
bar's across the split. A fixed h-[44px] (matching the chat bar and
PanelHeader) keeps every staged view's header height, divider, and
vertically centered controls identical regardless of content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The chat/panel split width was a transient inline style, so switching
chats (route remount), staging a different view, collapsing, or
reloading snapped the chat back to the default split. A small persisted
store (mothership-panel) now keeps the user's widths:

- the resource panel saves its width on drag end and re-applies it
  (viewport-clamped) whenever it's visible beside the chat pane
- the workflow route's docked chat pane does the same with its own
  stored width, so the chat reads as one consistent size everywhere
- clamping happens at apply time, never at save, so a narrow window
  doesn't permanently shrink the remembered width

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opening a document from an embedded knowledge base routed to the full
/knowledge/[id]/[documentId] page, closing the chat beside it. The KB
detail now follows the established embed pattern:

- KnowledgeBase gets `embedded`: document clicks (row + View Tags) swap
  to the Document view inside the panel via component state
- Document gets delegated back-navigation (onNavigateToKnowledgeBase /
  onNavigateToRoot): the breadcrumb walk and post-delete landing return
  within the panel — root lands on the staged Knowledge Base page
- standalone routes are untouched (no props -> same router paths)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Embedded mode degraded the canvas to a read-only preview: no dragging,
connecting, or selecting, no block action bars, no editor Panel, no
Deploy. `embedded` now means panel-hosted, not reduced:

- full interactivity, gated by permissions only (drag, connect, select,
  edge editing, block menus, undo/redo controls, search/replace, diff
  controls, OAuth modals)
- the editor Panel (Toolbar/Editor tabs, Deploy, Run) always renders;
  the panel header's duplicate Run action retires with it
- the auto-fit machinery runs only until the first successful fit (the
  panel may still be width-animating open) — after that the user owns
  the viewport like any editor

What embedded still does: props-based identity, collab join/leave, and
skipping the route-level redirect/title chrome the panel header covers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The header's ✕ cleared the stage and the panel auto-collapsed with it.
Now clearing the stage keeps the panel open on the empty state (search,
recents, browse) — only the collapse toggle closes the panel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The chat's effective floor was much larger than intended: on the chat
surface the panel was capped at 65% of the viewport (a 1680px window
left the chat stuck at ~588px) plus a 320px flex floor, and the
workflow route's docked chat stopped at 360px.

- the panel's max is now viewport minus a fixed 280px chat floor
  (MOTHERSHIP_WIDTH.CHAT_MIN replaces MAX_PERCENTAGE), so the chat can
  reach the same minimum on any screen size
- the home chat pane's flex floor drops 320px -> 280px to match
- the docked chat's drag minimum and default clamp drop 360px -> 280px

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The open-chat title bar still rendered the pre-split chip (no divider),
so the control changed design the moment a chat opened. It now renders
the same split pill as the icon-only and closed-chat states — both
segments open Recents there; the split is the family look.

Also pulls the chevron closer to the text across all three variants
(title segment pr-1.5 -> pr-1, chevron segment px-1.5 -> px-1), so the
chevron reads as part of the chip instead of floating beside it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canCloseChat required a staged resource, so the quick-open empty state
— now a legitimate panel view — left the chat unclosable, and the
restore effect would have snapped it right back. Now:

- the chat can hide whenever the panel is visible (staged content or
  empty state alike)
- the chat only force-restores when the panel collapses, so the view
  never blanks
- with the chat hidden, the empty state gains the slim 44px chrome bar
  (sidebar toggle + chat switcher + toggle spacer) so the way back to
  the conversation stays reachable

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The only cap was 30% of the viewport, so on wide monitors the sidebar
could drag out to 750px+, crushing the chat and resource panel. The
clamp is now min(400px, 30% of viewport) — applied in the store clamp
(persisted values self-heal on load) and the live drag handler.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Standalone pages' Resource.Header derived its height from padding
(py-[8.5px] -> 48px with the border), so the sidebar toggle and chat
switcher sat 2px lower than on chat surfaces (44px bars) and the
divider line moved — switching pages made the corner icons visibly
jump. The header is now a fixed h-[44px] in both standalone and panel
modes, matching the chat title bar and the workflow canvas cluster.

Also evens out the icon-only chat-switcher segment (pl-2 pr-1 -> px-2):
the recents icon was 2px off-center in its half of the split pill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The workflow page was the last holdout: its title and chrome floated
over the canvas (with a gradient fade) while the editor Panel and
Deploy/Run pinned to the very top — so the same workflow read
differently standalone vs staged in the chat panel (which has a real
header bar). The route now renders the canonical 44px bordered header
(sidebar toggle + chat switcher + workflow name) with the canvas and
editor Panel below it, exactly matching the staged structure and every
other main view. The floating cluster and canvas top-fade retire.

With a chat docked, the cluster hides (the chat pane's bar carries it)
and the two 44px bars align across the divider.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Non-chat pages rendered a compact icon-only chip while chat surfaces
showed the titled split, so the control kept changing shape between
pages. The iconOnly prop is gone: every surface now renders the titled
split pill — icon + the most recent chat's name (capped at 200px)
opens that chat outright, the chevron opens Recents. Variant selection
is derived (onOpenChat -> reopen split; chatId/isNewChat -> recents
split; otherwise the most-recent split).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The panel's close button lived inside whichever header the staged view
happened to render, so headerless states (loading skeletons, not-found
views, anything that skips its Resource.Header) silently dropped it —
leaving no way to close, and only the overlay toggle to collapse.

Both controls are now a single host-owned overlay cluster pinned to the
panel's top-right (the pattern the collapse toggle already used):

- home renders [close][toggle] absolutely; close shows whenever a
  resource is staged and the panel is open, regardless of what the
  content renders
- PanelTrailingControls becomes pure footprint spacers (close + toggle)
  for header rows; PanelCloseButton is the extracted real control
- the empty state keeps toggle-only (nothing staged, nothing to close)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Logs page header (and the log not-found view) still drew the old
Library glyph while the sidebar, resource registry, and panel rows had
moved to the Logs icon. Aliased as LogsIcon (the page components own
the bare name).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The panel transitioned border-width along with width, so hiding the
chat pane (panel border-l -> border-l-0 + snap to full width) animated
the 1px border away over 200ms — a ghost line flashing at the main
content's left edge. Border toggles are instant now; only width and
min-width animate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The panel's close X inherited the 16px header-icon class while the
chat pane's close runs 14px — the size that reads right, since the X
glyph is optically larger than other glyphs at equal box size. Close
glyphs are now 14px on both sides; non-X header icons (sidebar toggle,
panel toggle, preview mode) stay at the canonical 16px.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mmit

The persisted split-width store (stores/mothership-panel) never made it
into "the split remembers" — the branch referenced a module that only
existed in the working tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The empty-state logotype's sheen sweep referenced animate-logo-shimmer,
which had no keyframe in the Tailwind config — the band parked
off-canvas and never moved. Adds the sweep (1.4s ease-in-out after a
400ms settle, forwards so it parks off the right edge), in SVG user
units (2x the 796 viewBox width).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/sim/app/workspace/[workspaceId]/files/files.tsx
andresdjasso and others added 3 commits June 12, 2026 23:07
Replaces the flat currentColor fill on the chat ThinkingLoader with a
radial gradient (center → edge) plus a soft white inner-shadow glow,
per the Figma loader spec — theme-aware:

- light: #A7A7A7 → #D6D6D6, white inner glow at 0.9
- dark:  #4F4F4F → #6F6F6F, white inner glow at 0.6

One set of SVG defs serves both themes: the gradient stops and the
feFlood glow read CSS custom properties (--tl-grad-inner/-outer,
--tl-glow) set per theme on .frame / :global(.dark) .frame. The goo
filter now runs in sRGB so the gradient keeps its midtones through the
blur, and the inner glow rides the merged silhouette's edge (the Figma
inner-shadow technique, stdDeviation scaled 72→100 viewBox).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two fixes against the Figma loader frames (simMothershipLoader_lightTheme
82:122 / _darkTheme 82:119):

- Theme mapping was inverted. Light mode must show the DARK-grey loader
  (#4F4F4F→#6F6F6F, glow 0.6) so it reads on white; dark mode shows the
  LIGHT-grey loader (#A7A7A7→#D6D6D6, glow 0.9). The squeeze ring's
  currentColor stroke already tracked that polarity, so only the gradient
  vars swapped.
- Gradient is now objectBoundingBox (per shape) instead of one canvas-wide
  radial. Figma fits the radial to each shape's box, so every blob —
  including small/offset dots — reads glossy (center dark → edge light)
  rather than flat.

Verified computed values live in both themes and rendered against the
Figma frames.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The orbit pattern's two blobs are meant to chase each other around a
square track (the second offset by a half-loop). It used
`animation-delay: -1s` for the offset, but the shared wall-clock phase
lock (`.frame.frame *` sets animation-delay on every element) is
higher-specificity and clobbered it — so both blobs ran in lockstep,
stacked exactly, and one disappeared.

The second blob now gets its own 50%-shifted keyframes (orbit-b,
opposite corner) instead of a delay — the same technique metaballs uses
— so the phase lock no longer hides it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4eadb18. Configure here.

router.push(`/workspace/${workspaceId}/chat/${selectedChatId}?resource=${pageResource.id}`)
return
}
router.push(`/workspace/${workspaceId}/chat/${selectedChatId}`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chat switch leaves stale panel

High Severity

Switching chats from an open chat only updates the URL when derivePageResource returns null (chat routes). The workspace stage store is not reset or rebound to the new chat, so the panel can keep showing the previous chat’s staged artifact while messages belong to another conversation.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4eadb18. Configure here.

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.

1 participant