Skip to content

Toast

Toast collapses the web contract’s Root/Content/Title/Description/Action/Close part tree into one lookless Control, NaviusToast, plus named template parts. A consumer never constructs NaviusToast directly: a ToastManager (a plain, framework-agnostic C# queue with a visibility limit and per-toast auto-dismiss timers) is bound to a NaviusToastViewport placed in a corner of the window, and ToastManager.Add(ToastOptions) enqueues a toast that the viewport creates, positions, animates, and dismisses on the manager’s behalf.

xmlns:navius="clr-namespace:Navius.Wpf.Primitives.Controls;assembly=Navius.Wpf.Primitives"
xmlns:toast="clr-namespace:Navius.Wpf.Primitives.Controls.Toast;assembly=Navius.Wpf.Primitives"
<Grid>
<!-- app content -->
<navius:NaviusButton Content="Save" Click="OnSaveClick" />
<toast:NaviusToastViewport x:Name="Toasts"
Manager="{Binding ToastManager}"
Alignment="BottomRight" />
</Grid>

The Manager is a plain C# object, typically created once in code-behind or a view model (new ToastManager(limit: 3)) and bound or assigned to the viewport. Enqueue a toast with Manager.Add(new ToastOptions { Title = "Saved", Description = "Your changes were saved." }); the call returns a ToastHandle for later Update/Dismiss/Pause/Resume.

Property Type Default From Description
Manager ToastManager? null NaviusToastViewport The manager whose VisibleToasts this viewport renders. Assign once, usually via binding.
Alignment NaviusToastAlignment BottomRight NaviusToastViewport Which corner or top/bottom-center edge of the host the stack anchors to. No web equivalent by name: the web contract has a single fixed-position viewport styled by the consumer’s own CSS.
Gap double 16 NaviusToastViewport Spacing, in DIPs, between stacked toasts. Matches the web contract’s ToastProviderContext.Gap default.
Index int (attached, read-only) - NaviusToastViewport Published per visible toast, 0 = frontmost/newest, for a custom template to key off; the viewport itself positions toasts directly and does not read this back.
OffsetY double (attached, read-only) - NaviusToastViewport Cumulative offset, in DIPs, from the anchored edge; published alongside Index.
Title string? null NaviusToast Mirrors ToastOptions.Title. Changing it while loaded re-raises the UIA notification.
Description string? null NaviusToast Mirrors ToastOptions.Description.
Type ToastType Default NaviusToast Default | Success | Error | Loading; drives the default template’s visual variant.
Priority ToastPriority Low NaviusToast Low maps to UIA LiveSetting.Polite (the web’s role="status"); High maps to Assertive (role="alert").
ActionLabel string? null NaviusToast Label for the action template part, when present.
ActionAltText string "" NaviusToast Required plain-text description of the action for assistive tech.
ShowCloseButton bool true NaviusToast Whether the close template part renders.
Title / Description / Type / Priority / Duration / Action see ToastOptions see below ToastOptions Per-toast configuration record passed to ToastManager.Add/Update. Duration (TimeSpan?, null) falls back to ToastManager.DefaultDuration; a non-positive value is sticky (no auto-dismiss). Action (ToastActionSpec?, null) pairs a label, an alt-text string, and a click handler.
Limit int 1 ToastManager Max simultaneously-visible toasts; the rest queue and promote, oldest-queued first, as slots free. Live-mutable: changing it re-evaluates the queue and raises Changed immediately.
DefaultDuration TimeSpan 5000ms ToastManager Constructor-only default auto-dismiss duration for toasts that don’t set their own Duration.
Method Description
ToastManager.Add(ToastOptions) -> ToastHandle Enqueues a new toast; returns a handle to update, dismiss, pause, or resume it later.
ToastHandle.Update(ToastOptions) Replaces the toast’s options wholesale and rearms its auto-dismiss timer against the new effective duration (e.g. flipping a loading toast to success).
ToastHandle.Dismiss() Removes the toast immediately.
ToastHandle.Pause() / Resume() Ref-counted pause/resume of the toast’s auto-dismiss timer; multiple sources (hover, focus-within) can each pause without one source’s resume prematurely restarting the countdown.
ToastManager.Clear() Removes every tracked toast immediately.
ToastManager.PauseAll() / ResumeAll() Pause/resume every currently-visible toast’s timer (e.g. on window deactivation/activation).
Event Signature Fires when
NaviusToast.CloseRequested RoutedEventHandler Escape is pressed on a focused toast, or the close template part is clicked; the viewport dismisses the toast via ToastHandle.Dismiss().
NaviusToast.ActionRequested RoutedEventHandler The action template part is clicked; the viewport runs the configured ToastActionSpec.OnClick and then dismisses the toast.
ToastManager.Changed Action (plain CLR event) Raised after Add/Update/Dismiss/Clear/Limit changes; NaviusToastViewport subscribes to resync its visuals.
Key Behavior
Escape (toast focused) Raises CloseRequested; the viewport dismisses the toast.
F6 (anywhere in the window, at least one toast visible) Focuses the viewport. Hardcoded: the web contract’s configurable Hotkey/LabelTemplate are not ported.
Tab Native tab order; each toast is focusable, so the visible stack is reachable.

Swipe-to-dismiss is not implemented in this port (see Web deltas).

NaviusToastAutomationPeer (a FrameworkElementAutomationPeer) reports AutomationControlType.Group (no closer 1:1 UIA control type exists for a transient status/alert region) and GetLiveSettingCore() returns Assertive for High priority, Polite for Low, the UIA analogue of the web’s role="alert"/role="status". On load, and whenever Title or Description changes while loaded, NaviusToast additionally calls AutomationPeer.RaiseNotificationEvent directly, a more direct and better-supported mechanism than duplicating text into a hidden aria-live region; GetLiveSettingCore’s value remains the fallback for OS/AT combinations where the notification event isn’t observed (RaiseNotificationEvent requires Windows 10 version 1709+). Covered by NaviusToastAutomationPeer_LiveSetting_MatchesPriority and a dedicated Escape-key regression test in ToastTests.cs (31 tests total, most running as plain [Fact]s against a manual-advance timer double with no live Dispatcher needed).

  • The web’s five-part tree (Root/Content/Title/Description/Action/Close) plus a separate Provider/Portal collapses into one lookless NaviusToast (with PART_Close/PART_Action template parts) rendered by NaviusToastViewport; there is no NaviusToastProvider or NaviusToastPortal, since there is no cascading-context/DI surface or portal concept to replicate.
  • Live-region mechanism replaced outright: instead of duplicating announcement text into hidden aria-live regions, the WPF port raises a genuine UIA notification event (RaiseNotificationEvent), with GetLiveSettingCore kept only as a fallback for older OS/AT combinations.
  • F6 is hardcoded rather than configurable: the web’s Hotkey: string[] and LabelTemplate parameters are not ported. The parity task’s own accessibility audit found the web’s documented hotkey claim inaccurate, so this port only commits to the one hotkey it actually tests.
  • Swipe-to-dismiss (SwipeDirection/SwipeThreshold) is not implemented: hover-pause and Escape/close-button dismiss cover this milestone’s interaction surface; drag-to-dismiss was scoped out as a separately-testable follow-up.
  • NaviusToastPositioner/NaviusToastArrow are retired: confirmed unwired stubs upstream (the web contract itself notes they are “not used by the primary viewport-stacked toast”), and no anchored-toast variant exists in either port.
  • Queueing is promotion-based, not just eviction-based: the first Limit toasts by insertion order stay visible, and anything beyond that queues until an earlier toast is dismissed and a slot promotes the next-oldest queued toast. Limit is also live-mutable at runtime, a detail the web contract’s Provider.Limit parameter does not specify either way.
  • Stacking and positioning are C#-computed (Reflow() sets Canvas.Top/Bottom/Left/Right per toast from measured ActualHeight plus Gap) rather than CSS custom properties; NaviusToastViewport.Index/OffsetY are read-only attached properties published for a custom template, mirroring the web’s “Content publishes vars, never computes a transform” split.

The Toast Gallery page rendered at the pinned commit, in each theme.

Toast Gallery page in the light theme

Toast Gallery page in the dark theme

Toast Gallery page in the high contrast theme