Skip to content

Commit fadd08b

Browse files
authored
Merge pull request #2521 from Nexus-Mods/healthcheck-emptystate-tweaks
Updated Health Check UI empty state\diagnostic details.
2 parents 191d729 + 50a9940 commit fadd08b

File tree

13 files changed

+371
-100
lines changed

13 files changed

+371
-100
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Styles xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:pageHeader="using:NexusMods.App.UI.Controls.PageHeader"
4+
>
5+
6+
<Design.PreviewWith>
7+
<Border Padding="16">
8+
<pageHeader:PageHeader/>
9+
</Border>
10+
</Design.PreviewWith>
11+
12+
<!-- Control theme is located at src/Themes/NexusMods.Themes.NexusFluentDark/Resources/ControlThemes/PageHeaderControlTheme.axaml
13+
Default style is found here as well as the default template -->
14+
15+
</Styles>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using Avalonia;
2+
using Avalonia.Controls;
3+
using Avalonia.Controls.Primitives;
4+
using NexusMods.Icons;
5+
6+
namespace NexusMods.App.UI.Controls.PageHeader;
7+
8+
public class PageHeader : ContentControl
9+
{
10+
11+
/// <summary>
12+
/// Defines the Title property of the <see cref="PageHeader"/>.
13+
/// </summary>
14+
public static readonly StyledProperty<string?> TitleProperty = AvaloniaProperty.Register<PageHeader, string?>(nameof(Title), defaultValue: "Default Title");
15+
16+
/// <summary>
17+
/// Defines the Title property of the <see cref="PageHeader"/>.
18+
/// </summary>
19+
public static readonly StyledProperty<string?> DescriptionProperty = AvaloniaProperty.Register<PageHeader, string?>(nameof(Description), defaultValue: "This is the default description of the page.");
20+
21+
/// <summary>
22+
/// Defines the Title property of the <see cref="PageHeader"/>.
23+
/// </summary>
24+
public static readonly StyledProperty<IconValue?> IconProperty = AvaloniaProperty.Register<PageHeader, IconValue?>(nameof(Icon), defaultValue: IconValues.PictogramBox2);
25+
26+
/// <summary>
27+
/// Gets or sets the title text of the <see cref="PageHeader"/>.
28+
/// </summary>
29+
public string? Title
30+
{
31+
get => GetValue(TitleProperty);
32+
set => SetValue(TitleProperty, value);
33+
}
34+
/// <summary>
35+
/// Gets or sets the description text of the <see cref="PageHeader"/>.
36+
/// </summary>
37+
public string? Description
38+
{
39+
get => GetValue(DescriptionProperty);
40+
set => SetValue(DescriptionProperty, value);
41+
}
42+
43+
/// <summary>
44+
/// Gets or sets the icon of the <see cref="PageHeader"/>.
45+
/// </summary>
46+
public IconValue? Icon
47+
{
48+
get => GetValue(IconProperty);
49+
set => SetValue(IconProperty, value);
50+
}
51+
52+
private TextBlock? _titleText;
53+
private TextBlock? _descriptionText;
54+
private UnifiedIcon? _unifiedIcon;
55+
56+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
57+
{
58+
base.OnPropertyChanged(change);
59+
60+
if (change.Property == TitleProperty)
61+
{
62+
UpdateTitle(change.GetNewValue<string?>());
63+
}
64+
else if (change.Property == DescriptionProperty)
65+
{
66+
UpdateDescription(change.GetNewValue<string?>());
67+
}
68+
else if (change.Property == IconProperty)
69+
{
70+
UpdateIcon(change.GetNewValue<IconValue?>());
71+
}
72+
}
73+
74+
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
75+
{
76+
_titleText = e.NameScope.Find<TextBlock>("TitleTextBlock");
77+
if (_titleText != null)
78+
UpdateTitle(Title);
79+
80+
_descriptionText = e.NameScope.Find<TextBlock>("DescriptionTextBlock");
81+
if (_descriptionText != null)
82+
UpdateDescription(Description);
83+
84+
_unifiedIcon = e.NameScope.Find<UnifiedIcon>("Icon");
85+
if (_unifiedIcon != null)
86+
UpdateIcon(Icon);
87+
}
88+
89+
90+
/// <summary>
91+
/// Updates the visual title text of the <see cref="PageHeader"/>.
92+
/// </summary>
93+
/// <param name="newTitle">The new title text</param>
94+
private void UpdateTitle(string? newTitle)
95+
{
96+
if (_titleText != null)
97+
_titleText.Text = newTitle;
98+
}
99+
100+
/// <summary>
101+
/// Updates the visual title text of the <see cref="PageHeader"/>.
102+
/// </summary>
103+
/// <param name="newDescription">The new description text</param>
104+
private void UpdateDescription(string? newDescription)
105+
{
106+
if (_descriptionText != null)
107+
_descriptionText.Text = newDescription;
108+
}
109+
110+
/// <summary>
111+
/// Updates the visual icon of the <see cref="PageHeader"/>.
112+
/// </summary>
113+
/// <param name="newIcon">The new icon</param>
114+
private void UpdateIcon(IconValue? newIcon)
115+
{
116+
if (_unifiedIcon != null)
117+
_unifiedIcon.Value = newIcon;
118+
}
119+
}

src/NexusMods.App.UI/NexusMods.App.UI.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,10 @@
744744
<Compile Update="Pages\LoadoutPage\CollectionLoadoutDesignViewModel.cs">
745745
<DependentUpon>ICollectionLoadoutViewModel.cs</DependentUpon>
746746
</Compile>
747+
<Compile Update="Controls\PageHeader\PageHeader.axaml.cs">
748+
<DependentUpon>PageHeader.axaml</DependentUpon>
749+
<SubType>Code</SubType>
750+
</Compile>
747751
</ItemGroup>
748752

749753
<ItemGroup>

src/NexusMods.App.UI/Pages/Diagnostics/Details/DiagnosticDetailsView.axaml

+34-29
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,40 @@
2626
<DockPanel Margin="24">
2727

2828
<!-- header with pictogram -->
29-
<StackPanel Spacing="8" DockPanel.Dock="Top">
30-
31-
<StackPanel Orientation="Horizontal" Spacing="8">
32-
<Border Width="48" Height="48">
33-
<icons:UnifiedIcon Size="48" Value="{x:Static icons:IconValues.PictogramHealth}" />
34-
</Border>
35-
<TextBlock Text="Health Check:"
36-
Theme="{StaticResource HeadingSMSemiTheme}"
29+
<DockPanel DockPanel.Dock="Top">
30+
<Border Width="60"
31+
Height="60"
32+
Margin="0,0,8,0"
33+
DockPanel.Dock="Left"
34+
VerticalAlignment="Top">
35+
<icons:UnifiedIcon Size="60" x:Name="Icon" Value="{x:Static icons:IconValues.PictogramHealth}" />
36+
</Border>
37+
38+
<StackPanel Orientation="Vertical" VerticalAlignment="Top">
39+
<StackPanel Orientation="Horizontal" Spacing="8">
40+
<TextBlock x:Name="TitleTextBlock"
41+
Text="Health Check:"
42+
Theme="{StaticResource HeadingSMSemiTheme}"
43+
Foreground="{StaticResource NeutralStrongBrush}"
44+
VerticalAlignment="Center"
45+
TextWrapping="Wrap" />
46+
<TextBlock x:Name="SeverityTitleTextBlock"
47+
Theme="{StaticResource HeadingSMSemiTheme}"
48+
VerticalAlignment="Center" />
49+
</StackPanel>
50+
<TextBlock x:Name="DescriptionTextBlock"
51+
Text="Review your Loadout for any issues and learn how to resolve them if needed."
52+
Theme="{StaticResource BodyMDNormalTheme}"
3753
Foreground="{StaticResource NeutralStrongBrush}"
38-
VerticalAlignment="Center" />
39-
<TextBlock x:Name="SeverityTitleTextBlock"
40-
Theme="{StaticResource HeadingSMSemiTheme}"
41-
VerticalAlignment="Center" />
54+
TextWrapping="Wrap" />
4255
</StackPanel>
56+
</DockPanel>
4357

44-
<TextBlock
45-
x:Name="SeverityExplanationTextBlock"
46-
Text="Review your Loadout for any issues and learn how to resolve them if needed."
47-
Theme="{StaticResource BodyMDNormalTheme}"
48-
Foreground="{StaticResource NeutralStrongBrush}"
49-
TextWrapping="Wrap" />
50-
</StackPanel>
51-
52-
<Border DockPanel.Dock="Top" Classes="Toolbar"
53-
Background="Transparent"
58+
<Border DockPanel.Dock="Top" Classes="Toolbar"
59+
Background="Transparent"
5460
BorderThickness="0">
55-
56-
<StackPanel HorizontalAlignment="Left"
61+
62+
<StackPanel HorizontalAlignment="Left"
5763
Margin="0,20,0,0">
5864
<controls:StandardButton x:Name="SwitchView"
5965
Text="Back"
@@ -62,7 +68,7 @@
6268
Fill="Weak"
6369
ShowIcon="Left"
6470
LeftIcon="{x:Static icons:IconValues.ArrowBack}"
65-
IsEnabled="False"/>
71+
IsEnabled="False" />
6672

6773
<controls:StandardButton x:Name="DeleteButton"
6874
Type="Tertiary"
@@ -71,22 +77,21 @@
7177
ShowIcon="Left"
7278
ShowLabel="False"
7379
LeftIcon="{x:Static icons:IconValues.Copy}"
74-
IsEnabled="False"/>
80+
IsEnabled="False" />
7581
</StackPanel>
7682
</Border>
7783

7884
<Border
7985
x:Name="MarkdownWrapperBorder"
86+
VerticalAlignment="Top"
8087
Margin="0,12,0,0"
8188
CornerRadius="4"
8289
BorderThickness="2"
8390
Padding="24"
8491
Background="#0D93C5FD"
8592
BorderBrush="#6693C5FD">
8693

87-
88-
<reactiveUi:ViewModelViewHost x:Name="MarkdownRendererViewModelViewHost" />
89-
94+
<reactiveUi:ViewModelViewHost x:Name="MarkdownRendererViewModelViewHost" />
9095
</Border>
9196

9297
</DockPanel>

src/NexusMods.App.UI/Pages/Diagnostics/Details/DiagnosticDetailsView.axaml.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,20 @@ private void InitializeData(IDiagnosticDetailsViewModel vm)
4040
case DiagnosticSeverity.Suggestion:
4141
SeverityTitleTextBlock.Text = Language.DiagnosticDetailsView_SeverityTitle_SUGGESTION;
4242
SeverityTitleTextBlock.Classes.Add("ForegroundInfoStrong");
43-
SeverityExplanationTextBlock.Text = "Suggestions may offer improvements to your experience.";
43+
DescriptionTextBlock.Text = "Suggestions may offer improvements to your experience.";
4444
MarkdownWrapperBorder.Background = SolidColorBrush.Parse("#0D93C5FD");
4545
MarkdownWrapperBorder.BorderBrush = SolidColorBrush.Parse("#6693C5FD");
4646
break;
4747
case DiagnosticSeverity.Warning:
4848
SeverityTitleTextBlock.Text = Language.DiagnosticDetailsView_SeverityTitle_WARNING;
4949
SeverityTitleTextBlock.Classes.Add("ForegroundWarningStrong");
50-
SeverityExplanationTextBlock.Text = "Warnings may negatively impact your experience.";
50+
DescriptionTextBlock.Text = "Warnings may negatively impact your experience.";
5151
MarkdownWrapperBorder.Background = SolidColorBrush.Parse("#0DFEF08A");
5252
MarkdownWrapperBorder.BorderBrush = SolidColorBrush.Parse("#66FEF08A");
5353
break;
5454
case DiagnosticSeverity.Critical:
5555
SeverityTitleTextBlock.Text = Language.DiagnosticDetailsView_SeverityTitle_CRITICAL_ERROR;
56-
SeverityExplanationTextBlock.Text = "Critical errors make the game unplayable.";
56+
DescriptionTextBlock.Text = "Critical errors make the game unplayable.";
5757
SeverityTitleTextBlock.Classes.Add("ForegroundDangerStrong");
5858
MarkdownWrapperBorder.Background = SolidColorBrush.Parse("#0DF87171");
5959
MarkdownWrapperBorder.BorderBrush = SolidColorBrush.Parse("#66F87171");

src/NexusMods.App.UI/Pages/Diagnostics/List/DiagnosticListView.axaml

+63-21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
xmlns:icons="clr-namespace:NexusMods.Icons;assembly=NexusMods.Icons"
1111
xmlns:resources="clr-namespace:NexusMods.App.UI.Resources"
1212
xmlns:diagnostics="clr-namespace:NexusMods.App.UI.Controls.Diagnostics"
13+
xmlns:pageHeader="clr-namespace:NexusMods.App.UI.Controls.PageHeader"
1314
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="500"
1415
x:Class="NexusMods.App.UI.Pages.Diagnostics.DiagnosticListView">
1516

