FS.GG.UI.Elmish 0.27.0

Prefix Reserved
dotnet add package FS.GG.UI.Elmish --version 0.27.0
                    
NuGet\Install-Package FS.GG.UI.Elmish -Version 0.27.0
                    
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="FS.GG.UI.Elmish" Version="0.27.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FS.GG.UI.Elmish" Version="0.27.0" />
                    
Directory.Packages.props
<PackageReference Include="FS.GG.UI.Elmish" />
                    
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 FS.GG.UI.Elmish --version 0.27.0
                    
#r "nuget: FS.GG.UI.Elmish, 0.27.0"
                    
#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 FS.GG.UI.Elmish@0.27.0
                    
#: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=FS.GG.UI.Elmish&version=0.27.0
                    
Install as a Cake Addin
#tool nuget:?package=FS.GG.UI.Elmish&version=0.27.0
                    
Install as a Cake Tool

FS.GG.UI.Elmish

Elmish adapter contracts for FS.GG.UI V3 products.

FS.GG.UI.Elmish is one of the FS.GG.UI distribution packages — an F# / Elmish UI and 2D scene-graph framework for .NET 10 desktop, rendered through Vulkan + SkiaSharp.

Which adapter? FS.GG.UI.Elmish is the pure scene adapter (ElmishAdapter): your render projects the model to a SceneNode, and init/update stay pure, returning the next model plus effect values interpreted at the host boundary (it bridges viewer messages and effects into Elmish envelopes over Viewer.runInteractiveViewer). For a product built on the semantic control set — buttons, text boxes, grids — use the sibling package FS.GG.UI.Controls.Elmish (runInteractiveApp), which every FS.GG.UI sample uses. Both are supported; pick by whether your view produces a SceneNode or a Control<'msg> tree.

Install

dotnet add package FS.GG.UI.Elmish

Or scaffold a full governed project that wires the FS.GG.UI packages together:

dotnet new install FS.GG.UI.Template
dotnet new fs-gg-ui -o MyApp

Usage

The adapter wraps your own Elmish model/msg together with the viewer. It is a viewer bridge, not your MVU runtime: a ViewerMsg advances the viewer and rebuilds the scene from the current user model, while a UserMsg is a pass-through — it forwards your message as a DispatchUser effect and leaves the model and scene unchanged. You supply a render function that projects your model to a SceneNode; the adapter re-renders it on a ViewerMsg, and your product composes its own update around the adapter (interpret DispatchUser by running your update, then reflect the next user model back so the following ViewerMsg re-renders it).

open FS.GG.UI.Scene
open FS.GG.UI.SkiaViewer
open FS.GG.UI.Elmish

// Your own Elmish model/msg — and your own pure update (the adapter never folds this).
type Model = { Count: int }
type Msg = Increment

let update (msg: Msg) (model: Model) : Model =
    match msg with
    | Increment -> { model with Count = model.Count + 1 }

// Project the user model into a scene
let render (model: Model) : SceneNode =
    Text((20.0, 40.0), $"Count: {model.Count}", Colors.black)

let options = { Title = "Counter"; InitialSize = { Width = 640; Height = 480 } }

// Initialise the combined adapter model + initial effects
let initial, startupEffects =
    ElmishAdapter.init options { Count = 0 } (render { Count = 0 })

// Pass a user message through the adapter. `UserMsg` is a pass-through: it yields a
// `DispatchUser` effect and leaves `passthrough.UserModel`/scene unchanged (the scene is
// rebuilt via `render` only on a `ViewerMsg`).
let passthrough, effects =
    ElmishAdapter.update render (UserMsg Increment) initial

// Compose YOUR update around the adapter: interpret the `DispatchUser` effect by folding
// your own `update`, then reflect the next user model back so the following `ViewerMsg`
// re-renders the scene from it.
let folded =
    match effects with
    | [ DispatchUser m ] ->
        let userModel' = update m passthrough.UserModel
        { passthrough with UserModel = userModel'; Scene = render userModel' }
    | _ -> passthrough

API at a glance

  • ElmishAdapter.init — builds the combined ElmishAdapterModel<'model> from ViewerOptions, your initial user model, and an initial SceneNode, returning the model and its startup effects.
  • ElmishAdapter.update — advances the adapter on an ElmishAdapterMsg<'msg>: a ViewerMsg steps the viewer and refreshes the scene via render, while a UserMsg is forwarded verbatim as a DispatchUser effect — your user model is not folded here, so compose your own update around the adapter. Yields the next model plus effects.
  • ElmishAdapterModel<'model> — the bridged state record holding your UserModel, the current Scene (a SceneNode), and the ViewerModel.
  • ElmishAdapterMsg<'msg> — message envelope: UserMsg carries your own messages, ViewerMsg carries viewer messages.
  • ElmishAdapterEffect<'msg> — effect envelope: DispatchUser for your messages and DispatchViewer for ViewerEffects.
  • TransitionHost.beginTransition — allocates a newer typed generation for an expensive target and returns pure presentation/focus directives for a React host.
  • TransitionHost.update — accepts generation-bound delayed responses, exact post-commit acknowledgements, visibility edges, and controlled/global input observations. Stale work is rejected into the typed ledger.
  • TransitionHost.isPending — identifies the interval in which old-DOM global dispatch and pointer capture must be suppressed while controlled input remains synchronous.

For React hosts, interpret every RequestPresentation in a fresh startTransition, including work that resumes after await. Dispatch Presented presentation.Token from a layout effect only after that exact DOM revision commits. Do not transition controlled text or file setters: send their TransitionHostInput values synchronously. Forward document.visibilityState edges so hidden work is retained and one resume request converges to the newest generation. The complete host recipe and typed example live in template/fragments/elmish/README.md.

Versioning

All FS.GG.UI.* libraries share one version and move together. In a generated project a single <FsGgUiVersion> in Directory.Packages.props pins every package — upgrading is one edit; see docs/UPGRADING.md. Pre-release versions use a -preview.N suffix.

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 (1)

Showing the top 1 NuGet packages that depend on FS.GG.UI.Elmish:

Package Downloads
FS.GG.UI

Optional BOM / metapackage for the FS.GG.UI framework. Reference this single package at one version to pin the entire coherent FS.GG.UI.* set to that version; any attempt to mix a member at a different version fails loudly at restore/build. Ships no assembly — dependencies only.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.27.0 0 8/22/2026
0.26.0 619 8/3/2026
0.21.1 1,181 7/26/2026
0.21.0 170 7/26/2026
0.20.0 176 7/26/2026
0.19.0 312 7/23/2026
0.18.6 165 7/23/2026
0.18.5 165 7/22/2026
0.18.4 144 7/22/2026
0.18.0 248 7/22/2026
0.15.0 335 7/20/2026
0.14.0 175 7/19/2026
0.13.0 206 7/18/2026
0.12.0 328 7/17/2026
0.11.0 379 7/16/2026
0.10.0 436 7/14/2026
0.9.2 483 7/13/2026
0.9.0 581 7/11/2026
0.8.0 233 7/11/2026
0.7.0 183 7/11/2026
Loading failed