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) }; } }