From 2bcb1b5d53354ef8ba071479a8d712fe6c7836c2 Mon Sep 17 00:00:00 2001
From: Karen Lai <7976322+karkarl@users.noreply.github.com>
Date: Fri, 9 Oct 2026 11:28:05 -0700
Subject: [PATCH] fix: prevent sidebar toggle icon clipping at display scales
Keep the native WinUI subtle-button style while removing text-button padding from Workspace and Settings pane toggles. Add native layout and markup regression coverage and document the icon-only padding invariant.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3439bb57-3a0e-4b13-b579-25edeafbf01d
---
docs/CONNECTION_ARCHITECTURE.md | 3 +
.../Windows/HubWindow.xaml | 2 +-
.../Windows/WorkspaceWindow.xaml | 4 +-
.../Presentation/WorkspaceNavigationTests.cs | 1 +
.../WorkspaceSessionLayoutTests.cs | 67 +++++++++++++++++++
5 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/docs/CONNECTION_ARCHITECTURE.md b/docs/CONNECTION_ARCHITECTURE.md
index ed47c79b9a..08b01929f7 100644
--- a/docs/CONNECTION_ARCHITECTURE.md
+++ b/docs/CONNECTION_ARCHITECTURE.md
@@ -193,6 +193,9 @@ A floating-style subtle reopen button reserves a dedicated 56 DIP row at
the content's top-left below the titlebar, never covering hosted hit targets.
The pane toggle retains a 40 DIP target and 16 DIP glyph in both states; focus
moves to the surviving toggle. Pane changes do not remount chat or reset drafts.
+Both Workspace toggle states and the Settings toggle use the native
+`SubtleButtonStyle` with zero padding for icon-only content. The style's default
+text-button padding must not squeeze the glyph inside the fixed 40 DIP target.
The companion uses a native TitleBar titled OpenClaw Settings with shared claw
artwork. Search, Back, and Forward live beside the toggle in its stable sidebar
toolbar. The native pane reserves 56 DIP above its items, including in compact mode.
diff --git a/src/OpenClaw.Tray.WinUI/Windows/HubWindow.xaml b/src/OpenClaw.Tray.WinUI/Windows/HubWindow.xaml
index 197a988c2b..db7dc60f11 100644
--- a/src/OpenClaw.Tray.WinUI/Windows/HubWindow.xaml
+++ b/src/OpenClaw.Tray.WinUI/Windows/HubWindow.xaml
@@ -182,7 +182,7 @@
AutomationProperties.AutomationId="SettingsTogglePane"
AutomationProperties.Name="Toggle navigation pane"
ToolTipService.ToolTip="Toggle navigation pane"
- Width="40" Height="40" Margin="4,0,0,0"
+ Width="40" Height="40" Padding="0" Margin="4,0,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Style="{StaticResource SubtleButtonStyle}" Click="OnNavPaneToggleButtonClick">
diff --git a/src/OpenClaw.Tray.WinUI/Windows/WorkspaceWindow.xaml b/src/OpenClaw.Tray.WinUI/Windows/WorkspaceWindow.xaml
index 66dcc0f82d..2bc1a45410 100644
--- a/src/OpenClaw.Tray.WinUI/Windows/WorkspaceWindow.xaml
+++ b/src/OpenClaw.Tray.WinUI/Windows/WorkspaceWindow.xaml
@@ -200,13 +200,13 @@
diff --git a/tests/OpenClaw.Tray.Tests/Presentation/WorkspaceNavigationTests.cs b/tests/OpenClaw.Tray.Tests/Presentation/WorkspaceNavigationTests.cs
index 018b4a2620..ad79eb645b 100644
--- a/tests/OpenClaw.Tray.Tests/Presentation/WorkspaceNavigationTests.cs
+++ b/tests/OpenClaw.Tray.Tests/Presentation/WorkspaceNavigationTests.cs
@@ -473,6 +473,7 @@ public void PaneToggle_TargetAndGlyphSizesMatchAcrossPaneStates()
Assert.Equal("{StaticResource SubtleButtonStyle}", (string?)toggle.Attribute("Style"));
Assert.Equal("40", (string?)toggle.Attribute("Width"));
Assert.Equal("40", (string?)toggle.Attribute("Height"));
+ Assert.Equal("0", (string?)toggle.Attribute("Padding"));
var icon = Assert.Single(toggle.Descendants(), element => element.Name.LocalName == "FontIcon");
Assert.Equal("16", (string?)icon.Attribute("FontSize"));
}
diff --git a/tests/OpenClaw.Tray.UITests/WorkspaceSessionLayoutTests.cs b/tests/OpenClaw.Tray.UITests/WorkspaceSessionLayoutTests.cs
index fdca1e7a4e..a4890309dd 100644
--- a/tests/OpenClaw.Tray.UITests/WorkspaceSessionLayoutTests.cs
+++ b/tests/OpenClaw.Tray.UITests/WorkspaceSessionLayoutTests.cs
@@ -1,5 +1,7 @@
+using System.Xml.Linq;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Markup;
using OpenClawTray.Presentation;
using OpenClawTray.Windows;
using Windows.Foundation;
@@ -9,6 +11,71 @@ namespace OpenClaw.Tray.UITests;
[Collection(UICollection.Name)]
public sealed class WorkspaceSessionLayoutTests(UIThreadFixture ui)
{
+ [Theory]
+ [InlineData("WorkspaceWindow.xaml", "CollapsePaneButton")]
+ [InlineData("WorkspaceWindow.xaml", "ReopenPaneButton")]
+ [InlineData("HubWindow.xaml", "NavPaneToggleButton")]
+ public async Task PaneToggle_LeavesRoundingRoomAroundUnconstrainedGlyph(string file, string name)
+ {
+ var root = Environment.GetEnvironmentVariable("OPENCLAW_REPO_ROOT")
+ ?? throw new InvalidOperationException("OPENCLAW_REPO_ROOT is required for production markup proof.");
+ var document = XDocument.Load(Path.Combine(root, "src", "OpenClaw.Tray.WinUI", "Windows", file));
+ XNamespace x = "http://schemas.microsoft.com/winfx/2006/xaml";
+ var markup = new XElement(document.Descendants().Single(element => (string?)element.Attribute(x + "Name") == name));
+ // Mount the production control without its window event handler or localized tooltip.
+ markup.Attribute("Click")!.Remove();
+ markup.Attribute(x + "Uid")!.Remove();
+ markup.SetAttributeValue("Visibility", "Visible");
+ markup.SetAttributeValue(XNamespace.Xmlns + "x", x.NamespaceName);
+
+ await ui.RunOnUIAsync(async () =>
+ {
+ var button = Assert.IsType