feat(frontend): add canvas agent empty state with server-driven starters

Render a CanvasAgentEmptyState in the Agent panel that fetches localized
starter content from the new agent-starters endpoint, with local defaults
as fallback. Clicking a starter focuses the prompt composer (new focus
handle). Includes accompanying UI polish: side-nav cleanup, animated
prompt examples, and canvas panel spacing tweaks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 22:19:22 +08:00
parent c94b163540
commit 71a1b3ace4
16 changed files with 472 additions and 77 deletions
+98 -36
View File
@@ -29,6 +29,7 @@
--blue-soft: #dbeafe;
--black: #050505;
--assistant-panel-width: 600px;
--canvas-side-panel-width: 268px;
--shadow-sm: 0 2px 8px rgba(17, 24, 39, 0.06);
--shadow-md: 0 12px 30px rgba(17, 24, 39, 0.08);
}
@@ -495,6 +496,20 @@ button:disabled {
border-radius: 999px;
font-size: 12px;
font-weight: 800;
animation: prompt-example-enter 360ms cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: calc(var(--prompt-example-index, 0) * 45ms);
}
@keyframes prompt-example-enter {
from {
opacity: 0;
transform: translate3d(0, 9px, 0) scale(0.97);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0) scale(1);
}
}
.prompt-examples strong {
@@ -1287,7 +1302,7 @@ button:disabled {
position: absolute;
top: 0;
left: 8px;
z-index: 45;
z-index: 43;
height: 48px;
display: flex;
align-items: center;
@@ -1295,6 +1310,14 @@ button:disabled {
max-width: calc(100% - 220px);
min-width: 0;
pointer-events: auto;
transform: translate3d(0, 0, 0);
transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1), max-width 260ms cubic-bezier(0.22, 1, 0.36, 1);
will-change: transform;
}
.workspace-stage-title.is-offset-by-canvas-panel {
max-width: calc(100% - var(--canvas-side-panel-width) - 220px);
transform: translate3d(var(--canvas-side-panel-width), 0, 0);
}
.canvas-account-controls {
@@ -2524,7 +2547,7 @@ button:disabled {
}
.canvas-layer-panel {
--layer-panel-width: 274px;
--layer-panel-width: var(--canvas-side-panel-width);
position: absolute;
z-index: 44;
left: 0;
@@ -2825,7 +2848,7 @@ button:disabled {
}
.canvas-generated-files-panel {
--generated-files-panel-width: 408px;
--generated-files-panel-width: var(--canvas-side-panel-width);
position: absolute;
z-index: 44;
left: 0;
@@ -2841,6 +2864,22 @@ button:disabled {
font-size: 14px;
}
.canvas-layer-panel,
.canvas-generated-files-panel {
animation: canvas-side-panel-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
will-change: transform;
}
@keyframes canvas-side-panel-enter {
from {
transform: translate3d(-100%, 0, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
.canvas-generated-files-panel header {
display: flex;
align-items: center;
@@ -2872,38 +2911,41 @@ button:disabled {
.generated-files-list {
min-height: 0;
display: grid;
align-content: start;
gap: 10px;
padding: 2px 14px 22px;
display: flex;
flex-direction: column;
gap: 4px;
padding: 2px 8px 22px;
overflow-y: auto;
}
.generated-file-row {
min-height: 74px;
min-height: 56px;
display: grid;
grid-template-columns: 72px minmax(0, 1fr) 32px;
grid-template-columns: 48px minmax(0, 1fr) 16px;
align-items: center;
gap: 18px;
padding: 4px 0;
border-radius: 10px;
color: #262b33;
gap: 12px;
padding: 4px 8px;
border-radius: 8px;
color: #363636;
cursor: pointer;
}
.generated-file-row:hover,
.generated-file-row:hover {
background: rgba(12, 12, 13, 0.04);
}
.generated-file-row.selected {
background: #f4f6f8;
background: rgba(12, 12, 13, 0.06);
}
.generated-file-thumb {
width: 72px;
height: 72px;
width: 48px;
height: 48px;
display: block;
overflow: hidden;
border-radius: 10px;
border-radius: 8px;
background: #f2f3f5;
box-shadow: inset 0 0 0 1px rgba(17, 24, 39, 0.06);
box-shadow: 0 2px 10px rgba(1, 1, 1, 0.1);
}
.generated-file-thumb img {
@@ -2916,27 +2958,28 @@ button:disabled {
.generated-file-name {
min-width: 0;
overflow: hidden;
color: #2c3138;
color: #363636;
font-size: 14px;
font-weight: 520;
font-weight: 400;
line-height: 22px;
letter-spacing: 0;
text-overflow: ellipsis;
white-space: nowrap;
}
.generated-file-download {
width: 32px;
height: 32px;
width: 16px;
height: 16px;
display: grid;
place-items: center;
border-radius: 9px;
color: #535a64;
border-radius: 4px;
color: #363636;
background: transparent;
}
.generated-file-download:hover {
color: #111827;
background: #eceff3;
color: #111;
background: transparent;
}
.generated-files-empty {
@@ -2955,10 +2998,11 @@ button:disabled {
}
.generated-files-end {
padding: 16px 0 0;
color: #a4a9b1;
padding: 8px 0;
color: #86909c;
font-size: 14px;
font-weight: 560;
font-weight: 400;
line-height: 20px;
text-align: center;
}
@@ -2971,11 +3015,11 @@ button:disabled {
}
.canvas-bottom-left.is-offset-by-files-panel {
left: 424px;
left: calc(var(--canvas-side-panel-width) + 16px);
}
.canvas-bottom-left.is-offset-by-layers-panel {
left: 290px;
left: calc(var(--canvas-side-panel-width) + 16px);
}
.canvas-statusbar,
@@ -3084,11 +3128,11 @@ button:disabled {
}
.workspace-toolbar.is-offset-by-files-panel {
left: calc(408px + (100% - 408px) / 2);
left: calc(var(--canvas-side-panel-width) + (100% - var(--canvas-side-panel-width)) / 2);
}
.workspace-toolbar.is-offset-by-layers-panel {
left: calc(274px + (100% - 274px) / 2);
left: calc(var(--canvas-side-panel-width) + (100% - var(--canvas-side-panel-width)) / 2);
}
.workspace-toolbar button {
@@ -3152,11 +3196,11 @@ button:disabled {
}
.pen-tool-controls.is-offset-by-files-panel {
left: calc(408px + (100% - 408px) / 2);
left: calc(var(--canvas-side-panel-width) + (100% - var(--canvas-side-panel-width)) / 2);
}
.pen-tool-controls.is-offset-by-layers-panel {
left: calc(274px + (100% - 274px) / 2);
left: calc(var(--canvas-side-panel-width) + (100% - var(--canvas-side-panel-width)) / 2);
}
.pen-color-trigger {
@@ -3950,6 +3994,11 @@ button:disabled {
min-width: 0;
}
.workspace-stage-title.is-offset-by-canvas-panel {
max-width: none;
transform: none;
}
.workspace-stage-title .brand-kit-selector-trigger.is-compact {
max-width: 104px;
}
@@ -4088,6 +4137,19 @@ button:disabled {
}
}
@media (prefers-reduced-motion: reduce) {
.workspace-stage-title {
transition: none;
}
.canvas-layer-panel,
.canvas-generated-files-panel,
.prompt-examples strong,
.prompt-examples button {
animation: none;
}
}
@media (max-width: 480px) {
.workspace-countdown div {
display: none;