diff --git a/controlgallery/AtomUIGallery.Browser/BrowserGalleryView.cs b/controlgallery/AtomUIGallery.Browser/BrowserGalleryView.cs
index ca01c1ae6..0780bf4d5 100644
--- a/controlgallery/AtomUIGallery.Browser/BrowserGalleryView.cs
+++ b/controlgallery/AtomUIGallery.Browser/BrowserGalleryView.cs
@@ -1,6 +1,8 @@
using AtomUIGallery.ShowCases.AboutUs;
+using AtomUIGallery.ShowCases.Palette;
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.Imaging;
@@ -11,6 +13,10 @@ namespace AtomUIGallery.Browser;
internal sealed class BrowserGalleryView : UserControl, IScreen
{
+ private readonly Border _aboutUsNavigationItem;
+ private readonly Border _paletteNavigationItem;
+ private readonly ContentControl _contentHost;
+
public RoutingState Router { get; } = new();
public BrowserGalleryView()
@@ -46,6 +52,9 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
};
Grid.SetColumnSpan(header, 2);
+ _aboutUsNavigationItem = CreateNavigationItem("AboutUs", () => ShowAboutUs());
+ _paletteNavigationItem = CreateNavigationItem("Palette", () => ShowPalette());
+
var navigation = new Border
{
BorderBrush = new SolidColorBrush(Color.Parse("#E5E7EB")),
@@ -64,23 +73,16 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
FontWeight = FontWeight.SemiBold,
Foreground = new SolidColorBrush(Color.Parse("#374151"))
},
- new TextBlock
- {
- Text = "AboutUs",
- FontSize = 14,
- Foreground = new SolidColorBrush(Color.Parse("#111827"))
- }
+ _aboutUsNavigationItem,
+ _paletteNavigationItem
}
}
};
Grid.SetRow(navigation, 1);
- var aboutUsPage = new AboutUsPage
- {
- DataContext = new AboutUsViewModel(this)
- };
- Grid.SetColumn(aboutUsPage, 1);
- Grid.SetRow(aboutUsPage, 1);
+ _contentHost = new ContentControl();
+ Grid.SetColumn(_contentHost, 1);
+ Grid.SetRow(_contentHost, 1);
Content = new Grid
{
@@ -91,9 +93,11 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
{
header,
navigation,
- aboutUsPage
+ _contentHost
}
};
+
+ ShowAboutUs();
}
private static Bitmap LoadGalleryLogo()
@@ -101,4 +105,58 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
using var stream = AssetLoader.Open(new Uri("avares://AtomUIGallery.Browser/Assets/gallery-logo.png"));
return new Bitmap(stream);
}
+
+ private Border CreateNavigationItem(string text, Action navigate)
+ {
+ var item = new Border
+ {
+ CornerRadius = new CornerRadius(4),
+ Padding = new Thickness(8, 6),
+ Cursor = new Cursor(StandardCursorType.Hand),
+ Child = new TextBlock
+ {
+ Text = text,
+ FontSize = 14,
+ Foreground = new SolidColorBrush(Color.Parse("#111827"))
+ }
+ };
+ item.PointerPressed += (_, _) => navigate();
+ return item;
+ }
+
+ private void ShowAboutUs()
+ {
+ _contentHost.Content = new AboutUsPage
+ {
+ DataContext = new AboutUsViewModel(this)
+ };
+ UpdateNavigationSelection(_aboutUsNavigationItem);
+ }
+
+ private void ShowPalette()
+ {
+ _contentHost.Content = new PaletteShowCase
+ {
+ DataContext = new PaletteViewModel(this)
+ };
+ UpdateNavigationSelection(_paletteNavigationItem);
+ }
+
+ private void UpdateNavigationSelection(Border selectedItem)
+ {
+ ApplyNavigationItemState(_aboutUsNavigationItem, selectedItem == _aboutUsNavigationItem);
+ ApplyNavigationItemState(_paletteNavigationItem, selectedItem == _paletteNavigationItem);
+ }
+
+ private static void ApplyNavigationItemState(Border item, bool isSelected)
+ {
+ item.Background = isSelected
+ ? new SolidColorBrush(Color.Parse("#F3F4F6"))
+ : Brushes.Transparent;
+
+ if (item.Child is TextBlock textBlock)
+ {
+ textBlock.FontWeight = isSelected ? FontWeight.SemiBold : FontWeight.Normal;
+ }
+ }
}
diff --git a/docs/AtomUIGallery/browser-gallery-porting-notes.md b/docs/AtomUIGallery/browser-gallery-porting-notes.md
index 2ab390cbe..1ee621437 100644
--- a/docs/AtomUIGallery/browser-gallery-porting-notes.md
+++ b/docs/AtomUIGallery/browser-gallery-porting-notes.md
@@ -1,12 +1,12 @@
# AtomUI Gallery Browser 改造问题记录
-本文档记录 2026-06-07 进行 `AtomUIGallery.Browser` 初步改造时遇到的问题、根因和处理结论。当前目标是先让 Browser Gallery 以薄封装方式复用共享 `AtomUIGallery` 的 `AboutUsPage`,并允许 Browser 项目引用 `AtomUI.Desktop.Controls`,由控件库内部自动降级。
+本文档记录 2026-06-07 进行 `AtomUIGallery.Browser` 初步改造时遇到的问题、根因和处理结论。当前目标是让 Browser Gallery 以薄封装方式复用共享 `AtomUIGallery` 的 ShowCase,并允许 Browser 项目引用 `AtomUI.Desktop.Controls`,由控件库内部自动降级。
## 本轮目标
- 新增 Browser Gallery 项目并跑通空壳应用。
- Browser 启动阶段使用 AtomUI 红色 SVG logo。
-- Browser Gallery 不复制 `AboutUsPage`,只做一层薄的宿主封装。
+- Browser Gallery 不复制 `AboutUsPage` / `PaletteShowCase`,只做一层薄的宿主封装。
- Browser 可以引用 `AtomUI.Desktop.Controls`,用户侧继续调用 `UseDesktopControls()`,控件库内部按平台自动降级。
- 不改变公开 API,不影响 Desktop Gallery 原有行为。
@@ -53,13 +53,18 @@ this.UseAtomUI(builder =>
});
```
-`BrowserGalleryView` 只负责 Browser 单视图宿主和导航外壳,内容直接创建共享页面:
+`BrowserGalleryView` 只负责 Browser 单视图宿主、导航外壳和当前 ShowCase 切换,内容直接创建共享页面:
```csharp
var aboutUsPage = new AboutUsPage
{
DataContext = new AboutUsViewModel(this)
};
+
+var paletteShowCase = new PaletteShowCase
+{
+ DataContext = new PaletteViewModel(this)
+};
```
### Common 控件降级
@@ -101,12 +106,13 @@ themeManagerBuilder.AddControlThemesProvider(RuntimePlatform.Features.SupportsNa
: new BrowserDesktopControlThemesProvider());
```
-Browser desktop provider 当前只承载 `AboutUsPage` 需要的最小集合:
+Browser desktop provider 当前只承载 `AboutUsPage` 和 `PaletteShowCase` 需要的最小集合:
```text
-Buttons/Themes/HyperLinkButtonTheme.axaml
+Buttons/Themes/BrowserButtonThemes.axaml
GroupBox/Themes/GroupBoxTheme.axaml
ScrollViewer/Themes/ScrollViewerThemes.axaml
+TabControl/Themes/TabControlThemes.axaml
```
Browser token 当前只注册:
@@ -114,7 +120,9 @@ Browser token 当前只注册:
```text
ButtonToken
GroupBoxToken
+MenuToken
ScrollViewerToken
+TabControlToken
```
Desktop 下仍然使用完整 `ControlTokenTypePool` 和 `DesktopControlThemesProvider`,并继续注册原有 initialized handler。Browser 下跳过该 handler,避免注册 Window/Tooltip/媒体断点等 native window 相关逻辑。
@@ -146,7 +154,7 @@ dotnet build controlgallery/AtomUIGallery.Desktop/AtomUIGallery.Desktop.csproj -
- Browser Debug build 通过。
- Desktop Gallery Debug build 通过。
-- Browser 实跑 `AboutUsPage` 渲染成功,无 `.splash-error`。
+- Browser 实跑 `AboutUsPage` / `PaletteShowCase` 渲染成功,无 `.splash-error`。
Browser 运行验证时不要只依赖 DOM 文本,因为 Avalonia Browser 页面内容主要在 canvas 中绘制;需要结合 splash error 和截图。
@@ -162,6 +170,6 @@ Browser 运行验证时不要只依赖 DOM 文本,因为 Avalonia Browser 页
## 待继续处理
- `UseDesktopColorPicker()` 和 `UseDesktopDataGrid()` 尚未接入 Browser 降级路径。
-- Browser Gallery 当前只接入 `AboutUsPage`,完整 Workspace / AppView / AppShell 还未实现。
+- Browser Gallery 当前只接入 `AboutUsPage` 和 `PaletteShowCase`,完整 Workspace / AppView / AppShell 还未实现。
- `BrowserDesktopControlThemesProvider` 的范围后续应随着 ShowCase 迁移逐步扩大,并保持最小可用集合。
- `EmbeddableControlRootTheme` 在 Browser 下的精确不兼容点后续可以进一步拆解;当前先通过 Browser provider 排除该资源,保证启动路径稳定。
diff --git a/src/AtomUI.Desktop.Controls/BrowserDesktopControlThemesProvider.axaml b/src/AtomUI.Desktop.Controls/BrowserDesktopControlThemesProvider.axaml
index 25ff7ef56..60cd6f3d4 100644
--- a/src/AtomUI.Desktop.Controls/BrowserDesktopControlThemesProvider.axaml
+++ b/src/AtomUI.Desktop.Controls/BrowserDesktopControlThemesProvider.axaml
@@ -4,8 +4,9 @@
x:Class="AtomUI.Desktop.Controls.BrowserDesktopControlThemesProvider"
Id="AtomUI.Desktop.Controls">
-
+
+
diff --git a/src/AtomUI.Desktop.Controls/Buttons/Themes/BrowserButtonThemes.axaml b/src/AtomUI.Desktop.Controls/Buttons/Themes/BrowserButtonThemes.axaml
new file mode 100644
index 000000000..1424b19f4
--- /dev/null
+++ b/src/AtomUI.Desktop.Controls/Buttons/Themes/BrowserButtonThemes.axaml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/src/AtomUI.Desktop.Controls/ThemeManagerBuilderExtensions.cs b/src/AtomUI.Desktop.Controls/ThemeManagerBuilderExtensions.cs
index 6cc3bf2ab..83164c387 100644
--- a/src/AtomUI.Desktop.Controls/ThemeManagerBuilderExtensions.cs
+++ b/src/AtomUI.Desktop.Controls/ThemeManagerBuilderExtensions.cs
@@ -60,7 +60,9 @@ public static class ThemeManagerBuilderExtensions
{
typeof(ButtonToken),
typeof(GroupBoxToken),
- typeof(ScrollViewerToken)
+ typeof(MenuToken),
+ typeof(ScrollViewerToken),
+ typeof(TabControlToken)
};
}
}