feat(socials): bar appearance — text colour, background plate, opacity, text shadow
In the Socials drawer, under the show/hide switch: text colour, an optional background plate with its own colour and opacity, and a text drop shadow. The bar had been hard-wired white-on-transparent since it shipped. - `SocialsConfig` gains five additive properties (BarTextColor, BarBackgroundEnabled, BarBackgroundColor, BarBackgroundOpacity, BarTextShadow). - Persistence: five new Socials columns, added by the per-column idempotent migration pattern (a half-migrated DB heals instead of failing), written in Save and read back in Load with defaults for pre-existing rows. - `SocialBarRenderer.Render(entries, SocialBarStyle?)` — the look is a separate value type so the renderer stays a pure "entries + look" function and the preview can never read a half-applied config mid-edit. A malformed hex falls back to white/black instead of throwing inside a render tick. - The plate hugs the entries (rounded 20px, padding) so it reads as a caption bar, not a band across the frame. Off by default, because transparent is what creators have today. - The colour pickers reuse `BorderColorPalette` — one catalogue of the app's colours, per the TASK 60/63 rule. Guard: SocialBarAppearanceTests paints the real strip and inspects pixels — default is white with no plate, a red text colour reaches the glyphs, a 55% blue plate yields half-transparent blue pixels, and the shadow adds dark pixels that were not there before.
This commit is contained in:
@@ -70,6 +70,50 @@ public sealed class SocialsConfig : INotifyPropertyChanged
|
||||
set => Set(ref _barPosition, value);
|
||||
}
|
||||
|
||||
// ─── Bar appearance (creator request 2026-10-30) ───────────────────────────
|
||||
// The bar used to be hard-wired white-on-transparent. These five knobs are the whole
|
||||
// appearance surface: text colour, an optional plate behind it, and a text shadow.
|
||||
|
||||
private string _barTextColor = "#FFFFFF";
|
||||
/// <summary>Text and logo colour of the bar (hex, straight alpha).</summary>
|
||||
public string BarTextColor
|
||||
{
|
||||
get => _barTextColor;
|
||||
set => Set(ref _barTextColor, string.IsNullOrWhiteSpace(value) ? "#FFFFFF" : value);
|
||||
}
|
||||
|
||||
private bool _barBackgroundEnabled;
|
||||
/// <summary>Draw a rounded plate behind the entries. Off by default — the bar shipped
|
||||
/// transparent and most creators keep it that way.</summary>
|
||||
public bool BarBackgroundEnabled
|
||||
{
|
||||
get => _barBackgroundEnabled;
|
||||
set => Set(ref _barBackgroundEnabled, value);
|
||||
}
|
||||
|
||||
private string _barBackgroundColor = "#000000";
|
||||
public string BarBackgroundColor
|
||||
{
|
||||
get => _barBackgroundColor;
|
||||
set => Set(ref _barBackgroundColor, string.IsNullOrWhiteSpace(value) ? "#000000" : value);
|
||||
}
|
||||
|
||||
private double _barBackgroundOpacity = 0.55;
|
||||
/// <summary>0 = invisible plate, 1 = solid. Only meaningful when the plate is on.</summary>
|
||||
public double BarBackgroundOpacity
|
||||
{
|
||||
get => _barBackgroundOpacity;
|
||||
set => Set(ref _barBackgroundOpacity, Math.Clamp(value, 0, 1));
|
||||
}
|
||||
|
||||
private bool _barTextShadow;
|
||||
/// <summary>A soft black drop shadow behind the glyphs, for a bright or busy scene.</summary>
|
||||
public bool BarTextShadow
|
||||
{
|
||||
get => _barTextShadow;
|
||||
set => Set(ref _barTextShadow, value);
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
private bool Set<T>(ref T field, T value, [CallerMemberName] string? name = null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user