ForgeTrust.AppSurface.Theming 0.2.0-preview.8

This is a prerelease version of ForgeTrust.AppSurface.Theming.
dotnet add package ForgeTrust.AppSurface.Theming --version 0.2.0-preview.8
                    
NuGet\Install-Package ForgeTrust.AppSurface.Theming -Version 0.2.0-preview.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ForgeTrust.AppSurface.Theming" Version="0.2.0-preview.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ForgeTrust.AppSurface.Theming" Version="0.2.0-preview.8" />
                    
Directory.Packages.props
<PackageReference Include="ForgeTrust.AppSurface.Theming" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ForgeTrust.AppSurface.Theming --version 0.2.0-preview.8
                    
#r "nuget: ForgeTrust.AppSurface.Theming, 0.2.0-preview.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ForgeTrust.AppSurface.Theming@0.2.0-preview.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ForgeTrust.AppSurface.Theming&version=0.2.0-preview.8&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ForgeTrust.AppSurface.Theming&version=0.2.0-preview.8&prerelease
                    
Install as a Cake Tool

ForgeTrust.AppSurface.Theming

ForgeTrust.AppSurface.Theming defines immutable semantic light/dark pairs for AppSurface-owned UI. It is deliberately not a site-wide design system: it does not style application components, choose a user preference, persist a cookie, inspect a request, implement tenant policy, or load remote theme packs.

For an ASP.NET Core application, begin with the Web theme-pairs quickstart. ForgeTrust.AppSurface.Web references this package and supplies the Razor integration. Install this package directly only when authoring another package-owned adapter.

Release Guidance

AppSurface ships as a coordinated package family. Before installing this package from a prerelease feed, check the package chooser and release hub for current release risk, migration guidance, and readiness.

Contract

A pair has one canonical lowercase identifier (letter-led, 63 characters or fewer, with only lowercase letters, digits, and single interior hyphens) and a complete Light and Dark set of these roles:

Role Used for
Canvas, Surface, RaisedSurface Package-owned page and layered surfaces.
Text, MutedText, Border Readable content, secondary content, and structural boundaries.
Accent, AccentStrong, Focus Active states, emphasis, and visible keyboard focus.
Link, VisitedLink, Danger Links and recoverable/destructive error treatment.

Shared role values must be opaque #RRGGBB colors. Configuration seals them at registration time and checks WCAG 2.2 text contrast at 4.5:1 plus non-text contrast at 3:1 against every shared surface. These checks apply to the shared semantic tokens; they do not certify application-authored CSS. AppSurfaceThemePair.Graphite() is an evidence-gated shared Light/Dark pair: use it when the host has evidence for both branches, and let registration fail closed when the pair is incomplete or unsafe. It is distinct from the Docs-local fixed-dark GraphiteDark preset.

using ForgeTrust.AppSurface.Theming;

services.AddAppSurfaceTheming(options =>
{
    options.DefaultTheme = new AppSurfaceThemeId("graphite");
    options.DefaultMode = AppSurfaceThemeMode.System;
    options.Pairs.Add(AppSurfaceThemePair.Graphite());
});

System emits both branches and lets browser CSS select prefers-color-scheme. Light and Dark emit only the selected branch. This is host configuration, not per-user policy.

Graphite is the shared pair identifier and carries both semantic Light and Dark role sets through the Web and Docs bridge. GraphiteDark is not that pair: it is a Docs-local fixed-dark compatibility preset. Browser-local preferences are a separate Web opt-in that stores only a presentation choice in the browser; they do not change the registered pair or make Docs' local preset a shared theme.

For a presentation-only browser choice, use the Web-layer browser-local preference adapter. It is an explicit opt-in that preserves one canonical HTML document, stores only light or dark in browser-local storage, and falls back to this package's System CSS. For an already-authorized request context that must choose a registered pair, use the Web-layer host-owned selection adapter. Account synchronization, tenant lookup, identity normalization, authorization, mapping storage, cache partitioning, invalidation, consent decisions, and content-varying policy remain application concerns and do not belong in this neutral package.

Package-owned adapters that need a fail-closed boundary can call AppSurfaceThemeRegistry.IsSafeResolution(resolution). It applies the same identity, role, and contrast contract as startup registration without depending on or allocating a Web document.

Application-specific settings

An application can provide typed settings to a package-owned adapter through IAppSurfaceThemeExtensionProvider<TSettings>. The neutral package treats the setting as opaque: it neither validates, serializes, logs, nor renders it.

sealed record AcmeThemeSettings(string ProductMarkUrl, bool ShowReleaseRail);

sealed class AcmeThemeSettingsProvider : IAppSurfaceThemeExtensionProvider<AcmeThemeSettings>
{
    public bool TryGet(AppSurfaceThemeId themeId, out AcmeThemeSettings settings)
    {
        if (themeId.Value == "appsurface")
        {
            settings = new AcmeThemeSettings("/assets/acme-mark.svg", true);
            return true;
        }

        settings = null!;
        return false;
    }
}

Register the provider and call AddRequiredThemeExtension<TSettings>() when every configured pair must have settings. The neutral registry checks provider presence and calls TryGet once per sealed pair when it is first resolved; it reports ASTHEME201 for a missing provider and ASTHEME202 for a missing or null pair setting.

services.AddSingleton<IAppSurfaceThemeExtensionProvider<AcmeThemeSettings>, AcmeThemeSettingsProvider>();
services.AddRequiredThemeExtension<AcmeThemeSettings>();

Use this seam when a specific adapter needs app-owned configuration. Do not add arbitrary metadata bags or promote application concepts into shared semantic roles. The application still owns settings-schema, asset, and authorization validation.

Diagnostics and pitfalls

Every startup diagnostic follows Problem / Cause / Fix / Docs ordering and is safe to surface to an operator:

  • ASTHEME001 — no usable pairs or unsupported mode.
  • ASTHEME002 — default pair is not registered.
  • ASTHEME003 — missing/invalid pair identity.
  • ASTHEME004 — duplicate canonical pair id.
  • ASTHEME005 — a role is not one opaque #RRGGBB value.
  • ASTHEME101 — a role fails its required contrast ratio.
  • ASTHEME201 — an opted-in extension provider is not registered.
  • ASTHEME202 — an opted-in extension provider has no setting for a registered pair.

The Web adapter preserves a conflicting host color-scheme declaration and exposes data-as-theme-color-scheme-conflict="true"; resolve the conflict explicitly rather than expecting AppSurface to overwrite host CSS.

Do not use this package for a switcher, local-storage/cookie precedence, tenant lookup, or client-hint selection. The supported browser-local and request-aware adapters live in AppSurface Web; cookie, account, tenant, client-hint, and content-varying approaches still require a separate privacy, CSP, caching, and first-paint design. Related follow-on policy work is tracked in #706, #707, and #708.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ForgeTrust.AppSurface.Theming:

Package Downloads
ForgeTrust.AppSurface.Web

ForgeTrust.AppSurface.Web package for AppSurface application composition.

ForgeTrust.AppSurface.Docs

ForgeTrust.AppSurface.Docs package for AppSurface application composition.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0-preview.8 581 8/23/2026
0.2.0-preview.7 290 8/16/2026
0.2.0-preview.6 209 8/12/2026