feat(ui): the capture context menu is always available (Ctrl+right-click); wordmark "ty" is YouTube red

1. The preview's right-click handler swallowed every right-click for the zoom box, so the
   element/backdrop context menu could not open at all. Sources and capture windows must be
   changeable AT ANY TIME — a creator swaps a window mid-stream without entering edit mode.
   Ctrl + right-click now bypasses the zoom path and lets WPF open the menu under the cursor;
   plain right-click keeps the zoom box. No menu markup changed.

2. The wordmark's "ty" is YouTube red (#ff0000), permanently. The token sweep had recoloured it
   to the interactive blue because it was a bare literal; DESIGN.md now records "never re-colour
   the wordmark" beside the token, and UiShellTests pins it.

Guard: UiShellTests gains the wordmark rule and the Ctrl+right-click chord.
This commit is contained in:
2026-10-30 11:07:51 -07:00
parent cb4f8ec758
commit 318871033f
4 changed files with 23 additions and 2 deletions
+6
View File
@@ -590,6 +590,12 @@ public partial class PreviewPane : UserControl
private void Preview_MouseRightButtonDown(object sender, MouseButtonEventArgs e) private void Preview_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{ {
// Ctrl + right-click opens the element / backdrop context menu — sources and windows can
// be changed at ANY time, live or not (creator ruling 2026-10-30). Plain right-click stays
// with the zoom box, which is why the menu needed its own chord.
// Returning without Handled lets WPF's ContextMenuService open the menu under the cursor.
if ((Keyboard.Modifiers & ModifierKeys.Control) != 0) return;
var vm = DataContext as MainViewModel; var vm = DataContext as MainViewModel;
if (vm == null) return; if (vm == null) return;
var grid = (Grid)sender; var grid = (Grid)sender;
+3 -1
View File
@@ -23,7 +23,9 @@
</ControlTemplate> </ControlTemplate>
</Button.Template> </Button.Template>
<TextBlock FontSize="22" FontWeight="Bold" VerticalAlignment="Center"> <TextBlock FontSize="22" FontWeight="Bold" VerticalAlignment="Center">
<Run Text="LlamaCas" Foreground="{StaticResource Brush.OnSurface}"/><Run Text="ty" Foreground="{StaticResource Brush.Tertiary}"/><Run <Run Text="LlamaCas" Foreground="{StaticResource Brush.OnSurface}"/><!-- Creator ruling (2026-10-30, asked repeatedly): the wordmark's "ty" is YouTube red.
It is brand, not state — do not re-tokenise it to an accent. -->
<Run Text="ty" Foreground="{StaticResource Brush.Youtube}"/><Run
x:Name="BuildIdStamp" Text="{x:Static helpers:BuildStamp.Label}" FontSize="9" x:Name="BuildIdStamp" Text="{x:Static helpers:BuildStamp.Label}" FontSize="9"
BaselineAlignment="Superscript" Foreground="{StaticResource Brush.OnSurfaceVariant}" BaselineAlignment="Superscript" Foreground="{StaticResource Brush.OnSurfaceVariant}"
ToolTipService.ToolTip="{x:Static helpers:BuildStamp.Label}"/><Run Text=" " FontSize="4"/> ToolTipService.ToolTip="{x:Static helpers:BuildStamp.Label}"/><Run Text=" " FontSize="4"/>
+1 -1
View File
@@ -58,7 +58,7 @@
| `success-container` | `#1d5c38` | Success notice surface (success toast) | | `success-container` | `#1d5c38` | Success notice surface (success toast) |
| `warning-container` | `#b8860b` | Warning surface — health banner, warning toast | | `warning-container` | `#b8860b` | Warning surface — health banner, warning toast |
| `test-container` | `#9c6f1c` | Test-stream chrome: the gold top bar and glow | | `test-container` | `#9c6f1c` | Test-stream chrome: the gold top bar and glow |
| `youtube` | `#ff0000` | **YouTube-branded surfaces only** — the Stream Info and YPP rails, the YouTube account row. Not for state: live stays `primary` | | `youtube` | `#ff0000` | **YouTube-branded surfaces only** — Stream Info / YPP rails, the YouTube account row, and the wordmark's "ty" (creator ruling: never re-colour it) | — the Stream Info and YPP rails, the YouTube account row. Not for state: live stays `primary` |
**The rule:** red means "live or recording" and nothing else. Never a Send button, a delete action, **The rule:** red means "live or recording" and nothing else. Never a Send button, a delete action,
a brand flourish, or a general accent — that was the defect in the first Stitch draft. a brand flourish, or a general accent — that was the defect in the first Stitch draft.
+13
View File
@@ -59,6 +59,19 @@ public class UiShellTests
Assert.DoesNotContain("MaxHeight", listLine); Assert.DoesNotContain("MaxHeight", listLine);
} }
[Fact]
public void The_wordmark_ty_stays_youtube_red_and_ctrl_opens_the_context_menu()
{
var topBar = SourceAssert.Text("Controls", "TopBar.xaml");
Assert.Contains("<Run Text=\"ty\" Foreground=\"{StaticResource Brush.Youtube}\"/>", topBar);
// Plain right-click is the zoom box; the context menu moved to Ctrl+right-click so a
// creator can change capture sources mid-stream.
var preview = SourceAssert.Text("Controls", "PreviewPane.xaml.cs");
Assert.Contains("ModifierKeys.Control", preview);
Assert.Contains("return;", preview);
}
private static int Count(string haystack, string needle) private static int Count(string haystack, string needle)
{ {
var hits = 0; var hits = 0;