From f92b5f43739bc7c3a6e5d964ca42a5fca8aaf808 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:18:49 +0800 Subject: [PATCH] Add AI-related color resources to theme palette and demo (#689) * Initial plan * Add AI-related color resources for Light and Dark themes Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> * Fix gradient angle to correctly represent 278 degrees Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> * Fix gradient angle and add AI resources to palette demo Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> * Add AI General gradients section to palette demo UI Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> * feat: unify gradient initialization. * feat: add AI-related color resources for Light and Dark themes. * feat: add AI-related color tokens to ColorTokens and PaletteDemo * Rename AI token names from Ai to AI (capital) Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> * fix: fix AI-related color tokens names. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com> Co-authored-by: Dong Bin Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com> --- .../Constant/ColorTokens.cs | 26 +++ .../Controls/ColorDetailControl.cs | 6 + .../ViewModels/PaletteDemoViewModel.cs | 60 ++++++- src/Semi.Avalonia/Tokens/Palette/Dark.axaml | 150 ++++++++++++++++++ src/Semi.Avalonia/Tokens/Palette/Light.axaml | 150 ++++++++++++++++++ 5 files changed, 386 insertions(+), 6 deletions(-) diff --git a/demo/Semi.Avalonia.Demo/Constant/ColorTokens.cs b/demo/Semi.Avalonia.Demo/Constant/ColorTokens.cs index 7475113..5512830 100644 --- a/demo/Semi.Avalonia.Demo/Constant/ColorTokens.cs +++ b/demo/Semi.Avalonia.Demo/Constant/ColorTokens.cs @@ -79,6 +79,32 @@ public static class ColorTokens new("SemiColorDangerLightActive", "Danger Light Active") ]; + public static IReadOnlyList> AIGeneralTokens { get; } = + [ + new("SemiColorAIGeneral", "AI General"), + new("SemiColorAIGeneralPointerover", "AI General Pointerover"), + new("SemiColorAIGeneralActive", "AI General Active"), + new("SemiColorAIGeneralDisabled", "AI General Disabled") + ]; + + public static IReadOnlyList> AIPurpleTokens { get; } = + [ + new("SemiColorAIPurple", "AI Purple"), + new("SemiColorAIPurplePointerover", "AI Purple Pointerover"), + new("SemiColorAIPurpleActive", "AI Purple Active"), + new("SemiColorAIPurpleDisabled", "AI Purple Disabled") + ]; + + public static IReadOnlyList> AIBackgroundTokens { get; } = + [ + new("SemiColorAIBackgroundBottom", "AI Bottom Background"), + new("SemiColorAIBackgroundBottomPointerover", "AI Bottom Background Pointerover"), + new("SemiColorAIBackgroundBottomActive", "AI Bottom Background Active"), + new("SemiColorAIBackgroundTop", "AI Top Background"), + new("SemiColorAIBackgroundTopPointerover", "AI Top Background Pointerover"), + new("SemiColorAIBackgroundTopActive", "AI Top Background Active"), + ]; + public static IReadOnlyList> TextTokens { get; } = [ new("SemiColorText0", "Text 0"), diff --git a/demo/Semi.Avalonia.Demo/Controls/ColorDetailControl.cs b/demo/Semi.Avalonia.Demo/Controls/ColorDetailControl.cs index 4a12060..06a2ce8 100644 --- a/demo/Semi.Avalonia.Demo/Controls/ColorDetailControl.cs +++ b/demo/Semi.Avalonia.Demo/Controls/ColorDetailControl.cs @@ -92,6 +92,12 @@ public class ColorDetailControl : TemplatedControl Hex2 = hex2 as string; OpacityNumber = brush.Opacity.ToString(CultureInfo.InvariantCulture); } + else + { + Hex = null; + Hex2 = null; + OpacityNumber = null; + } } public async Task Copy(object o) diff --git a/demo/Semi.Avalonia.Demo/ViewModels/PaletteDemoViewModel.cs b/demo/Semi.Avalonia.Demo/ViewModels/PaletteDemoViewModel.cs index ab77f92..363c608 100644 --- a/demo/Semi.Avalonia.Demo/ViewModels/PaletteDemoViewModel.cs +++ b/demo/Semi.Avalonia.Demo/ViewModels/PaletteDemoViewModel.cs @@ -19,7 +19,7 @@ public partial class PaletteDemoViewModel : ObservableObject "Red", "Pink", "Purple", "Violet", "Indigo", "Blue", "LightBlue", "Cyan", "Teal", "Green", "LightGreen", "Lime", "Yellow", "Amber", "Orange", - "Grey" + "Grey", "AIPurple" ]; private readonly IResourceDictionary? _lightResourceDictionary; @@ -61,6 +61,38 @@ public partial class PaletteDemoViewModel : ObservableObject s.Initialize(_darkResourceDictionary, color, false); DarkLists.Add(s); } + + InitializeAIGeneralGradients(); + } + + private void InitializeAIGeneralGradients() + { + if (_lightResourceDictionary is null || _darkResourceDictionary is null) return; + + ColorListViewModel lightGradients = new ColorListViewModel { SeriesName = "AI General" }; + ColorListViewModel darkGradients = new ColorListViewModel { SeriesName = "AI General" }; + + for (var i = 0; i < 10; i++) + { + var key = $"SemiAIGeneral{i}"; + + if (_lightResourceDictionary.TryGetValue(key, out var lightValue) && lightValue is IBrush lightBrush) + { + var name = $"AI General {i}"; + var item = new ColorItemViewModel(name, lightBrush, key, true, i); + lightGradients.Color.Add(item); + } + + if (_darkResourceDictionary.TryGetValue(key, out var darkValue) && darkValue is IBrush darkBrush) + { + var name = $"AI General {i}"; + var item = new ColorItemViewModel(name, darkBrush, key, false, i); + darkGradients.Color.Add(item); + } + } + + LightLists.Add(lightGradients); + DarkLists.Add(darkGradients); } private void InitializeFunctionalColors() @@ -79,6 +111,12 @@ public partial class PaletteDemoViewModel : ObservableObject "Warning", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.WarningTokens)); FunctionalColors.Add(new FunctionalColorGroupViewModel( "Danger", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.DangerTokens)); + FunctionalColors.Add(new FunctionalColorGroupViewModel( + "AI General", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.AIGeneralTokens)); + FunctionalColors.Add(new FunctionalColorGroupViewModel( + "AI Purple", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.AIPurpleTokens)); + FunctionalColors.Add(new FunctionalColorGroupViewModel( + "AI Background", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.AIBackgroundTokens)); FunctionalColors.Add(new FunctionalColorGroupViewModel( "Text", _lightResourceDictionary, _darkResourceDictionary, ColorTokens.TextTokens)); FunctionalColors.Add(new FunctionalColorGroupViewModel( @@ -142,14 +180,24 @@ public partial class ColorItemViewModel : ObservableObject """; - public ColorItemViewModel(string colorDisplayName, ISolidColorBrush brush, string resourceKey, bool light, + public ColorItemViewModel(string colorDisplayName, IBrush brush, string resourceKey, bool light, int index) { ColorDisplayName = colorDisplayName; Brush = brush; ResourceKey = resourceKey; - var hex = ColorConverter.ToHex.Convert(brush.Color, typeof(string), false, CultureInfo.InvariantCulture); - Hex = hex as string ?? string.Empty; + + // Only calculate hex for solid color brushes + if (brush is ISolidColorBrush solidBrush) + { + var hex = ColorConverter.ToHex.Convert(solidBrush.Color, typeof(string), false, CultureInfo.InvariantCulture); + Hex = hex as string ?? string.Empty; + } + else + { + Hex = string.Empty; + } + if ((light && index < 5) || (!light && index >= 5)) { TextBrush = Brushes.Black; @@ -175,7 +223,7 @@ public partial class FunctionalColorGroupViewModel : ObservableObject { if (lightDictionary?.TryGetValue(key, out var lightValue) ?? false) { - if (lightValue is ISolidColorBrush lightBrush) + if (lightValue is IBrush lightBrush) { LightColors.Add(new ColorItemViewModel(name, lightBrush, key, true, 0)); } @@ -183,7 +231,7 @@ public partial class FunctionalColorGroupViewModel : ObservableObject if (darkDictionary?.TryGetValue(key, out var darkValue) ?? false) { - if (darkValue is ISolidColorBrush darkBrush) + if (darkValue is IBrush darkBrush) { DarkColors.Add(new ColorItemViewModel(name, darkBrush, key, true, 0)); } diff --git a/src/Semi.Avalonia/Tokens/Palette/Dark.axaml b/src/Semi.Avalonia/Tokens/Palette/Dark.axaml index 11ab37e..591be1f 100644 --- a/src/Semi.Avalonia/Tokens/Palette/Dark.axaml +++ b/src/Semi.Avalonia/Tokens/Palette/Dark.axaml @@ -170,6 +170,16 @@ #35363C #43444A #4F5159 + #3A1770 + #532394 + #6F31B8 + #8D41DB + #A744FF + #C375FF + #D598FF + #E5BAFF + #F3DDFF + #FBF3FF @@ -333,6 +343,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -390,6 +470,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Semi.Avalonia/Tokens/Palette/Light.axaml b/src/Semi.Avalonia/Tokens/Palette/Light.axaml index 7b4b843..91beb1c 100644 --- a/src/Semi.Avalonia/Tokens/Palette/Light.axaml +++ b/src/Semi.Avalonia/Tokens/Palette/Light.axaml @@ -170,6 +170,16 @@ White White White + #F8EDFF + #F2DAFF + #E3B5FF + #D191FF + #BD6CFF + #A647FF + #8636DB + #6928B8 + #4E1C94 + #361270 @@ -333,6 +343,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -390,6 +470,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +