Browse Source
A new Home page (first in the drawer) modeled on the Accelerate demo dashboard: a gradient hero banner with floating control glyphs animated via keyframed TranslateTransforms, followed by categorized card sections for every catalog page. Cards carry an icon badge, title and one-line description, and clicking one navigates via SelectedPageIndex so the drawer selection stays in sync. PageItem gains Description/Category and the view model exposes grouped HomeSections plus NavigateToPageCommand. Card colors are self-contained theme dictionaries so the page works across Fluent/Fluent2/Simple in both variants. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>pull/21771/head
5 changed files with 373 additions and 71 deletions
@ -0,0 +1,174 @@ |
|||
<ContentPage Theme="{StaticResource ScrollPage}" |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:local="using:ControlCatalog" |
|||
xmlns:viewModels="using:ControlCatalog.ViewModels" |
|||
x:Class="ControlCatalog.Pages.HomePage" |
|||
x:DataType="viewModels:MainWindowViewModel" |
|||
Header="Home"> |
|||
|
|||
<ContentPage.Resources> |
|||
<ResourceDictionary> |
|||
<ResourceDictionary.ThemeDictionaries> |
|||
<ResourceDictionary x:Key="Default"> |
|||
<SolidColorBrush x:Key="HomeCardBackground" Color="#FFFFFF" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#E5E5EA" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#3E6DF3" /> |
|||
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#64646E" /> |
|||
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#E8EFFD" /> |
|||
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#3462D9" /> |
|||
<SolidColorBrush x:Key="HomeSectionDivider" Color="#EBEBEF" /> |
|||
</ResourceDictionary> |
|||
<ResourceDictionary x:Key="Dark"> |
|||
<SolidColorBrush x:Key="HomeCardBackground" Color="#2B2B33" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#3A3A45" /> |
|||
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#8AB4FF" /> |
|||
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#9C9CAB" /> |
|||
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#31395A" /> |
|||
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#8AB4FF" /> |
|||
<SolidColorBrush x:Key="HomeSectionDivider" Color="#3A3A45" /> |
|||
</ResourceDictionary> |
|||
</ResourceDictionary.ThemeDictionaries> |
|||
</ResourceDictionary> |
|||
</ContentPage.Resources> |
|||
|
|||
<ContentPage.Styles> |
|||
<!-- Neutralize the themed Button chrome so only the inner card Border shows. --> |
|||
<Style Selector="Button.card /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderBrush" Value="Transparent" /> |
|||
</Style> |
|||
<Style Selector="Button.card:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderBrush" Value="Transparent" /> |
|||
</Style> |
|||
<Style Selector="Button.card:pressed /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderBrush" Value="Transparent" /> |
|||
</Style> |
|||
<Style Selector="Button.card > Border"> |
|||
<Setter Property="Transitions"> |
|||
<Transitions> |
|||
<BrushTransition Property="BorderBrush" Duration="0:0:0.1" /> |
|||
</Transitions> |
|||
</Setter> |
|||
</Style> |
|||
<Style Selector="Button.card:pointerover > Border"> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource HomeCardBorderBrushHover}" /> |
|||
</Style> |
|||
</ContentPage.Styles> |
|||
|
|||
<StackPanel Spacing="28" Margin="0,0,15,20" HorizontalAlignment="Stretch"> |
|||
|
|||
<!-- Hero banner --> |
|||
<Border CornerRadius="16" ClipToBounds="True" Height="220" HorizontalAlignment="Stretch"> |
|||
<Border.Background> |
|||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%"> |
|||
<GradientStop Offset="0" Color="#6D28D9" /> |
|||
<GradientStop Offset="0.55" Color="#4338CA" /> |
|||
<GradientStop Offset="1" Color="#2563EB" /> |
|||
</LinearGradientBrush> |
|||
</Border.Background> |
|||
<Grid ClipToBounds="True"> |
|||
<!-- Floating control glyphs, animated from code-behind --> |
|||
<Canvas IsHitTestVisible="False"> |
|||
<PathIcon x:Name="FloatIcon1" |
|||
Data="{x:Static local:Icons.CursorClick}" |
|||
Foreground="#26FFFFFF" |
|||
Width="120" Height="120" |
|||
Canvas.Left="-30" Canvas.Bottom="-25" /> |
|||
<PathIcon x:Name="FloatIcon2" |
|||
Data="{x:Static local:Icons.Palette}" |
|||
Foreground="#21FFFFFF" |
|||
Width="96" Height="96" |
|||
Canvas.Left="200" Canvas.Top="-30" /> |
|||
<PathIcon x:Name="FloatIcon3" |
|||
Data="{x:Static local:Icons.Calendar}" |
|||
Foreground="#26FFFFFF" |
|||
Width="110" Height="110" |
|||
Canvas.Right="-25" Canvas.Top="-20" /> |
|||
<PathIcon x:Name="FloatIcon4" |
|||
Data="{x:Static local:Icons.Toggle}" |
|||
Foreground="#21FFFFFF" |
|||
Width="130" Height="130" |
|||
Canvas.Right="170" Canvas.Bottom="-40" /> |
|||
</Canvas> |
|||
<!-- Centered lockup --> |
|||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10"> |
|||
<Image Source="/Assets/Icon.png" Height="64" /> |
|||
<TextBlock Text="Avalonia Control Catalog" |
|||
FontSize="26" FontWeight="Bold" |
|||
Foreground="White" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Explore every control, on every platform, in every theme" |
|||
FontSize="13" |
|||
Foreground="#B3FFFFFF" |
|||
HorizontalAlignment="Center" /> |
|||
</StackPanel> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- Card sections --> |
|||
<ItemsControl ItemsSource="{Binding HomeSections}"> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate DataType="viewModels:HomeSection"> |
|||
<StackPanel Spacing="14" Margin="0,0,0,26"> |
|||
<TextBlock Text="{Binding Title}" |
|||
FontSize="19" FontWeight="Bold" /> |
|||
<ItemsControl ItemsSource="{Binding Items}"> |
|||
<ItemsControl.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<WrapPanel Orientation="Horizontal" /> |
|||
</ItemsPanelTemplate> |
|||
</ItemsControl.ItemsPanel> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate DataType="viewModels:PageItem"> |
|||
<Button Classes="card" |
|||
Command="{Binding $parent[ContentPage].((viewModels:MainWindowViewModel)DataContext).NavigateToPageCommand}" |
|||
CommandParameter="{Binding}" |
|||
Margin="0,0,12,12" |
|||
Padding="0" |
|||
Background="Transparent" |
|||
BorderThickness="0" |
|||
Cursor="Hand"> |
|||
<Border Background="{DynamicResource HomeCardBackground}" |
|||
BorderBrush="{DynamicResource HomeCardBorderBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="10" |
|||
Padding="16,14" |
|||
Width="248" |
|||
MinHeight="118" |
|||
BoxShadow="0 1 3 0 #0D000000"> |
|||
<StackPanel Spacing="10"> |
|||
<Border Background="{DynamicResource HomeBadgeBackground}" |
|||
CornerRadius="8" |
|||
Width="36" Height="36" |
|||
HorizontalAlignment="Left"> |
|||
<PathIcon Data="{Binding IconData}" |
|||
Foreground="{DynamicResource HomeBadgeForeground}" |
|||
Width="18" Height="18" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" /> |
|||
</Border> |
|||
<StackPanel Spacing="3"> |
|||
<TextBlock Text="{Binding Header}" |
|||
FontSize="14" FontWeight="SemiBold" /> |
|||
<TextBlock Text="{Binding Description}" |
|||
FontSize="12" |
|||
Foreground="{DynamicResource HomeSubtleForeground}" |
|||
TextWrapping="Wrap" |
|||
MaxLines="2" /> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</Border> |
|||
</Button> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</StackPanel> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
|
|||
</StackPanel> |
|||
</ContentPage> |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using Avalonia; |
|||
using Avalonia.Animation; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Media; |
|||
using Avalonia.Styling; |
|||
using Avalonia.VisualTree; |
|||
using ControlCatalog.ViewModels; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class HomePage : ContentPage |
|||
{ |
|||
public HomePage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
|||
{ |
|||
base.OnAttachedToVisualTree(e); |
|||
|
|||
// Pages hosted in a NavigationPage inherit the navigator as DataContext;
|
|||
// the card grid binds to MainWindowViewModel, so resolve it from MainView.
|
|||
if (DataContext is not MainWindowViewModel) |
|||
DataContext = this.FindAncestorOfType<MainView>()?.DataContext; |
|||
|
|||
StartFloatingAnimation(FloatIcon1, 12, 8, TimeSpan.FromSeconds(12)); |
|||
StartFloatingAnimation(FloatIcon2, -14, 8, TimeSpan.FromSeconds(10)); |
|||
StartFloatingAnimation(FloatIcon3, -12, -12, TimeSpan.FromSeconds(14)); |
|||
StartFloatingAnimation(FloatIcon4, 12, -8, TimeSpan.FromSeconds(11)); |
|||
} |
|||
|
|||
private static void StartFloatingAnimation(Control target, double dx, double dy, TimeSpan duration) |
|||
{ |
|||
var transform = new TranslateTransform(); |
|||
target.RenderTransform = transform; |
|||
|
|||
var animation = new Animation |
|||
{ |
|||
Duration = duration, |
|||
IterationCount = IterationCount.Infinite, |
|||
Children = |
|||
{ |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(0d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, 0d), |
|||
new Setter(TranslateTransform.YProperty, 0d), |
|||
} |
|||
}, |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(0.5d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, dx), |
|||
new Setter(TranslateTransform.YProperty, dy), |
|||
} |
|||
}, |
|||
new KeyFrame |
|||
{ |
|||
Cue = new Cue(1d), |
|||
Setters = |
|||
{ |
|||
new Setter(TranslateTransform.XProperty, 0d), |
|||
new Setter(TranslateTransform.YProperty, 0d), |
|||
} |
|||
}, |
|||
} |
|||
}; |
|||
|
|||
_ = animation.RunAsync(target); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue