Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0fba433
Lock P0 visual system unification contracts
masarray Aug 17, 2026
69fcb00
Add deterministic P0 visual system patch
masarray Aug 17, 2026
85e017c
Run deterministic P0 visual system patch
masarray Aug 17, 2026
335158c
Unify P0 workspace visual system
github-actions[bot] Aug 17, 2026
778aed8
Add temporary P0 review-fix helper
masarray Aug 17, 2026
2bfe1a3
Run P0 review fixes
masarray Aug 17, 2026
a5780d1
Fix P0 visual review findings
github-actions[bot] Aug 17, 2026
f22631d
Remove temporary P0 review workflow
masarray Aug 17, 2026
8e6203e
Remove temporary P0 visual workflow
masarray Aug 17, 2026
f13731a
Remove temporary P0 review helper
masarray Aug 17, 2026
633676c
Remove temporary P0 visual helper
masarray Aug 17, 2026
e1d8d54
Add temporary helper to update P0 build guard
masarray Aug 17, 2026
0841639
Run deterministic P0 build guard update
masarray Aug 17, 2026
cd47d8f
Fix P0 build guard helper matching
masarray Aug 17, 2026
b955950
Add temporary helper to align P0 responsive nav bootstrap
masarray Aug 17, 2026
58d5468
Run P0 responsive bootstrap alignment
masarray Aug 17, 2026
a09f7a7
Align P0 nav bootstrap with responsive authority
github-actions[bot] Aug 17, 2026
4350398
Remove temporary P0 build guard workflow
masarray Aug 17, 2026
cacdb76
Remove temporary P0 build guard helper
masarray Aug 17, 2026
4522560
Remove temporary P0 responsive bootstrap workflow
masarray Aug 17, 2026
3cca07c
Remove temporary P0 responsive bootstrap helper
masarray Aug 17, 2026
9dcb065
Align state-color regression wording with P0 compact header
masarray Aug 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 54 additions & 14 deletions App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,33 +189,64 @@
</Setter>
</Style>

<!-- Compact P2 typography scale: restrained sizes for dense engineering workstations. -->
<!-- P0 workstation typography: five levels only for fast engineering scan paths. -->
<Style x:Key="WorkspaceTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{StaticResource Ink}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<Style x:Key="WorkspaceSubtitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Foreground" Value="{StaticResource Muted}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<Style x:Key="SectionTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{StaticResource Ink}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<Style x:Key="BodyText" TargetType="TextBlock">
<Setter Property="FontSize" Value="12.2"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{StaticResource Ink}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<Style x:Key="Caption" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Muted}"/>
<Setter Property="FontSize" Value="11.8"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<Style x:Key="MicroLabel" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Muted}"/>
<Setter Property="FontSize" Value="10.6"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>

<!-- Main-window workspace surfaces deliberately avoid card shadows. The data is the hierarchy. -->
<Style x:Key="WorkspaceCard" TargetType="Border">
<Setter Property="Background" Value="{StaticResource PremiumSurface}"/>
<Setter Property="CornerRadius" Value="12"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderSubtle}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Effect" Value="{x:Null}"/>
</Style>

<Style x:Key="SearchSurface" TargetType="Border">
<Setter Property="Height" Value="36"/>
<Setter Property="Background" Value="#F8FAFC"/>
<Setter Property="BorderBrush" Value="#D7E1EE"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
</Style>

<Style x:Key="PrimaryButton" TargetType="Button">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="{StaticResource AccentGradient}"/>
Expand Down Expand Up @@ -577,23 +608,31 @@
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontSize" Value="12.5"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid SnapsToDevicePixels="True">
<!-- Transparent hit target only. The visible chrome is the animated sliding pill behind it. -->
<Border Background="Transparent" CornerRadius="18" Margin="2"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True" TextElement.Foreground="{TemplateBinding Foreground}"/>
<Border Background="Transparent" CornerRadius="10" Margin="2"/>
<Border x:Name="KeyboardFocusRing" Margin="2" CornerRadius="10"
BorderBrush="#7EA9EA" BorderThickness="1.5" Opacity="0"
IsHitTestVisible="False"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
RecognizesAccessKey="True"
TextElement.Foreground="{TemplateBinding Foreground}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontSize" Value="13.45"/>
<Setter Property="Foreground" Value="#344054"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="FontSize" Value="12.55"/>
<Setter Property="Opacity" Value="0.82"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="KeyboardFocusRing" Property="Opacity" Value="1"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.45"/>
Expand Down Expand Up @@ -734,18 +773,19 @@
<Setter Property="CanUserSortColumns" Value="True"/>
<Setter Property="CanUserAddRows" Value="False"/>
<Setter Property="CanUserDeleteRows" Value="False"/>
<Setter Property="RowHeight" Value="34"/>
<Setter Property="RowHeight" Value="32"/>
<Setter Property="ColumnHeaderHeight" Value="34"/>
<Setter Property="AlternatingRowBackground" Value="#F5F8FD"/>
<Setter Property="FontSize" Value="12.5"/>
<Setter Property="FontSize" Value="12.2"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>

<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="#F1F5F9"/>
<Setter Property="Foreground" Value="#475467"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Padding" Value="10,0"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="9,0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderBrush" Value="{StaticResource Line}"/>
Expand Down
36 changes: 27 additions & 9 deletions GridUxBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ private sealed class GlobalRapidFilterState
public required ICollectionView View { get; init; }
public required DispatcherTimer RefreshTimer { get; init; }
public Dictionary<string, string> Filters { get; } = new(StringComparer.OrdinalIgnoreCase);
public List<Grid> HeaderRoots { get; } = new();
public string SearchQuery { get; set; } = string.Empty;
public bool FiltersExpanded { get; set; }
}

