Refine right canvas rail controls
Move the right canvas rail into a centered floating socket in both open and closed states so chat space is preserved and the canvas content keeps the full panel width. Add a dedicated dock-style show/hide control, make surface buttons select surfaces without hiding the canvas, remove the header close button, and align the diff viewer header padding with shared spacing tokens. Update right-canvas.css
Alessandro committed
Apr 27, 2026 at 00:30 UTC
e92e518ab25883222f7f5bc38f637982e64e4ae0
4 files changed
+50
-27
plugins/_diff_viewer/webui/diff-viewer-panel.html
+1
-1
@@ -210,7 +210,7 @@
210
align-items: center;
211
gap: 6px;
212
min-height: 44px;
213
- padding: 7px 9px;
213
+ padding: var(--spacing-xs) var(--spacing-md);
214
border-bottom: 1px solid color-mix(in srgb, var(--color-border) 66%, transparent);
215
background: color-mix(in srgb, var(--color-background) 92%, #000 8%);
216
}
webui/components/canvas/right-canvas-store.js
+8
@@ -175,6 +175,14 @@ const model = {
175
return await this.open(targetId, payload);
176
},
177
178
+ async toggleCanvas() {
179
+ if (this.isOpen) {
180
+ await this.close();
181
+ return false;
182
+ }
183
+ return await this.open(this.activeSurfaceId || this.surfaces[0]?.id || "");
184
+ },
185
+
186
setWidth(px, options = {}) {
187
const { persist = true } = options;
188
const max = this.maxWidth();
webui/components/canvas/right-canvas.css
+26
-16
@@ -39,14 +39,30 @@ body.right-canvas-resizing {
39
}
40
41
.right-canvas-rail {
42
+ position: absolute;
43
+ top: 50%;
44
+ right: 100%;
45
+ z-index: 4;
46
display: flex;
47
flex: 0 0 52px;
48
flex-direction: column;
49
align-items: center;
50
gap: 7px;
51
+ height: auto;
52
+ max-height: min(70vh, calc(100vh - 32px));
53
padding: 10px 7px;
48
- border-right: 1px solid var(--right-canvas-border);
49
- background: color-mix(in srgb, var(--color-background) 92%, #000 8%);
54
+ transform: translateY(-50%);
55
+ border-right: 0;
56
+ border-radius: 8px 0 0 8px;
57
+ box-shadow: -10px 0 30px rgba(0, 0, 0, 0.24);
58
+ background: var(--color-chat-background);
59
+}
60
+
61
+.right-canvas-rail-separator {
62
+ width: 24px;
63
+ height: 1px;
64
+ margin: 1px 0 3px;
65
+ background: color-mix(in srgb, var(--right-canvas-border) 76%, transparent);
66
}
67
68
.right-canvas.is-closed {
@@ -57,25 +73,15 @@ body.right-canvas-resizing {
73
background: transparent;
74
}
75
76
+.right-canvas.is-open {
77
+ overflow: visible;
78
+}
79
+
80
.right-canvas.is-closed .right-canvas-shell,
81
.right-canvas.is-closed .right-canvas-resize-handle {
82
display: none;
83
}
84
65
-.right-canvas.is-closed .right-canvas-rail {
66
- position: absolute;
67
- top: 50%;
68
- right: 100%;
69
- z-index: 2;
70
- height: auto;
71
- max-height: min(70vh, calc(100vh - 32px));
72
- transform: translateY(-50%);
73
- border: 1px solid var(--right-canvas-border);
74
- border-right: 0;
75
- border-radius: 8px 0 0 8px;
76
- box-shadow: -10px 0 30px rgba(0, 0, 0, 0.24);
77
-}
78
-
85
.right-canvas-rail-button,
86
.right-canvas-icon-button,
87
.right-canvas-tab {
@@ -102,6 +108,10 @@ body.right-canvas-resizing {
108
transition: background-color 0.16s ease, border-color 0.16s ease, opacity 0.16s ease;
109
}
110
111
+.right-canvas-toggle-button {
112
+ color: color-mix(in srgb, var(--color-primary) 70%, var(--color-text));
113
+}
114
+
115
.right-canvas-rail-button:hover,
116
.right-canvas-icon-button:hover,
117
.right-canvas-rail-button.is-active {
webui/components/canvas/right-canvas.html
+15
-10
@@ -24,6 +24,20 @@
24
<div class="right-canvas-resize-handle" title="Resize canvas" @pointerdown="$store.rightCanvas.startResize($event)"></div>
25
26
<nav class="right-canvas-rail" aria-label="Canvas surfaces">
27
+ <button
28
+ type="button"
29
+ class="right-canvas-rail-button right-canvas-toggle-button"
30
+ :class="{ 'is-active': $store.rightCanvas.isOpen }"
31
+ :title="$store.rightCanvas.isOpen ? 'Hide canvas' : 'Show canvas'"
32
+ :aria-label="$store.rightCanvas.isOpen ? 'Hide canvas' : 'Show canvas'"
33
+ :aria-pressed="$store.rightCanvas.isOpen.toString()"
34
+ @click="$store.rightCanvas.toggleCanvas()"
35
+ >
36
+ <span class="material-symbols-outlined">dock_to_right</span>
37
+ </button>
38
+
39
+ <div class="right-canvas-rail-separator" aria-hidden="true"></div>
40
+
41
<template x-for="surface in $store.rightCanvas.surfaces" :key="surface.id">
42
<button
43
type="button"
@@ -31,7 +45,7 @@
45
:class="{ 'is-active': $store.rightCanvas.isSurfaceActive(surface.id) && $store.rightCanvas.isOpen }"
46
:title="surface.title"
47
:aria-label="surface.title"
34
- @click="$store.rightCanvas.toggle(surface.id)"
48
+ @click="$store.rightCanvas.open(surface.id)"
49
>
50
<span class="material-symbols-outlined" x-text="surface.icon"></span>
51
</button>
@@ -73,15 +87,6 @@
87
>
88
<span class="material-symbols-outlined">open_in_new</span>
89
</button>
76
- <button
77
- type="button"
78
- class="right-canvas-icon-button"
79
- title="Close canvas"
80
- aria-label="Close canvas"
81
- @click="$store.rightCanvas.close()"
82
- >
83
- <span class="material-symbols-outlined">close</span>
84
- </button>
90
<x-extension id="right-canvas-toolbar-end"></x-extension>
91
</div>
92
</header>