Files

375 lines
15 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform;
/// <summary>
/// Centralized theme colors for Skia views using MAUI Color types.
/// All colors are defined as MAUI Colors for API compliance and converted to SKColor for rendering.
/// </summary>
public static class SkiaTheme
{
#region Primary Colors
/// <summary>Material Blue - Primary accent color</summary>
public static readonly Color Primary = Color.FromRgb(0x21, 0x96, 0xF3);
/// <summary>Material Blue Dark - Darker primary variant</summary>
public static readonly Color PrimaryDark = Color.FromRgb(0x19, 0x76, 0xD2);
/// <summary>Material Blue Light with transparency</summary>
public static readonly Color PrimaryLight = Color.FromRgba(0x21, 0x96, 0xF3, 0x60);
/// <summary>Material Blue with 35% opacity for selection</summary>
public static readonly Color PrimarySelection = Color.FromRgba(0x21, 0x96, 0xF3, 0x59);
/// <summary>Material Blue with 50% opacity</summary>
public static readonly Color PrimaryHalf = Color.FromRgba(0x21, 0x96, 0xF3, 0x80);
#endregion
#region Text Colors
/// <summary>Primary text color - dark gray</summary>
public static readonly Color TextPrimary = Color.FromRgb(0x21, 0x21, 0x21);
/// <summary>Secondary text color - medium gray</summary>
public static readonly Color TextSecondary = Color.FromRgb(0x61, 0x61, 0x61);
/// <summary>Tertiary/hint text color</summary>
public static readonly Color TextTertiary = Color.FromRgb(0x75, 0x75, 0x75);
/// <summary>Disabled text color</summary>
public static readonly Color TextDisabled = Color.FromRgb(0x9E, 0x9E, 0x9E);
/// <summary>Placeholder text color</summary>
public static readonly Color TextPlaceholder = Color.FromRgb(0x80, 0x80, 0x80);
/// <summary>Link text color</summary>
public static readonly Color TextLink = Color.FromRgb(0x21, 0x96, 0xF3);
/// <summary>Visited link text color - Material Purple</summary>
public static readonly Color TextLinkVisited = Color.FromRgb(0x9C, 0x27, 0xB0);
#endregion
#region Background Colors
/// <summary>White background</summary>
public static readonly Color BackgroundWhite = Colors.White;
/// <summary>Semi-transparent white (59% opacity)</summary>
public static readonly Color WhiteSemiTransparent = Color.FromRgba(255, 255, 255, 150);
/// <summary>Light gray background</summary>
public static readonly Color BackgroundLight = Color.FromRgb(0xF5, 0xF5, 0xF5);
/// <summary>Slightly darker light background</summary>
public static readonly Color BackgroundLightAlt = Color.FromRgb(0xFA, 0xFA, 0xFA);
/// <summary>Surface background (cards, dialogs)</summary>
public static readonly Color BackgroundSurface = Color.FromRgb(0xFF, 0xFF, 0xFF);
/// <summary>Disabled background</summary>
public static readonly Color BackgroundDisabled = Color.FromRgb(0xEE, 0xEE, 0xEE);
#endregion
#region Gray Scale
/// <summary>Gray 50 - lightest</summary>
public static readonly Color Gray50 = Color.FromRgb(0xFA, 0xFA, 0xFA);
/// <summary>Gray 100</summary>
public static readonly Color Gray100 = Color.FromRgb(0xF5, 0xF5, 0xF5);
/// <summary>Gray 200</summary>
public static readonly Color Gray200 = Color.FromRgb(0xEE, 0xEE, 0xEE);
/// <summary>Gray 300</summary>
public static readonly Color Gray300 = Color.FromRgb(0xE0, 0xE0, 0xE0);
/// <summary>Gray 400</summary>
public static readonly Color Gray400 = Color.FromRgb(0xBD, 0xBD, 0xBD);
/// <summary>Gray 500</summary>
public static readonly Color Gray500 = Color.FromRgb(0x9E, 0x9E, 0x9E);
/// <summary>Gray 600</summary>
public static readonly Color Gray600 = Color.FromRgb(0x75, 0x75, 0x75);
/// <summary>Gray 700</summary>
public static readonly Color Gray700 = Color.FromRgb(0x61, 0x61, 0x61);
/// <summary>Gray 800</summary>
public static readonly Color Gray800 = Color.FromRgb(0x42, 0x42, 0x42);
/// <summary>Gray 900 - darkest</summary>
public static readonly Color Gray900 = Color.FromRgb(0x21, 0x21, 0x21);
#endregion
#region Border Colors
/// <summary>Light border color</summary>
public static readonly Color BorderLight = Color.FromRgb(0xE0, 0xE0, 0xE0);
/// <summary>Medium border color</summary>
public static readonly Color BorderMedium = Color.FromRgb(0xC8, 0xC8, 0xC8);
/// <summary>Dark border color</summary>
public static readonly Color BorderDark = Color.FromRgb(0xA0, 0xA0, 0xA0);
#endregion
#region Shadow Colors
/// <summary>Shadow with 10% opacity</summary>
public static readonly Color Shadow10 = Color.FromRgba(0, 0, 0, 0x1A);
/// <summary>Shadow with 15% opacity</summary>
public static readonly Color Shadow15 = Color.FromRgba(0, 0, 0, 0x26);
/// <summary>Shadow with 20% opacity</summary>
public static readonly Color Shadow20 = Color.FromRgba(0, 0, 0, 0x33);
/// <summary>Shadow with 25% opacity</summary>
public static readonly Color Shadow25 = Color.FromRgba(0, 0, 0, 0x40);
/// <summary>Shadow with 40% opacity</summary>
public static readonly Color Shadow40 = Color.FromRgba(0, 0, 0, 0x64);
/// <summary>Shadow with 50% opacity</summary>
public static readonly Color Shadow50 = Color.FromRgba(0, 0, 0, 0x80);
#endregion
#region Overlay Colors
/// <summary>Scrim/overlay with 40% opacity</summary>
public static readonly Color Overlay40 = Color.FromRgba(0, 0, 0, 0x64);
/// <summary>Scrim/overlay with 50% opacity</summary>
public static readonly Color Overlay50 = Color.FromRgba(0, 0, 0, 0x80);
#endregion
#region Status Colors
/// <summary>Error/danger color - Material Red</summary>
public static readonly Color Error = Color.FromRgb(0xF4, 0x43, 0x36);
/// <summary>Success color - Material Green</summary>
public static readonly Color Success = Color.FromRgb(0x4C, 0xAF, 0x50);
/// <summary>Warning color - Material Orange</summary>
public static readonly Color Warning = Color.FromRgb(0xFF, 0x98, 0x00);
#endregion
#region Button Colors
/// <summary>Cancel button background</summary>
public static readonly Color ButtonCancel = Color.FromRgb(0x9E, 0x9E, 0x9E);
/// <summary>Cancel button hover</summary>
public static readonly Color ButtonCancelHover = Color.FromRgb(0x75, 0x75, 0x75);
#endregion
#region Scrollbar Colors
/// <summary>Scrollbar thumb color</summary>
public static readonly Color ScrollbarThumb = Color.FromRgba(0x80, 0x80, 0x80, 0x80);
/// <summary>Scrollbar track color</summary>
public static readonly Color ScrollbarTrack = Color.FromRgba(0xC8, 0xC8, 0xC8, 0x40);
#endregion
#region Indicator Colors
/// <summary>Unselected indicator color</summary>
public static readonly Color IndicatorUnselected = Color.FromRgb(0xB4, 0xB4, 0xB4);
/// <summary>Selected indicator color</summary>
public static readonly Color IndicatorSelected = Color.FromRgb(0x21, 0x96, 0xF3);
#endregion
#region Menu Colors
/// <summary>Menu background</summary>
public static readonly Color MenuBackground = Color.FromRgb(0xF0, 0xF0, 0xF0);
/// <summary>Menu hover background</summary>
public static readonly Color MenuHover = Color.FromRgb(0xDC, 0xDC, 0xDC);
/// <summary>Menu active/pressed background</summary>
public static readonly Color MenuActive = Color.FromRgb(0xC8, 0xC8, 0xC8);
/// <summary>Menu separator color</summary>
public static readonly Color MenuSeparator = Color.FromRgb(0xDC, 0xDC, 0xDC);
#endregion
#region Dark Theme Colors
/// <summary>Dark theme background</summary>
public static readonly Color DarkBackground = Color.FromRgb(0x30, 0x30, 0x30);
/// <summary>Dark theme surface</summary>
public static readonly Color DarkSurface = Color.FromRgb(0x50, 0x50, 0x50);
/// <summary>Dark theme text</summary>
public static readonly Color DarkText = Color.FromRgb(0xE0, 0xE0, 0xE0);
/// <summary>Dark theme hover</summary>
public static readonly Color DarkHover = Color.FromRgb(0x50, 0x50, 0x50);
#endregion
#region SKColor Cached Conversions (for rendering performance)
// Primary
internal static readonly SKColor PrimarySK = Primary.ToSKColor();
internal static readonly SKColor PrimaryDarkSK = PrimaryDark.ToSKColor();
internal static readonly SKColor PrimaryLightSK = PrimaryLight.ToSKColor();
internal static readonly SKColor PrimarySelectionSK = PrimarySelection.ToSKColor();
internal static readonly SKColor PrimaryHalfSK = PrimaryHalf.ToSKColor();
// Text
internal static readonly SKColor TextPrimarySK = TextPrimary.ToSKColor();
internal static readonly SKColor TextSecondarySK = TextSecondary.ToSKColor();
internal static readonly SKColor TextTertiarySK = TextTertiary.ToSKColor();
internal static readonly SKColor TextDisabledSK = TextDisabled.ToSKColor();
internal static readonly SKColor TextPlaceholderSK = TextPlaceholder.ToSKColor();
internal static readonly SKColor TextLinkSK = TextLink.ToSKColor();
internal static readonly SKColor TextLinkVisitedSK = TextLinkVisited.ToSKColor();
// Backgrounds
internal static readonly SKColor BackgroundWhiteSK = SKColors.White;
internal static readonly SKColor WhiteSemiTransparentSK = WhiteSemiTransparent.ToSKColor();
internal static readonly SKColor BackgroundLightSK = BackgroundLight.ToSKColor();
internal static readonly SKColor BackgroundLightAltSK = BackgroundLightAlt.ToSKColor();
internal static readonly SKColor BackgroundSurfaceSK = BackgroundSurface.ToSKColor();
internal static readonly SKColor BackgroundDisabledSK = BackgroundDisabled.ToSKColor();
// Gray scale
internal static readonly SKColor Gray50SK = Gray50.ToSKColor();
internal static readonly SKColor Gray100SK = Gray100.ToSKColor();
internal static readonly SKColor Gray200SK = Gray200.ToSKColor();
internal static readonly SKColor Gray300SK = Gray300.ToSKColor();
internal static readonly SKColor Gray400SK = Gray400.ToSKColor();
internal static readonly SKColor Gray500SK = Gray500.ToSKColor();
internal static readonly SKColor Gray600SK = Gray600.ToSKColor();
internal static readonly SKColor Gray700SK = Gray700.ToSKColor();
internal static readonly SKColor Gray800SK = Gray800.ToSKColor();
internal static readonly SKColor Gray900SK = Gray900.ToSKColor();
// Borders
internal static readonly SKColor BorderLightSK = BorderLight.ToSKColor();
internal static readonly SKColor BorderMediumSK = BorderMedium.ToSKColor();
internal static readonly SKColor BorderDarkSK = BorderDark.ToSKColor();
// Shadows
internal static readonly SKColor Shadow10SK = Shadow10.ToSKColor();
internal static readonly SKColor Shadow15SK = Shadow15.ToSKColor();
internal static readonly SKColor Shadow20SK = Shadow20.ToSKColor();
internal static readonly SKColor Shadow25SK = Shadow25.ToSKColor();
internal static readonly SKColor Shadow40SK = Shadow40.ToSKColor();
internal static readonly SKColor Shadow50SK = Shadow50.ToSKColor();
// Overlays
internal static readonly SKColor Overlay40SK = Overlay40.ToSKColor();
internal static readonly SKColor Overlay50SK = Overlay50.ToSKColor();
// Status
internal static readonly SKColor ErrorSK = Error.ToSKColor();
internal static readonly SKColor SuccessSK = Success.ToSKColor();
internal static readonly SKColor WarningSK = Warning.ToSKColor();
// Buttons
internal static readonly SKColor ButtonCancelSK = ButtonCancel.ToSKColor();
internal static readonly SKColor ButtonCancelHoverSK = ButtonCancelHover.ToSKColor();
// Scrollbars
internal static readonly SKColor ScrollbarThumbSK = ScrollbarThumb.ToSKColor();
internal static readonly SKColor ScrollbarTrackSK = ScrollbarTrack.ToSKColor();
// Indicators
internal static readonly SKColor IndicatorUnselectedSK = IndicatorUnselected.ToSKColor();
internal static readonly SKColor IndicatorSelectedSK = IndicatorSelected.ToSKColor();
// Menu
internal static readonly SKColor MenuBackgroundSK = MenuBackground.ToSKColor();
internal static readonly SKColor MenuHoverSK = MenuHover.ToSKColor();
internal static readonly SKColor MenuActiveSK = MenuActive.ToSKColor();
internal static readonly SKColor MenuSeparatorSK = MenuSeparator.ToSKColor();
// Dark theme
internal static readonly SKColor DarkBackgroundSK = DarkBackground.ToSKColor();
internal static readonly SKColor DarkSurfaceSK = DarkSurface.ToSKColor();
internal static readonly SKColor DarkTextSK = DarkText.ToSKColor();
internal static readonly SKColor DarkHoverSK = DarkHover.ToSKColor();
#endregion
#region Theme-Aware Helpers
/// <summary>
/// Returns true if dark mode is currently active.
/// Checks UserAppTheme first, falls back to system RequestedTheme.
/// </summary>
public static bool IsDarkMode
{
get
{
var app = Application.Current;
if (app == null) return false;
// If user explicitly set a theme, use that
if (app.UserAppTheme != AppTheme.Unspecified)
return app.UserAppTheme == AppTheme.Dark;
// Otherwise use system theme
return app.RequestedTheme == AppTheme.Dark;
}
}
/// <summary>
/// Gets the appropriate button background color for the current theme.
/// </summary>
public static SKColor ButtonBackgroundSK => IsDarkMode ? DarkSurfaceSK : Gray200SK;
/// <summary>
/// Gets the appropriate text color for the current theme.
/// </summary>
public static SKColor CurrentTextSK => IsDarkMode ? DarkTextSK : TextPrimarySK;
/// <summary>
/// Gets the appropriate background color for input controls in the current theme.
/// </summary>
public static SKColor InputBackgroundSK => IsDarkMode ? DarkBackgroundSK : BackgroundWhiteSK;
/// <summary>
/// Gets the appropriate border color for the current theme.
/// </summary>
public static SKColor CurrentBorderSK => IsDarkMode ? Gray600SK : BorderLightSK;
/// <summary>
/// Gets the appropriate surface background for the current theme.
/// </summary>
public static SKColor CurrentSurfaceSK => IsDarkMode ? DarkSurfaceSK : BackgroundWhiteSK;
/// <summary>
/// Gets the appropriate page background for the current theme.
/// </summary>
public static SKColor CurrentPageBackgroundSK => IsDarkMode ? DarkBackgroundSK : BackgroundWhiteSK;
#endregion
}