ui(properties): no raw typography left in the panel, and one heading rank
The earlier pass checked wiring only; this is the typography sweep. Raw Foreground/FontSize labels are gone from the elements panel: - Opacity, Timer (minutes) and URI are headings above their control (PropertyHeader), with the control row on the panel's 10px indent — the same shape as Border Thickness/Opacity. - Scroll speed, scoreboard Opacity/Text size and their value readouts are PropertyFieldLabel. - The drag hint and the scoreboard sign-in note are PropertyHint. - Simulate (dev) keeps its orange, gains the field-label typography. - Edge, Text colour and Background were PropertySubHeader/SubHeader: ONE heading rank now, so PropertySubHeader and the legacy SubHeader are deleted from Themes/Controls.xaml. - DeveloperPanel — the last panel with raw typography and an unstyled CheckBox — now uses the same styles, and PropertiesStyleTests accepts PropertyPillCheck (the guard went stale when every check box became a pill switch). 18 tests pass; Release 0 warnings.
This commit is contained in:
@@ -7,15 +7,15 @@
|
||||
to a window or reference it from code that compiles in Release; the only host is
|
||||
OverlayHost.xaml.cs inside #if DEBUG. -->
|
||||
<StackPanel>
|
||||
<TextBlock Text="Developer" Foreground="{StaticResource Brush.Attention}" FontSize="11"
|
||||
FontWeight="SemiBold" Margin="0,10,0,2"/>
|
||||
<TextBlock Text="Developer" Style="{StaticResource PropertyHeader}"
|
||||
Foreground="{StaticResource Brush.Attention}"/>
|
||||
|
||||
<CheckBox Margin="10,2,0,0" IsChecked="{Binding DeveloperMode, Mode=TwoWay}"
|
||||
Foreground="{StaticResource Brush.OnSurface}"
|
||||
<CheckBox Style="{StaticResource PropertyPillCheck}" Margin="10,2,0,0"
|
||||
IsChecked="{Binding DeveloperMode, Mode=TwoWay}"
|
||||
Content="Developer mode — all resolutions, output budget ignored"/>
|
||||
|
||||
<TextBlock Text="Debug builds only. Overrides the free output profile (921,600 px / 30 fps). Never present in a release build."
|
||||
Foreground="{StaticResource Brush.Attention}" FontSize="10" TextWrapping="Wrap"
|
||||
Style="{StaticResource PropertyHint}" Foreground="{StaticResource Brush.Attention}"
|
||||
Margin="10,4,0,8"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
+24
-26
@@ -315,10 +315,10 @@
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsDraggable, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsChatBox, Converter={StaticResource InverseBoolToVis}}">
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsBlur, Converter={StaticResource InverseBoolToVis}}">
|
||||
<TextBlock Text="Opacity" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel Margin="0,0,0,6">
|
||||
<TextBlock x:Name="OpacityValueText" Text="100%" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11"
|
||||
DockPanel.Dock="Right" VerticalAlignment="Center" Margin="8,0,0,0" Width="32"/>
|
||||
<TextBlock Text="Opacity" Style="{StaticResource PropertyHeader}"/>
|
||||
<DockPanel Margin="10,0,0,6">
|
||||
<TextBlock x:Name="OpacityValueText" Text="100%" Style="{StaticResource PropertyFieldLabel}"
|
||||
DockPanel.Dock="Right" Margin="8,0,0,0" Width="32"/>
|
||||
<Slider x:Name="OpacitySlider" Width="120" Minimum="0" Maximum="1"
|
||||
Value="{Binding SelectedElement.Opacity, Mode=TwoWay}"
|
||||
ValueChanged="OpacitySlider_ValueChanged" VerticalAlignment="Center"/>
|
||||
@@ -375,7 +375,7 @@
|
||||
<!-- The drag hint sits under the shape row — indented, so the
|
||||
parentage shows. -->
|
||||
<TextBlock Text="Drag to move · drag the corner dot to resize"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="10" Margin="10,2,0,0"/>
|
||||
Style="{StaticResource PropertyHint}" Margin="10,2,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Webcam geometry (TASK 57): under the vertical tier the camera
|
||||
@@ -490,7 +490,7 @@
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsScoreboard, Converter={StaticResource BoolToVis}}"
|
||||
IsEnabled="{Binding CanUseScoreboard}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Sign in to YouTube to use the scoreboard."
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,4"
|
||||
Style="{StaticResource PropertyHint}" Margin="0,0,0,4"
|
||||
Visibility="{Binding CanUseScoreboard, Converter={StaticResource InverseBoolToVis}}"/>
|
||||
<!-- DEBUG builds only: prove the strip in the preview before a real
|
||||
stream. Absent from Release, not merely hidden by a flag. -->
|
||||
@@ -500,21 +500,21 @@
|
||||
Visibility="{Binding IsDevelopmentBuild, Converter={StaticResource BoolToVis}}">
|
||||
<!-- Dev-only affordances wear orange so a development control can never
|
||||
be mistaken for product. -->
|
||||
<TextBlock Text="Simulate (dev)" Foreground="{StaticResource Brush.Attention}" FontSize="12"/>
|
||||
<TextBlock Text="Simulate (dev)" Style="{StaticResource PropertyFieldLabel}"
|
||||
Foreground="{StaticResource Brush.Attention}"/>
|
||||
</CheckBox>
|
||||
<CheckBox Style="{StaticResource PropertyPillCheck}" Margin="0,0,0,4"
|
||||
Content="Show the scoreboard" IsChecked="{Binding ScoreboardEnabled, Mode=TwoWay}"
|
||||
ToolTip="Off hides the strip in every scene AND stops the channel polling."/>
|
||||
<TextBlock Text="Edge (socials take the other)" Style="{StaticResource PropertySubHeader}"/>
|
||||
<TextBlock Text="Edge (socials take the other)" Style="{StaticResource PropertyHeader}"/>
|
||||
<ComboBox Style="{StaticResource YtComboBox}" Height="24" FontSize="11" Margin="10,0,0,6"
|
||||
ItemsSource="{Binding ScoreboardEdgeOptions}"
|
||||
SelectedItem="{Binding ScoreboardEdge, Mode=TwoWay}"/>
|
||||
|
||||
<DockPanel Margin="10,0,0,6">
|
||||
<TextBlock DockPanel.Dock="Left" Text="Scroll speed" Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
FontSize="11" Width="76" VerticalAlignment="Center"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="11"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"
|
||||
<TextBlock DockPanel.Dock="Left" Text="Scroll speed" Style="{StaticResource PropertyFieldLabel}" Width="76"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right"
|
||||
Style="{StaticResource PropertyFieldLabel}"
|
||||
Text="{Binding ScoreboardScrollSpeed, StringFormat={}{0:0} px/s}"/>
|
||||
<Slider Minimum="20" Maximum="200" SmallChange="10" LargeChange="40"
|
||||
Value="{Binding ScoreboardScrollSpeed, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
@@ -540,7 +540,7 @@
|
||||
IsChecked="{Binding ScoreboardShowLastGift, Mode=TwoWay}"/>
|
||||
</WrapPanel>
|
||||
|
||||
<TextBlock Text="Text colour" Style="{StaticResource PropertySubHeader}"/>
|
||||
<TextBlock Text="Text colour" Style="{StaticResource PropertyHeader}"/>
|
||||
<ComboBox Style="{StaticResource YtComboBox}" Height="24" FontSize="11" Margin="10,0,0,6"
|
||||
ItemsSource="{Binding ScoreboardColorOptions}" DisplayMemberPath="Name"
|
||||
SelectedValuePath="Hex" SelectedValue="{Binding ScoreboardTextColor, Mode=TwoWay}"/>
|
||||
@@ -551,20 +551,18 @@
|
||||
ItemsSource="{Binding ScoreboardColorOptions}" DisplayMemberPath="Name"
|
||||
SelectedValuePath="Hex" SelectedValue="{Binding ScoreboardBackgroundColor, Mode=TwoWay}"/>
|
||||
<DockPanel Margin="10,0,0,6">
|
||||
<TextBlock DockPanel.Dock="Left" Text="Opacity" Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
FontSize="11" Width="60" VerticalAlignment="Center"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="42" TextAlignment="Right" FontSize="11"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"
|
||||
<TextBlock DockPanel.Dock="Left" Text="Opacity" Style="{StaticResource PropertyFieldLabel}" Width="60"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="42" TextAlignment="Right"
|
||||
Style="{StaticResource PropertyFieldLabel}"
|
||||
Text="{Binding ScoreboardBackgroundOpacity, StringFormat={}{0:P0}}"/>
|
||||
<Slider Minimum="0" Maximum="1" SmallChange="0.05" LargeChange="0.1"
|
||||
Value="{Binding ScoreboardBackgroundOpacity, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
</DockPanel>
|
||||
|
||||
<DockPanel Margin="10,0,0,0">
|
||||
<TextBlock DockPanel.Dock="Left" Text="Text size" Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
FontSize="11" Width="60" VerticalAlignment="Center"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="11"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"
|
||||
<TextBlock DockPanel.Dock="Left" Text="Text size" Style="{StaticResource PropertyFieldLabel}" Width="60"/>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right"
|
||||
Style="{StaticResource PropertyFieldLabel}"
|
||||
Text="{Binding ScoreboardFontSizeLabel}"/>
|
||||
<Slider Minimum="14" Maximum="24" SmallChange="1" LargeChange="2" TickFrequency="1" IsSnapToTickEnabled="True"
|
||||
Value="{Binding ScoreboardFontSize, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
@@ -573,8 +571,8 @@
|
||||
|
||||
<!-- Countdown config -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsCountdown, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Timer (minutes)" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel Margin="0,0,0,6">
|
||||
<TextBlock Text="Timer (minutes)" Style="{StaticResource PropertyHeader}"/>
|
||||
<DockPanel Margin="10,0,0,6">
|
||||
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
||||
Width="22" Height="22" Margin="4,0,0,0"
|
||||
Click="CountdownAccept_Click">
|
||||
@@ -613,8 +611,8 @@
|
||||
<TextBox Text="{Binding SelectedElement.Height, UpdateSourceTrigger=PropertyChanged, StringFormat=F0}"
|
||||
Style="{StaticResource YtTextBoxCompact}"/>
|
||||
</DockPanel>
|
||||
<TextBlock Text="URI" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel>
|
||||
<TextBlock Text="URI" Style="{StaticResource PropertyHeader}"/>
|
||||
<DockPanel Margin="10,0,0,0">
|
||||
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
||||
Width="22" Height="22" Margin="4,0,0,0" IsTabStop="False"
|
||||
Click="WebAccept_Click">
|
||||
@@ -852,7 +850,7 @@
|
||||
<!-- Background properties -->
|
||||
<StackPanel Margin="0,8,0,0"
|
||||
Visibility="{Binding SelectedElement.IsBackground, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="Background" Style="{StaticResource SubHeader}"/>
|
||||
<TextBlock Text="Background" Style="{StaticResource PropertyHeader}"/>
|
||||
<StackPanel Margin="4,0,0,0">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
||||
<TextBlock Text="Use default background:" Style="{StaticResource PropertyFieldLabel}"/>
|
||||
|
||||
+8
-15
@@ -147,9 +147,11 @@
|
||||
(the guard test in ytLive.Tests/PropertiesStyleTests.cs enforces it). -->
|
||||
<!-- ═══ Property-panel typography (2026-11-01) ═══
|
||||
One hierarchy for every properties section, so no panel invents its own:
|
||||
PropertyHeader — the category (bright, 11px, semibold)
|
||||
PropertySubHeader — a field label inside it (dim, 10px, indented)
|
||||
PropertyHint — the explanatory sentence under a control (dim, 10px, wrapped)
|
||||
PropertyHeader — the heading of a group (bright, 11px, semibold)
|
||||
PropertyFieldLabel — the label in a row with its control (dim, 10px, semibold)
|
||||
PropertyHint — the explanatory sentence under a control (dim, 10px, wrapped)
|
||||
ONE heading rank: a group is never sometimes a header and sometimes a sub-header, which
|
||||
is what put Ticker out of step with Geometry (creator ruling, 2026-11-01).
|
||||
Colour does the grouping: bright for the thing you are editing, dim for its labels and
|
||||
help. No new palette entries; these are the existing OnSurface / OnSurfaceVariant tokens. -->
|
||||
<Style x:Key="PropertyHeader" TargetType="TextBlock">
|
||||
@@ -159,18 +161,9 @@
|
||||
<Setter Property="Margin" Value="0,0,0,6"/>
|
||||
</Style>
|
||||
|
||||
<!-- Sub-headings sit FLUSH LEFT, level with the category header; it is their smaller size and
|
||||
dimmer colour that make them subordinate, not an indent. Only the controls indent. -->
|
||||
<Style x:Key="PropertySubHeader" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Margin" Value="0,6,0,3"/>
|
||||
</Style>
|
||||
|
||||
<!-- A field label that sits in a row with its control (DockPanel.Dock="Left", fixed Width).
|
||||
Same typography as PropertySubHeader, but vertically centred and marginless so the rows
|
||||
stay on a grid. -->
|
||||
<!-- A field label that sits in a row with its control (DockPanel.Dock="Left", fixed Width),
|
||||
or a value readout beside a slider. Vertically centred and marginless so the rows stay on
|
||||
a grid. -->
|
||||
<Style x:Key="PropertyFieldLabel" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
|
||||
@@ -43,9 +43,17 @@ public class PropertiesStyleTests
|
||||
AssertStyled(combo, "YtComboBox",
|
||||
$"{where}: a ComboBox is not styled with YtComboBox — it renders with the light system template");
|
||||
|
||||
// Every check box is a pill switch (creator ruling, 2026-11-01: "all checkboxes as
|
||||
// pill switches"), so PropertyPillCheck is the theme style that matters here; YtCheckBox
|
||||
// is still accepted where a plain box is deliberate.
|
||||
foreach (var check in doc.Descendants().Where(e => e.Name.LocalName == "CheckBox"))
|
||||
AssertStyled(check, "YtCheckBox",
|
||||
$"{where}: a CheckBox is not styled with YtCheckBox — it renders with the light system template");
|
||||
{
|
||||
var style = (string?)check.Attribute("Style") ?? string.Empty;
|
||||
Assert.True(
|
||||
style.Contains("PropertyPillCheck", StringComparison.Ordinal)
|
||||
|| style.Contains("YtCheckBox", StringComparison.Ordinal),
|
||||
$"{where}: a CheckBox carries no theme style — it renders with the light system template");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Every field in the properties panel carries the compact theme style and paints
|
||||
|
||||
Reference in New Issue
Block a user