ui(brand): superimposed dragon watermark behind participants, theme-flipped (white/dark, black/light)
Some checks failed
CI / build-and-test (push) Failing after 27s
Some checks failed
CI / build-and-test (push) Failing after 27s
This commit is contained in:
parent
80d9baf2d0
commit
dfdfa9e0e1
7 changed files with 99 additions and 2 deletions
34
src/TeamsISO.App/Assets/_recolor_dragon.py
Normal file
34
src/TeamsISO.App/Assets/_recolor_dragon.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
from PIL import Image
|
||||
import os
|
||||
|
||||
# We treat the navy-blue dragon-mark.png as a silhouette source: anything with
|
||||
# nontrivial alpha is "dragon", everything else stays transparent. We emit a
|
||||
# pure-black and pure-white variant, tightly cropped to the actual content
|
||||
# bbox so they center cleanly when used as a watermark.
|
||||
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
src_path = os.path.join(ROOT, "dragon-mark.png")
|
||||
src = Image.open(src_path).convert("RGBA")
|
||||
|
||||
alpha = src.split()[-1]
|
||||
# Threshold to drop anti-alias fringe that can fool getbbox into reporting
|
||||
# the whole canvas as "in".
|
||||
mask = alpha.point(lambda v: 255 if v > 16 else 0)
|
||||
bbox = mask.getbbox()
|
||||
print("content bbox =", bbox, "size =", (bbox[2] - bbox[0], bbox[3] - bbox[1]))
|
||||
|
||||
cropped = src.crop(bbox)
|
||||
_, _, _, ca = cropped.split()
|
||||
|
||||
for name, rgb in (("black", (0, 0, 0)), ("white", (255, 255, 255))):
|
||||
flat = Image.merge(
|
||||
"RGBA",
|
||||
(
|
||||
Image.new("L", cropped.size, rgb[0]),
|
||||
Image.new("L", cropped.size, rgb[1]),
|
||||
Image.new("L", cropped.size, rgb[2]),
|
||||
ca,
|
||||
),
|
||||
)
|
||||
out_path = os.path.join(ROOT, f"dragon-mark-{name}.png")
|
||||
flat.save(out_path, "PNG", optimize=True)
|
||||
print("wrote", out_path, flat.size)
|
||||
BIN
src/TeamsISO.App/Assets/dragon-mark-black.png
Normal file
BIN
src/TeamsISO.App/Assets/dragon-mark-black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
src/TeamsISO.App/Assets/dragon-mark-white.png
Normal file
BIN
src/TeamsISO.App/Assets/dragon-mark-white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
|
|
@ -106,7 +106,11 @@
|
|||
BorderThickness="0"
|
||||
Cursor="Hand"
|
||||
ToolTip="About TeamsISO">
|
||||
<Image Source="/Assets/dragon-mark.png"
|
||||
<!-- Source bound to Wd.BrandMark.Image so the mark flips
|
||||
white↔black with the active theme (see Theme.Dark /
|
||||
Theme.Light). The PNG carries its own AA so HighQuality
|
||||
scaling is preferred over NearestNeighbor at this size. -->
|
||||
<Image Source="{DynamicResource Wd.BrandMark.Image}"
|
||||
Width="20" Height="20"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||||
</Button>
|
||||
|
|
@ -447,8 +451,30 @@
|
|||
BorderBrush="{DynamicResource Wd.Border}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource Radius.M}"
|
||||
Background="{DynamicResource Wd.Surface}">
|
||||
Background="{DynamicResource Wd.Surface}"
|
||||
ClipToBounds="True">
|
||||
<Grid>
|
||||
<!--
|
||||
Brand watermark superimposed BEHIND the participants grid.
|
||||
Sits at 6% opacity so a populated grid reads cleanly over
|
||||
the top while the dragon is still visible through the
|
||||
transparent row backgrounds (RowBackground="Transparent"
|
||||
on the DataGrid below). When the grid is empty the
|
||||
watermark becomes the de-facto empty-state surface.
|
||||
|
||||
IsHitTestVisible=False so the watermark never absorbs
|
||||
clicks meant for grid rows or the empty area below them.
|
||||
Source binds to the theme-flipped Wd.BrandMark.Image
|
||||
resource — white dragon in dark mode, black in light.
|
||||
-->
|
||||
<Image Source="{DynamicResource Wd.BrandMark.Image}"
|
||||
Opacity="0.06"
|
||||
Stretch="Uniform"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="40"
|
||||
IsHitTestVisible="False"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||||
<DataGrid x:Name="ParticipantsGrid"
|
||||
ItemsSource="{Binding ParticipantsView}"
|
||||
AutoGenerateColumns="False"
|
||||
|
|
|
|||
|
|
@ -60,7 +60,17 @@
|
|||
|
||||
<!-- Wild Dragon brand assets — embedded as resources so the published binary is self-contained. -->
|
||||
<ItemGroup>
|
||||
<!-- Source navy-blue dragon-mark, kept for AboutWindow / installer iconography. -->
|
||||
<Resource Include="Assets\dragon-mark.png" />
|
||||
<!--
|
||||
Theme-aware silhouette variants used by Theme.Dark / Theme.Light to expose
|
||||
a single Wd.BrandMark.Image resource key. The dark theme picks the white
|
||||
dragon (visible on #0A0A0A), the light theme picks the black dragon
|
||||
(visible on #FAFAFB). Generated from dragon-mark.png via
|
||||
Assets/_recolor_dragon.py — re-run if the source mark ever changes.
|
||||
-->
|
||||
<Resource Include="Assets\dragon-mark-white.png" />
|
||||
<Resource Include="Assets\dragon-mark-black.png" />
|
||||
<Resource Include="Assets\wild-dragon-wordmark.png" />
|
||||
<Resource Include="Assets\teamsiso.ico" />
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -44,4 +44,20 @@
|
|||
<SolidColorBrush x:Key="Wd.Status.LiveBg" Color="#13261A"/>
|
||||
<SolidColorBrush x:Key="Wd.Status.Warn" Color="#FBBF24"/>
|
||||
<SolidColorBrush x:Key="Wd.Status.Error" Color="#FB819C"/>
|
||||
|
||||
<!--
|
||||
Brand mark image, theme-flipped. Dark mode shows the WHITE dragon so it
|
||||
reads against the near-black canvas. The light theme exposes the same
|
||||
key pointing at the BLACK dragon. Consumers bind via
|
||||
{DynamicResource Wd.BrandMark.Image} so the swap is automatic on
|
||||
ThemeManager.Toggle().
|
||||
|
||||
CacheOption=OnLoad decodes the PNG at load time and releases the
|
||||
underlying stream, which matters because the source files are 1243×1125
|
||||
— without OnLoad the BitmapImage holds the stream open for the life
|
||||
of the resource dictionary.
|
||||
-->
|
||||
<BitmapImage x:Key="Wd.BrandMark.Image"
|
||||
UriSource="pack://application:,,,/TeamsISO;component/Assets/dragon-mark-white.png"
|
||||
CacheOption="OnLoad"/>
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -46,4 +46,15 @@
|
|||
<SolidColorBrush x:Key="Wd.Status.LiveBg" Color="#DCFCE7"/>
|
||||
<SolidColorBrush x:Key="Wd.Status.Warn" Color="#B45309"/>
|
||||
<SolidColorBrush x:Key="Wd.Status.Error" Color="#D43E5C"/>
|
||||
|
||||
<!--
|
||||
Brand mark image, theme-flipped. Light mode shows the BLACK dragon so it
|
||||
reads against the cyan-tinted off-white canvas. Mirror of the Dark
|
||||
theme's resource — same key, opposite silhouette. Consumers use
|
||||
{DynamicResource Wd.BrandMark.Image} so the swap is automatic.
|
||||
See Theme.Dark.xaml's comment for the CacheOption=OnLoad rationale.
|
||||
-->
|
||||
<BitmapImage x:Key="Wd.BrandMark.Image"
|
||||
UriSource="pack://application:,,,/TeamsISO;component/Assets/dragon-mark-black.png"
|
||||
CacheOption="OnLoad"/>
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
Loading…
Reference in a new issue