design: every window inherits Inter (implicit Window style)
Dialogs are separate WPF windows, so the FontFamily set on MainWindow never reached them — GoLive, Socials and the four pickers still rendered Segoe UI while the main window used Inter. The theme now carries an implicit Window style (family + Display text mode + layout rounding). Guard: DialogTypographyTests opens a real Window inside the real app and asserts it resolves the bundled Inter family — which fails if the style or the font resource goes missing — and asserts no dialog sets FontFamily itself, i.e. nobody opts out of the standard.
This commit is contained in:
@@ -2,6 +2,16 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:Helpers="clr-namespace:ytLive.Helpers">
|
||||
|
||||
<!-- Typography for every window: dialogs are separate WPF windows, so FontFamily set on
|
||||
MainWindow does not reach them. This implicit style is the one place that does — a
|
||||
dialog inherits Inter without setting anything, and the design standard holds for every
|
||||
surface the creator can open. -->
|
||||
<Style TargetType="Window">
|
||||
<Setter Property="FontFamily" Value="{StaticResource FontFamily.Sans}"/>
|
||||
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
|
||||
<Setter Property="UseLayoutRounding" Value="True"/>
|
||||
</Style>
|
||||
|
||||
<!-- Base button style -->
|
||||
<Style x:Key="YtButton" TargetType="Button">
|
||||
<Setter Property="Background" Value="{StaticResource Brush.Tertiary}"/>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Xunit;
|
||||
|
||||
namespace ytLive.Tests;
|
||||
|
||||
/// <summary>DESIGN.md names Inter for all UI text, but a dialog is a SEPARATE WPF window: the
|
||||
/// FontFamily set on MainWindow never reaches it, so every dialog still rendered Segoe UI while
|
||||
/// the main window had moved on (found 2026-10-30).
|
||||
///
|
||||
/// <para>The theme now carries an implicit <c>Window</c> style. This test proves the mechanism on
|
||||
/// a real window inside the real app — which is what catches a missing resource or a broken
|
||||
/// implicit-style lookup — and asserts no dialog opts out by setting FontFamily itself.</para></summary>
|
||||
[Collection("RealApp")]
|
||||
public class DialogTypographyTests
|
||||
{
|
||||
private readonly RealAppHost _app;
|
||||
|
||||
public DialogTypographyTests(RealAppHost app) => _app = app;
|
||||
|
||||
[Fact]
|
||||
public void A_window_inherits_the_standard_typeface_and_no_dialog_opts_out()
|
||||
{
|
||||
// 1. The mechanism: any Window opened in the app resolves the token family. Dialogs are
|
||||
// Windows; proving it once here covers all of them, and it fails if the implicit style
|
||||
// or the font resource ever goes missing.
|
||||
_app.Run(() =>
|
||||
{
|
||||
var window = new Window();
|
||||
window.Show();
|
||||
try
|
||||
{
|
||||
Assert.Contains("Inter", window.FontFamily?.Source ?? string.Empty,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
finally { window.Close(); }
|
||||
});
|
||||
|
||||
// 2. Opt-outs: a dialog that sets FontFamily itself would silently leave the standard.
|
||||
foreach (var file in DialogFiles())
|
||||
Assert.DoesNotContain("FontFamily=", File.ReadAllText(file));
|
||||
}
|
||||
|
||||
private static IEnumerable<string> DialogFiles()
|
||||
{
|
||||
var root = Path.GetDirectoryName(SourceAssert.RepoPath("App.xaml"))!;
|
||||
return Directory.EnumerateFiles(root, "*.xaml", SearchOption.AllDirectories)
|
||||
.Where(p => !p.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
&& !p.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
&& !p.Contains("ytLive.Tests", StringComparison.Ordinal))
|
||||
.Where(p => Path.GetFileName(p).Contains("Dialog", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(p).StartsWith("GoLiveWindow", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user