From 6d2bb95528dee9f303c036e0023812e36c989125 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 19 Aug 2026 09:44:31 +0200 Subject: [PATCH] feat(style): name the four type roles Body, Sender, Header, Meta. Three of them share the base size, which looks like an oversight and is not: the sender is set apart by weight and the header by small caps with wide tracking. Neither of those is a size, and solving them with size instead would turn the log into a ransom note. Only meta steps down, because it is meant to be skipped over rather than read. Factors sit in a static array rather than as consts. The master spec puts typography under theme control, and ThemeTypography is already the declared extension point for it -- a const would wall that off before anyone gets there. No caller yet. FontManager takes the first one in the next commit; that is the one place in this cycle where a piece lands before its call site, and it closes inside the same block. --- HellionChat/Ui/StyleEngine/TypeScale.cs | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 HellionChat/Ui/StyleEngine/TypeScale.cs diff --git a/HellionChat/Ui/StyleEngine/TypeScale.cs b/HellionChat/Ui/StyleEngine/TypeScale.cs new file mode 100644 index 0000000..ca8f3a5 --- /dev/null +++ b/HellionChat/Ui/StyleEngine/TypeScale.cs @@ -0,0 +1,42 @@ +namespace HellionChat.Ui.StyleEngine; + +internal enum TypeRole +{ + Body, + Sender, + Header, + Meta, +} + +// Named sizes derived from one base, so a role means the same thing wherever it +// is drawn. +// +// Three of the four share the base size. That is deliberate: what sets the +// sender apart is weight and what sets the header apart is small caps with wide +// tracking, and neither is a size. Solving those with size instead would make +// the log look like a ransom note. Only the meta role -- timestamps and the +// header's trailing detail -- steps down, because it is meant to be skipped over +// rather than read. +// +// The factors are defaults, not constants. The master spec puts typography under +// theme control rather than user control, and ThemeTypography already exists as +// the extension point for exactly that. A const would wall it off. What is +// deliberately absent either way is a user-facing slider per role. +internal static class TypeScale +{ + // Below this a timestamp stops being readable at any display scale. + internal const float MinPt = 7f; + + private static readonly float[] Factors = + [ + 1.00f, // Body -- the reference every other role is stated against + 1.00f, // Sender -- set apart by weight, see FontManager.SenderWeight + 1.00f, // Header -- set apart by small caps and tracking + 0.82f, // Meta -- timestamps, and the world and clock in the header + ]; + + internal static float FactorOf(TypeRole role) => Factors[(int)role]; + + internal static float SizePtOf(TypeRole role, float basePt) => + TypeScaleMath.Resolve(basePt, FactorOf(role), MinPt); +}