DRYL COMPONENTS
Color mode: System — switch to light
2.20.1
Intelligence

DrylCanvasWorkspace

AI-aware

DrylCanvasWorkspace and DrylCanvasDock turn the canvas into an application surface: named views instead of a single sheet, and a command bar in the corner instead of a chat column.

How it works

A line-of-business page is a workspace holding named views, plus a dock in the corner. The workspace shows exactly one view at full size; the others stay one chip away in the bar. The open_view tool lets the model open a view and build into it — the previous artifact stays where it was instead of being overwritten.

Switching is a movement, not a jump. It runs through the same view-transition layer as the canvas's own fullscreen morph, and the bar carries the gliding gradient indicator DrylTabs uses. A single view gets no bar at all — one artifact needs no chrome.

The dock is a command bar, not a chat. An input plus one line of live status ("Building · 7 elements"); the full transcript unfolds on demand, and your app supplies its content through the <Log> slot. The dock lives in the browser's top layer, so it anchors to the viewport rather than to the nearest glass card.

csharp
// One workspace, one run: the run always writes into the view the user is looking at.
private readonly CanvasWorkspace _ws = new();
private readonly DrylCanvasRun _run = new();

protected override void OnInitialized() => _run.UseWorkspace(_ws);

// The workspace argument is what adds open_view to the tool set.
var tools = DrylCanvasTools.Create(_run, generatorAgent, workspace: _ws);
var agent = new ChatClientAgent(chatClient, tools: tools.All);
razor
<DrylCanvasWorkspace Workspace="_ws">
    <View><DrylAiCanvas Run="_run" AllowExpand="false" /></View>
</DrylCanvasWorkspace>

<DrylCanvasDock Run="_run" Busy="Busy" OnSend="Send" Corner="DockCorner.BottomRight">
    <Log>@* your own DrylMessages — the dock brings no second message model *@</Log>
</DrylCanvasDock>

Workspace and dock

Ask the dock below for a view — &quot;Overview&quot;, &quot;Order 4711&quot; or &quot;Returns&quot;. Every request runs through open_view: the view is opened, activated, and the artifact streams into it node by node. The previous view stays as a chip in the bar; clicking it morphs back. Fully scripted — in your app you hand DrylCanvasTools.All to a real model.

No view yet
Ask for a view below — &quot;Overview&quot;, for example.
Overview Order 4711 Returns — ask for one of these below; the previous view stays in the bar.
AI
Idle

Documents and history

A workspace that only lives in memory is a demo, not an application. A CanvasDocument serializes the whole workspace — every named view, its artifact, and which one was open — with a schema version, so a dashboard survives a reload, a user switch and a deployment. Data bindings travel with it; the numbers do not, so a restored document asks your sources for fresh values.

Persistence is your call. DRYL ships the ICanvasDocumentStore contract and an in-memory implementation and no database code at all. On WebAssembly the same interface goes over HTTP or localStorage.

Undo is a movement. Each settled revision is a snapshot; the bar offers undo, redo and "back to version N", and every step morphs through the same view-transition layer a view switch uses — the artifact changes, it never blinks.

csharp
// The contract, plus the implementation DRYL ships. Register your own instead and it wins.
builder.Services.AddDrylCanvasDocumentStore();

// Save the whole workspace …
var doc = CanvasDocument.Capture(_ws, "Sales dashboard");
var id = await store.SaveAsync(doc);

// … and bring it back, views, active view and all.
var loaded = await store.LoadAsync(id);
loaded?.Restore(_ws);

// A saved document as the starting point of a new one.
var fresh = loaded!.AsTemplate("Q3 dashboard");
razor
<DrylCanvasWorkspace Workspace="_ws"
                     ShowHistory
                     Revision="_run.Round"
                     RevisionLabel="@_lastPrompt"
                     AutoSave
                     @bind-DocumentId="_documentId"
                     DocumentTitle="Sales dashboard" />

Document and history

Add a metric a few times — each change is committed as a version. Step back with undo, jump to any version through the history popover, then save the workspace, change it again and load it back. &quot;New from template&quot; turns the saved document into the starting point of a new one. Everything runs against the in-memory store; no model involved.

Overview

Revenue is up 12% this quarter.

Add a metric, then step back with undo.

Direct manipulation

Describing a change is not always the shortest way to make one. Hand the canvas a CanvasSelection and its elements become pickable — by click or by keyboard. The selected element carries a small toolbar: prompt about it, pin it, duplicate it, remove it, drag it into another slot.

A pin is an instruction to the AI, not a freeze. A node marked "locked": true is refused by the patcher on every AI op — and the model gets a sentence in its receipt saying why, so the next turn works around it instead of retrying. What you trigger still goes through: a data refresh keeps refreshing, an action result keeps landing, and the toolbar itself keeps working.

The dock knows what you pointed at. Share one selection between canvas and dock and the chip above the input names the element; the prompt you send is prefixed with its id, type and label, so "make it a bar chart" patches the right node. And because a reorder is a plain move op, the siblings glide into their new slots on the FLIP layer that was already there — one op, one movement.

csharp
// One selection, shared by the canvas and the dock. Handing it over is the opt-in —
// there is no second flag, and a canvas without one renders exactly as before.
private readonly CanvasSelection _selection = new();

// A user edit is a version like an AI round is.
private void HandleEdit(CanvasEdit edit)
{
    _revisionLabel = edit.Label;   // e.g. "Removed Revenue per month"
    _revision++;
}
razor
<DrylCanvasWorkspace Workspace="_ws" ShowHistory
                     Revision="_revision" RevisionLabel="@_revisionLabel">
    <View>
        <DrylAiCanvas Run="_run" AllowExpand="false"
                      Selection="_selection" OnEdit="HandleEdit" />
    </View>
</DrylCanvasWorkspace>

<DrylCanvasDock Run="_run" Busy="Busy" OnSend="Send" Selection="_selection" />

Direct manipulation

Ask for &quot;Overview&quot;, then click an element. Pin it and watch the toolbar disable what a pin forbids; duplicate it and the copy glides in with fresh ids; drag the handle or press Alt+Arrow to reorder. With something selected, the dock prefixes your prompt with that element — send anything and the scripted update round updates the free stats while bouncing off the pinned one. Every edit is committed as a version, so undo covers your changes as well as the model's.

Click an element to select it — then prompt about it, pin, duplicate or remove it. Arrow keys walk the artifact, Alt + / reorders, Enter asks the dock about the selected element.

No view yet
Ask for a view below — &quot;Overview&quot;, for example.
Overview Order 4711 — ask for one, then take it apart by hand. The first stat comes pinned.
An unhandled error has occurred. Reload x

Reconnecting to the server…

Attempt /

Next try in s