Skip to content
RunsComputer viewMenu

Computer view

A live view of the agent's screen: a cursor that glides to each action, a label for what it is doing, take over and hand back, and a replay scrubber with a timeline and step thumbnails.

A browser agent signs in to a preview deploy, stops for the password, opens billing and downloads an invoice. Replay it afterwards.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/computer-view.json

Usage

tsx
import { ComputerView } from "@/components/ui/chatcn/computer-view"

<ComputerView
  status="live"
  frames={[
    {
      id: "f1",
      url: "preview-482.palletapp.dev/login",
      screen: <img src={screenshotUrl} alt="" className="size-full object-cover" />,
      action: { kind: "click", label: "Click Sign in", x: 0.5, y: 0.56 },
      at: 4200,
    },
  ]}
  onTakeOver={() => takeOver()}
  onHandBack={() => handBack()}
/>

Each frame is a picture of the screen plus the action taken on it. x and y run from 0 to 1 from the top left, so they survive any size. Pass a live <iframe> as children to replace the picture and keep the cursor, labels and timeline.

Examples

Every state

Connecting, live, waiting for you, you in control, disconnected and replay.

Scripted screens

The demos draw their screens in plain HTML sized in cqw units. The screen box is a size container, so the same node renders at full size and as a 112 px thumbnail.

The placeholder screens behind the demos: plain HTML sized in cqw, so one screen renders at full size and as a thumbnail.

States

StatusShows
connectingSpinner and Connecting to the browser, no frames yet
liveA static Live dot, the cursor and Take over. Back to live when you scrub back
pausedA dimmed screen with the reason and Take over
userAn inset ink ring, You are in control, and Hand back. The agent cursor hides
endedReplay, with play, step and the timeline
errorLost the connection, how to fix it, and Reconnect

Props

PropTypeNotes
framesComputerFrame[]{ id, url?, screen, thumbnail?, action?, at? }
statusComputerViewStatusOne of the six states above
pausedReasonReactNodeWhy the agent waits, shown in paused
errorTextReactNodeShown in error. Say how to fix it
onTakeOver, onHandBack, onReconnect() => voidEach shows its button
index, defaultIndex, onIndexChangenumberControlled or uncontrolled playhead
frameDurationMsnumberHow long replay holds a frame. Default 1400
showScrubber, showThumbnailsbooleanDefault true
aspectRationumberDefault 16 / 10
childrenReactNodeReplaces the screen, for a live iframe

The playhead logic lives in useChatcnRunReplay (installed with the component), so you can drive your own replay UI with the same rules: follow new frames while live, stop following when the user scrubs back.

Keyboard

KeyAction
ArrowLeft, ArrowRight on the timelinePrevious or next step
Home, EndFirst or last step
PageUp, PageDownFive steps
Space, K on the timelinePlay or pause the replay
TabAddress bar actions, controls, timeline, then thumbnails

Accessibility

  • The timeline is a slider whose value text reads Step 4 of 12: Click Sign in.
  • The status next to the address is a polite live region, so Waiting for you and You are in control are announced once.
  • Thumbnails are buttons named after their step and mark the current one with aria-current.
  • The cursor, label and click ring are decorative and hidden from assistive tech; the step text below the screen carries the same information.

Motion

  • The cursor glides between points with a transform over 450 ms ease-chatcn-in-out: it explains where the agent is acting, so it is slower than UI feedback.
  • The action label fades in once the cursor has nearly arrived, and a click ring expands once, 520 ms, at the moment of the click.
  • Frames crossfade over 200 ms with the previous frame kept underneath, so there is never a blank flash.
  • The playhead and fill move by transform. Dragging the timeline is 1:1 with no easing.
  • Under reduced motion the cursor jumps, the click ring is skipped and only opacity fades remain.