@@ -47,30 +48,71 @@
4748
<!-- need DockPanel to make the TabControl fill the available space, needed for ScrollViewer to calculate height properly -->
4849
<DockPanel Margin="24">
4950

50-
<!-- header with pictogram -->
51-
<StackPanel Spacing="8" DockPanel.Dock="Top">
51+
<pageHeader:PageHeader DockPanel.Dock="Top"
52+
Title="{x:Static resources:Language.DiagnosticListView_Page_Title}"
53+
Description="{x:Static resources:Language.DiagnosticListView_Page_Description}"
54+
Icon="{x:Static icons:IconValues.PictogramHealth}"/>
5255

53-
<StackPanel Orientation="Horizontal" Spacing="8">
54-
<Border Width="48" Height="48">
55-
<icons:UnifiedIcon Size="48" Value="{x:Static icons:IconValues.PictogramHealth}" />
56-
</Border>
57-
<TextBlock Text="Health Check"
58-
Theme="{StaticResource HeadingSMSemiTheme}"
59-
Foreground="{StaticResource NeutralStrongBrush}"
60-
VerticalAlignment="Center" />
61-
</StackPanel>
56+
<controls:EmptyState x:Name="EmptyState"
57+
Margin="0"
58+
Padding="0"
59+
HorizontalAlignment="Stretch"
60+
VerticalAlignment="Top">
6261

63-
<TextBlock
64-
Text="Review your Loadout for any issues and learn how to resolve them if needed."
65-
Theme="{StaticResource BodyMDNormalTheme}"
66-
Foreground="{StaticResource NeutralStrongBrush}"
67-
TextWrapping="Wrap" />
68-
</StackPanel>
62+
<controls:EmptyState.Styles>
63+
<Style Selector="controls|EmptyState">
64+
<Setter Property="Template">
65+
<ControlTemplate>
66+
<Grid>
67+
<Border x:Name="EmptyStateBorder">
68+
<ContentPresenter x:Name="SubtitleContentPresenter"
69+
Content="{TemplateBinding Subtitle}" />
70+
</Border>
71+
<ContentPresenter Grid.Column="0" Grid.Row="0" x:Name="ContentPresenter"
72+
Content="{TemplateBinding Content}" />
73+
</Grid>
74+
</ControlTemplate>
75+
</Setter>
76+
</Style>
6977

70-
<controls:EmptyState x:Name="EmptyState"
71-
Icon="{x:Static icons:IconValues.CheckCircle}"
72-
Header="{x:Static resources:Language.DiagnosticListView_EmptyState_Header}"
73-
Subtitle="{x:Static resources:Language.DiagnosticListView_EmptyState_Subtitle}">
78+
<Style Selector="Border#EmptyStateBorder">
79+
<Setter Property="HorizontalAlignment" Value="Stretch" />
80+
<Setter Property="Padding" Value="0" />
81+
<Setter Property="Margin" Value="0" />
82+
</Style>
83+
</controls:EmptyState.Styles>
84+
85+
<controls:EmptyState.Subtitle>
86+
<Border
87+
VerticalAlignment="Top"
88+
Margin="0,16,0,0"
89+
CornerRadius="4"
90+
BorderThickness="2"
91+
Padding="24"
92+
Background="#0D86EFAC"
93+
BorderBrush="#6686EFAC">
94+
95+
<StackPanel Orientation="Vertical" Spacing="8">
96+
<DockPanel>
97+
<icons:UnifiedIcon Value="{x:Static icons:IconValues.CheckCircle}"
98+
Size="20"
99+
Foreground="{StaticResource SuccessStrongBrush}"
100+
DockPanel.Dock="Left"
101+
Margin="0,0,6,0" />
102+
<TextBlock
103+
Theme="{StaticResource HeadingXSSemiTheme}"
104+
Foreground="{StaticResource NeutralTranslucentStrongBrush}"
105+
Text="Your loadout passed the health check with no issues"
106+
TextWrapping="Wrap" />
107+
</DockPanel>
108+
<TextBlock
109+
Theme="{StaticResource BodyLGNormalTheme}"
110+
Foreground="{StaticResource NeutralSubduedBrush}"
111+
Text="Ready for gaming"
112+
TextWrapping="Wrap" />
113+
</StackPanel>
114+
</Border>
115+
</controls:EmptyState.Subtitle>
74116

75117
<TabControl x:Name="TabControl"
76118
Margin="0,24,0,0"

0 commit comments

Comments
 (0)