private static readonly ConditionalWeakTable<MainWindow, MainWindowState> MainWindows = new();
Expand Down Expand Up @@ -494,9 +496,8 @@ private static void InstallGlobalRapidFilters(MainWindow owner, DataGrid grid)
headerStyle.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Color.FromRgb(243, 246, 250))));
headerStyle.Setters.Add(new Setter(Control.BorderBrushProperty, new SolidColorBrush(Color.FromRgb(220, 227, 236))));
headerStyle.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0, 0, 1, 1)));
headerStyle.Setters.Add(new Setter(FrameworkElement.HeightProperty, 74d));
grid.ColumnHeaderStyle = headerStyle;
grid.ColumnHeaderHeight = 74;
grid.ColumnHeaderHeight = 34;

foreach (var column in grid.Columns)
{
Expand All @@ -515,6 +516,22 @@ internal static void SetGlobalRapidSearch(DataGrid grid, string? query)
state.RefreshTimer.Start();
}

internal static void SetGlobalRapidFiltersExpanded(DataGrid grid, bool expanded)
{
if (!GlobalGrids.TryGetValue(grid, out var state))
return;

state.FiltersExpanded = expanded;
foreach (var root in state.HeaderRoots)
{
if (root.RowDefinitions.Count < 2)
continue;
root.RowDefinitions[1].Height = expanded ? new GridLength(34) : new GridLength(0);
}
grid.ColumnHeaderHeight = expanded ? 68 : 34;
grid.UpdateLayout();
}

private static void ApplyGlobalColumnStretch(DataGrid grid)
{
var layout = new Dictionary<string, (double Weight, double Minimum)>(StringComparer.OrdinalIgnoreCase)
Expand Down Expand Up @@ -553,16 +570,16 @@ private static FrameworkElement BuildRapidFilterHeader(GlobalRapidFilterState st
Source = column,
Mode = BindingMode.OneWay
});
root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(38) });
root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(36) });
root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(34) });
root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(0) });

var title = new TextBlock
{
Text = caption,
Margin = new Thickness(10, 0, 8, 0),
Foreground = new SolidColorBrush(Color.FromRgb(52, 64, 84)),
FontWeight = FontWeights.SemiBold,
FontSize = 12.5,
FontSize = 12.0,
VerticalAlignment = VerticalAlignment.Center,
TextTrimming = TextTrimming.CharacterEllipsis
};
Expand All @@ -572,6 +589,7 @@ private static FrameworkElement BuildRapidFilterHeader(GlobalRapidFilterState st
var filterBox = CreateRapidFilterTextBox(state, caption);
Grid.SetRow(filterBox, 1);
root.Children.Add(filterBox);
state.HeaderRoots.Add(root);

return root;
}
Expand All @@ -581,9 +599,9 @@ private static TextBox CreateRapidFilterTextBox(GlobalRapidFilterState state, st
var box = new TextBox
{
Tag = key,
Height = 36,
Padding = new Thickness(10, 0, 7, 0),
FontSize = 12.5,
Height = 34,
Padding = new Thickness(9, 0, 7, 0),
FontSize = 12.0,
FontWeight = FontWeights.Normal,
Foreground = new SolidColorBrush(Color.FromRgb(29, 41, 57)),
CaretBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235)),
Expand Down Expand Up @@ -667,7 +685,7 @@ private static ControlTemplate BuildRapidFilterTextBoxTemplate()
watermark.SetValue(TextBlock.TextProperty, "Filter…");
watermark.SetValue(FrameworkElement.MarginProperty, new Thickness(10, 0, 7, 0));
watermark.SetValue(TextBlock.ForegroundProperty, new SolidColorBrush(Color.FromRgb(152, 162, 179)));
watermark.SetValue(TextBlock.FontSizeProperty, 12.5d);
watermark.SetValue(TextBlock.FontSizeProperty, 12.0d);
watermark.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
watermark.SetValue(UIElement.IsHitTestVisibleProperty, false);
watermark.SetValue(UIElement.VisibilityProperty, Visibility.Collapsed);
Expand Down
10 changes: 10 additions & 0 deletions MainWindow.GlobalLiveSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace ArIED61850Tester;

public partial class MainWindow
{
private bool _globalLiveFiltersExpanded;

private void GlobalLiveSearch_TextChanged(object sender, TextChangedEventArgs e)
=> GridUxBehavior.SetGlobalRapidSearch(GlobalLiveGrid, GlobalLiveSearchBox?.Text);

Expand All @@ -16,4 +18,12 @@ private void GlobalLiveSearchClear_Click(object sender, RoutedEventArgs e)
GlobalLiveSearchBox.Clear();
GlobalLiveSearchBox.Focus();
}

private void GlobalLiveFilters_Click(object sender, RoutedEventArgs e)
{
_globalLiveFiltersExpanded = !_globalLiveFiltersExpanded;
GridUxBehavior.SetGlobalRapidFiltersExpanded(GlobalLiveGrid, _globalLiveFiltersExpanded);
if (GlobalLiveFiltersLabel != null)
GlobalLiveFiltersLabel.Text = _globalLiveFiltersExpanded ? "Hide filters" : "Filters";
}
}
Loading
Loading