feat(agent): split-screen agent workspace (conversation left, content panel right) - #6432
Open
tsahimatsliah wants to merge 16 commits into
Open
feat(agent): split-screen agent workspace (conversation left, content panel right)#6432tsahimatsliah wants to merge 16 commits into
tsahimatsliah wants to merge 16 commits into
Conversation
The page was a scrolling document with a floating toolbar overlay. Rebuild it as a fixed two-column app shell: conversation on the left, an openable content panel on the right. Left column owns its own header (back, agent identity, status, panel launchers, pause, settings), an internally-scrolling transcript, and a compact docked composer — auto-growing textarea, icon-only quick actions, Enter to send. Right panel behaves like Claude's: it accumulates tabs as you open things (post, feed, activity, debug), each tab focusable and closable, resizable by its left edge, and it covers the column as a full overlay below laptop. Activity and Debug moved out of the left column's tab bar and into that panel, so the conversation stays a pure transcript. Drops the hero card, the header title morph, and the pane/modal view toggle with it: the split shell replaces all three.
`?demo=1` is the design surface for this mock-up; real data lands later once the backend exists. Split the page so the demo route renders purely from the mock fixtures — no interest/posts/findings queries, no feature gate, no auth wall — which makes the preview link reviewable by anyone without the flag or an account. The live route keeps its queries, flag redirect and ProtectedPage untouched.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Design review pass over the split workspace. Header: one 24px optical band, every control the same XSmall tertiary button with a 16px glyph on tertiary ink. The agent's identity tile is now its power switch — a status dot on the tile, a popover with an on/off toggle, cadence, last run, and jumps to activity and settings. That replaces the "Hunting" chip, whose tinted background read as loud and whose wording never said what the agent was doing. Panel buttons show open state by colour rather than a filled background, and back uses MoveTo. Transcript: the shared markdown styles are tuned for reading an article (17px on 1.7 leading, 24px paragraph gaps). Scoped overrides step the chat down to 15px on a 1.6 leading with 12px gaps. Agent turns lose their avatar, name and per-message date — the right-aligned user bubbles already separate the voices, so only a scheduled run keeps a marker. Posts in the transcript get a compact card instead of the full feed card, and the pick-list rows tighten to match. Composer: quick actions moved out of the box and below it as labelled subtle chips, the keyboard-hint line is gone, a gradient fades the transcript out behind the bar, and the send button becomes a stop square while a run is in flight. Adds transcript block primitives — embed row/card, code with copy and run, and table — plus an AgentBlocks Storybook page covering every variant.
… tabs The toggle wrote through `update()`, which returns early on the demo surface and whenever there is no interest loaded — so switching the agent off changed nothing you could see. Run state now lives in the context, seeded from the interest and owned locally after that, so the control responds everywhere. Switching off also interrupts a run in flight; leaving one going would contradict the switch that was just used. Pane tabs were a row of near-identical pills. They are now a full-height strip: the active tab takes a surface fill, a brand underline and a brand icon, inactive tabs sit quiet behind dividers and reveal their close button on hover.
MainLayout holds its paint until boot resolves, so the mock-only demo page was blank on any environment without a reachable API — including a local dev server. Fall back to a standalone shell when boot errors out, and let the workspace own the viewport there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`/agent/[id]?demo=1` renders mock data but still sits inside the app shell, and BootDataProvider replaces the whole tree when boot fails — so the demo is blank on any dev server without an API behind it. `_app` already short-circuits `/dev/*` past the shell, so put the workspace there with a static provider stack that Storybook now shares. Also stops a post view from surfacing as an unhandled rejection when the request fails. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…the tabs - Chat column and composer go from 12/16px side padding to 20/32/40px, so the transcript stops hugging the frame when the panel takes half the width. - Header controls move from 24px buttons on a 16px glyph to 32px on 20px, the run tile with them, so the row reads at arm's length. - Panel tabs return to floating chips. The active one carries a brand fill rather than being the only filled one, which is what made three open tabs look alike. - Panel gains a close button; it replaces the mobile-only back arrow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The panel was on an ad-hoc 20px that matched neither the conversation nor the post page. It now carries the post page's own ramp (16/24/32), so an article opened in the panel reads exactly as it does on its own page, and the feed, activity and debug tabs align with it. Both header rows share one inset. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Selected tab is now the only chip that is filled and outlined; the rest are bare text. Brand-float against surface-float was two 8% washes over the same background, which is why three open tabs looked alike. - Send control moves to a float button on a 20px glyph, nudged a pixel right so the airplane sits optically centred, and stays icon-only. Stop keeps the square. - New usage panel in the composer's status slot, the way Claude Code hangs one off its bar: allowances with a warning tier as they run out, and the routes out of the ceiling — Plus, or your own API key. Numbers are placeholders until the backend meters runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
32px chip, 8px radius, 16px icon, label truncating at 13rem, close revealed on hover and pinned on the selected tab. Selected sits on an opaque raised surface with a white icon; the rest are bare text on a hover fill. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…r beam A sent prompt now reads as received in three places at once: a light travels the composer's border while the run is in flight, the transcript's pending turn becomes a status strip (elapsed time and what it is doing), and the mark on that strip is daily.dev's logo animating — its three strokes hop in a wave and reassemble into the intact logo for most of every 2s loop. Also: the run-state dot on the agent tile was mostly cut-out ring at 8px, so it never registered; and a prompt sent over a pending turn left the earlier reply spinning forever, since the timer only ever resolves the newest one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first pass rotated the whole layer inside an overflow-clipped padding box, which dragged the blur around with it and needed an opaque underlay to stop the light leaking through the composer's 8% surface. Rebuilt on the technique from beam.jakubantalik.com: the ring is cut with mask-composite, and the conic gradient's angle animates rather than the element rotating, so the head sweeps the perimeter at an even rate and stays in the border whatever sits behind it. Ring and blur are tuned up from the reference's values — this bar is 15:1, which stretches the same sweep far thinner than the near-square card the original targets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Swaps my port for the published component (border-beam@1.3.0, MIT, no runtime deps) at size md / colorVariant colorful / strength 1, so the animation, the colour ramps, the hue-shift and the fade in and out are the reference's own rather than an approximation of them. The hand-rolled CSS is gone. It mounts client-side only: the package injects its stylesheet as a React `<style>` child, and SSR escapes the quotes in its selectors. `<style>` holds raw text, so those entities are never decoded and every rule silently fails to match — the beam renders as nothing at all. Also: the panel feed is list cards at every width (grid gave nine findings a cover image each), and the run-state dot comes back down a size. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…isions The parity pass over both platforms' chat experiences, landing the patterns relevant to a feed agent: - Prompts sent mid-run queue instead of interrupting: dashed removable bubbles under the transcript, drained in order as runs finish. Stop clears the queue. - Autoscroll only follows while the reader is pinned to the tail; otherwise a floating "New reply" pill appears above the composer. - Reply actions on hover: copy (blocks flattened to text) and thumbs up/down. - Failed turns render a warning row with Retry re-sending the command. - Escape stops the in-flight run; closing a panel tab yields to it. - New turns ease in (240ms rise-and-settle, reduced-motion aware). The decision record ships as Storybook pages: AgentExperienceMap (shipped / adapted / deferred / ignored, capability by capability), AgentChatStates (every message state live, including the queue draining), and AgentLogoLab — ten logo thinking-mark explorations as one-prop variants of AgentThinkingMark. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The keyframe-loop explorations are gone. The mark is now the attractor of a small particle system: dots sampled around the logo's own outline, moved every frame by a force field, with the solid mark painted faintly underneath as the shape they resolve toward. Five states on one engine — working (travelling attention beads), thinking (per-dot orbits under smooth-noise focus), searching (sweeping meridian that settles what it passes), weaving (advection along the outline) and assembling (scatter and magnetic re-formation). Nothing is periodic: positions come from travelling waves and value noise, so the logo continuously assembles rather than replaying a loop. Plain 2D canvas arcs — depth is carried by dot size and alpha alone, so there are no filters, no shadows, and it renders identically everywhere. Dot count and radius are tuned per size rather than scaled from one figure, instances share one clock and stop drawing while offscreen or on a hidden tab, and reduced motion gets a single static frame. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Storybook is not deployed anywhere, so the five states could only be compared on a local dev server. The gallery moves into shared and /dev/agent-indicator renders it, which puts the decision on every Vercel preview; the story now just mounts the same component. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #6392. Base is
feat/interest-agent-mockup, so the diff here is only the split-screen rework.Demo link: https://claude-interest-agent-pr-a6c00e.preview.app.daily.dev/agent/demo?demo=1 — no flag, no login, pure mock data.
Changes
Rebuilds
/agent/[id]from a scrolling document with a floating toolbar into a fixed two-column app shell, modelled on Claude Code's conversation + side panel.Left column — conversation only. One 48px header row (back, agent identity, live status, panel launchers, pause, settings), an internally-scrolling transcript, and a compact composer docked at the bottom of the column instead of floating over the page. The composer is a single auto-growing textarea with Enter to send, Shift+Enter for a newline, and one dense control row: the three quick actions as icon-only buttons with tooltips, and send. The "working" state is a thin pulsing status line above the box rather than its own bar.
Right panel — Claude's tab behaviour. Opening a post or a feed link opens it as a tab; opening another adds a tab rather than replacing. Tabs focus on click, close on their own ✕, and closing the active one falls through to its neighbour. The panel resizes by its left edge (persisted via
usePersistentContext), Esc closes the active tab, and below laptop it covers the column as a full overlay with a back arrow.Activity and Debug are panels, not tabs. They open in the right panel from the header buttons, the same way you'd open a terminal alongside a conversation. That is what let the Chat/Activity/Debug tab bar disappear and the left column stay a pure transcript.
Demo route is self-contained.
?demo=1renders purely from the mock fixtures: no interest/posts/findings queries, no feature gate, no auth wall. Real data stays on the live route and is the backend team's side of the work. Anyone with the preview link can review without the flag or an account.Removed with the shell that replaced them: the hero card (its stats fold into a compact transcript intro), the scroll-morphing header title, and the pane/modal view toggle plus
AgentFeedModal.Manual Testing
The page is auth-gated and its boot needs a backend, so
packages/storybook/stories/features/interests/AgentWorkspace.stories.tsxdrives the real components against the mock fixtures. Verified there: both panel types open, a post opens into a second tab, tabs focus/close/fall through, the composer sends and the transcript auto-scrolls, mobile overlay behaviour, and light + dark themes.Worth a look on the preview in both sidebar variants — the shell's
100dvhoffsets differ between the v1 global header and the v2 floating card, and that is the one thing Storybook cannot prove.Events
No new tracking events.
Experiment
No new experiments. The existing
featureInterestAgentflag still gates the live route; the demo route is deliberately outside it.🤖 Generated with Claude Code
Preview domain
https://claude-interest-agent-pr-a6c00e.preview.app.daily.dev