Fuaran.UI.ThemeManifest
0.46.0
Prefix Reserved
dotnet add package Fuaran.UI.ThemeManifest --version 0.46.0
NuGet\Install-Package Fuaran.UI.ThemeManifest -Version 0.46.0
<PackageReference Include="Fuaran.UI.ThemeManifest" Version="0.46.0" />
<PackageVersion Include="Fuaran.UI.ThemeManifest" Version="0.46.0" />
<PackageReference Include="Fuaran.UI.ThemeManifest" />
paket add Fuaran.UI.ThemeManifest --version 0.46.0
#r "nuget: Fuaran.UI.ThemeManifest, 0.46.0"
#:package Fuaran.UI.ThemeManifest@0.46.0
#addin nuget:?package=Fuaran.UI.ThemeManifest&version=0.46.0
#tool nuget:?package=Fuaran.UI.ThemeManifest&version=0.46.0
Fuaran.UI.ThemeManifest
A machine-readable theme token contract the AI can reason against and the Fuaran.UI.StyleObserver can verify against.
The W3C Design Tokens (DTCG) format carries token values + a free-form $description — and nothing else: no controlled role vocabulary, no constraints, no verification surface. ThemeManifest is DTCG-compatible (a vanilla DTCG file decodes cleanly — it is not NIH) extended with the two things DTCG lacks:
- Role →
ToneVariantmapping (RoleBinding) — soTone.Brandis known to resolve to the manifest's brand token. The dual-field token shape (a quantified value + a semantic tag) borrows SpecifyUI's SPEC representation (arXiv:2509.07334). - An invariant block (
Invariant list) — contrast floors, colour-usage budgets, motion voice — soft-weighted per Draco (idl.uw.edu/draco): each invariant carries aWeightso violations rank by importance rather than being equally fatal (weight learning is a later phase; the slot ships now).
The UsageBudget invariant formalises the established 60-30-10 rule (blog.logrocket.com/ux-design/60-30-10-rule) as a per-token targetPct ± tolerancePct, rather than inventing a new metric — the check substrate the StyleObserver's area-weighted colour-distribution pass resolves against.
Shape
ThemeManifest = { Meta; Tokens: ManifestToken list; Roles: RoleBinding list; Invariants: Invariant list }
ManifestToken— DTCG$type/$value/$descriptionround-trip + the SPECRoletag (carried under$extensions.fuaran.role).Nameis the dotted path flattened from the DTCG group tree ("color.brand.base").InvariantKind—ContrastFloor of role * minRatio/UsageBudget of token * targetPct * tolerancePct/MotionVoice of MotionBudget. Additive-only post-ship (parallel toStyleFlag/LayoutFlag).ThemeManifest.resolveRole : ToneVariant -> ThemeManifest -> ManifestToken option— the lookup the StyleObserver consumes;resolveNamedRoleis the named-role counterpart.
The manifest is a host/theme artefact, not part of the Node tree — it travels alongside the tree, never inside it, preserving the "semantic, not CSS" tree posture. FSharp.Core-only and Fable-portable (a small dependency-free JSON parser ships in the package, so encode/decode run byte-identically under Fable and .NET — no System.Text.Json, no external JSON dependency).
A JSON schema (theme-manifest.schema.json) and a neutral example theme (example-theme.manifest.json) ship in the package as the machine-readable contract + the canonical fixture.
Adopting an existing theme (Phase 149)
You don't have to hand-author a manifest. The Project module ingests an app's existing token surface into a baseline manifest you then enrich with invariants:
Project.projectFromFuaranToneVars css— the renderer's semantic--fuaran-tone-{tone}-{bg,fg,border}set. Role inference is direct (the contract is already semantic): each tone'sbgslot is bound to itsToneVariant, soresolveRole Tone.Brandworks with no hand-mapping.Project.projectFromCssCustomProperties css— a generic:root(plus an optional:root[data-theme=dark]) custom-property block. Bespoke var names carry no inferable role, so roles are left unbound for you to map. Light/dark pairs are preserved: the light value keeps the bare name, the dark counterpart is emitted as{name}@dark.Project.projectFromDtcg json— a DTCG /tokens.jsonfile. Values (and any explicit$extensions.fuaran.roletags) round-trip losslessly; grouping is not mined for bindings (DTCG's "don't infer purpose from grouping" caveat), so nothing is over-claimed.Project.merge baseM over— layer an app override onto a shell token set with last-write-wins precedence matching the CSS cascade (e.g. a shell--color-*set + a rebound--fuaran-tone-*set).
What you add by hand: the projectors produce tokens + inferable role bindings only. A thin projected manifest (tokens, no invariants) already drives the contrast flags; usage-budget enforcement and per-role contrast floors require you to add the Invariants (ContrastFloor / UsageBudget / MotionVoice) — opt-in by manifest richness.
Apache-2.0 licensed — see the repo LICENSE.
| Product | Versions 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. |
-
net10.0
- Fable.Core (>= 5.0.0)
- FSharp.Core (>= 10.1.300)
- Fuaran.Core.Column (>= 0.11.0)
- Fuaran.Core.DataFrame (>= 0.11.0)
- Fuaran.Core.Tree (>= 0.11.0)
- Fuaran.Core.Validator (>= 0.11.0)
- Fuaran.Core.Wire (>= 0.11.0)
- Fuaran.UI (>= 0.46.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Fuaran.UI.ThemeManifest:
| Package | Downloads |
|---|---|
|
Fuaran.UI.StyleObserver
Fuaran resolved-style observability concrete observers — BrowserStyleObserver (Fable, getComputedStyle-backed, effective-background composite walk, rAF-debounced) and InMemoryStyleObserver (pure .NET, drives Expecto tests + the eval gate). Companion of Fuaran.UI.StyleObserver.Abstractions; shares all flag-derivation logic. Apache-2.0 licensed. |
|
|
Fuaran.UI.Telemetry.Drift
Drift detector for Fuaran op-apply telemetry. Computes per-OpKind aggregate metrics (success rate, p50/p95 latency, top decoder-rejection reasons, top NodeNotFound NodeIds) and flags week-on-week success-rate regressions exceeding an operator-tunable threshold (default 10pp). Also ships a deterministic StyleFlag drift detector (Phase 151) — the resolved-style twin that diffs declared-invariant flag sets across two windows of StyleObservation to surface newly-introduced / cleared visual-legibility violations, severity-weighted by the ThemeManifest's invariant weights (semantic visual regression, no pixels, CI-gateable). Manual-run console tool for now (`dotnet run --project src/Fuaran.UI.Telemetry.Drift`); cron-friendly later when an operator-decided threshold is wired into a scheduled job. Companion to Fuaran.UI.Telemetry.Abstractions. Apache-2.0 licensed. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.46.0 | 0 | 8/28/2026 |
| 0.39.0 | 39 | 8/27/2026 |
| 0.35.0 | 97 | 8/24/2026 |
| 0.32.0 | 109 | 8/23/2026 |
| 0.31.0 | 133 | 8/21/2026 |
| 0.30.0 | 112 | 8/21/2026 |
| 0.29.0 | 119 | 8/19/2026 |
| 0.28.0 | 112 | 8/18/2026 |
| 0.27.0 | 109 | 8/18/2026 |
| 0.26.0 | 114 | 8/18/2026 |
| 0.18.0 | 115 | 8/10/2026 |
| 0.15.0 | 105 | 8/9/2026 |
| 0.12.0 | 126 | 7/31/2026 |
| 0.11.0 | 121 | 7/30/2026 |
| 0.10.0 | 121 | 7/29/2026 |
| 0.6.0 | 121 | 7/27/2026 |
| 0.4.0 | 125 | 7/26/2026 |
| 0.3.0 | 133 | 7/24/2026 |