Skip to content

feat(agent): split-screen agent workspace (conversation left, content panel right) - #6432

Open
tsahimatsliah wants to merge 16 commits into
feat/interest-agent-mockupfrom
claude/interest-agent-pr-a6c00e
Open

feat(agent): split-screen agent workspace (conversation left, content panel right)#6432
tsahimatsliah wants to merge 16 commits into
feat/interest-agent-mockupfrom
claude/interest-agent-pr-a6c00e

Conversation

@tsahimatsliah

@tsahimatsliah tsahimatsliah commented Aug 5, 2026

Copy link
Copy Markdown
Member

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=1 renders 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.tsx drives 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 100dvh offsets differ between the v1 global header and the v2 floating card, and that is the one thing Storybook cannot prove.

  • Have you done sanity checks in the webapp?
  • MobileL (420px)
  • Laptop (1020px)

Events

No new tracking events.

Experiment

No new experiments. The existing featureInterestAgent flag 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

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.
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Aug 5, 2026 5:58pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Aug 5, 2026 5:58pm

Request Review

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>
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