feat(Browser): add palette showcase with tab fallbacks

This commit is contained in:
chinboy
2026-06-07 18:04:02 +08:00
parent 013e18ffc2
commit 99cc82ef3a
5 changed files with 100 additions and 22 deletions
@@ -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;
}
}
}
@@ -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 排除该资源,保证启动路径稳定。
@@ -4,8 +4,9 @@
x:Class="AtomUI.Desktop.Controls.BrowserDesktopControlThemesProvider"
Id="AtomUI.Desktop.Controls">
<atom:ControlThemesProvider.ControlThemes>
<ResourceInclude Source="Buttons/Themes/HyperLinkButtonTheme.axaml" />
<ResourceInclude Source="Buttons/Themes/BrowserButtonThemes.axaml" />
<ResourceInclude Source="GroupBox/Themes/GroupBoxTheme.axaml" />
<ResourceInclude Source="ScrollViewer/Themes/ScrollViewerThemes.axaml" />
<ResourceInclude Source="TabControl/Themes/TabControlThemes.axaml" />
</atom:ControlThemesProvider.ControlThemes>
</atom:ControlThemesProvider>
@@ -0,0 +1,9 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
x:ClassModifier="internal">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="HyperLinkButtonTheme.axaml" />
</ResourceDictionary.MergedDictionaries>
<atom:IconButtonTheme x:Key="{x:Type atom:IconButton}" TargetType="atom:IconButton" />
</ResourceDictionary>
@@ -60,7 +60,9 @@ public static class ThemeManagerBuilderExtensions
{
typeof(ButtonToken),
typeof(GroupBoxToken),
typeof(ScrollViewerToken)
typeof(MenuToken),
typeof(ScrollViewerToken),
typeof(TabControlToken)
};
}
}