Controls Releases
Release notes for the MAUI packages (Shiny.Maui.Controls, Shiny.Maui.Controls.Markdown, Shiny.Maui.Controls.MermaidDiagrams) and the Blazor packages (Shiny.Blazor.Controls, Shiny.Blazor.Controls.Markdown, Shiny.Blazor.Controls.MermaidDiagrams).
1.0 - TBD
Section titled “1.0 - TBD”Shiny.Blazor.Controls, with Markdown and Mermaid Diagrams in their own Shiny.Blazor.Controls.Markdown and Shiny.Blazor.Controls.MermaidDiagrams packages. Drop them into any .razor page — no DI registration required, just @using directivesOverlayHost, pan gestures, locked mode, fit-content auto-sizing, and keyboard handling. Includes ShinyContentPage convenience base class. Replaces the previous SheetView on MAUI (MAUI). Blazor retains SheetView as its equivalent componentHideCharacter, configurable length, cell sizing, colors, and keyboard type (MAUI + Blazor)IsOpen (MAUI + Blazor)FontSizePicker and FontSizePickerButton for size selection. Integrated into the ImageEditor toolbar (MAUI)Address results with coordinates, country code filtering, and pluggable IAddressSearchProvider for custom geocoding services (MAUI + Blazor)ColorPicker or a ColorPickerButton that opens a popup dialog with auto-contrast text (MAUI + Blazor)ShinyDurationPicker) that opens a FloatingPanel with hour/minute selection, “hr”/“min” labels, min/max constraints, and configurable minute intervals. The DurationPickerCell TableView cell uses the same FloatingPanel-based picker internally. Requires ShinyContentPage (MAUI)UIVisualEffectView with theme-aware UIBlurEffect for true real-time backdrop blur. Android 12+ captures the background behind the view and applies RenderEffect blur for per-view frosted glass. Blazor uses CSS backdrop-filter: blur(). Configurable blur radius, tint color/opacity, and corner radius. Falls back to semi-transparent tint on older Android (MAUI + Blazor)DataTemplate and DataTemplateSelector properties (MessageTemplate, MessageTemplateSelector) for controlling how each chat message bubble’s content is rendered. Enables action buttons, cards, rich content, or any custom layout per message type while ChatView still manages bubble chrome (avatar, name, timestamp, colors, alignment) (MAUI)Use24Hour property switches between 24-hour and AM/PM format; MinuteInterval constrains minute selection (iOS enforces natively via UIDatePicker.MinuteInterval, other platforms snap to nearest interval on selection) (MAUI)IToaster.ShowAsync(text, cfg => {...}) (MAUI) or IToastService.ShowAsync(...) (Blazor). Supports auto-dismiss with configurable duration, manual dismiss via IDisposable, pill or fill-horizontal display modes, top/bottom positioning, queue or stack mode for multiple toasts, indeterminate spinner, countdown progress bar, icon, tap command/callback, full styling (colors, border, corner radius), feedback, screen reader announce, and iOS safe area awareness. No XAML or OverlayHost required — the overlay auto-attaches on first use (MAUI + Blazor)ClearButtonTool (auto-shows/hides) and speech-to-text tools in the SpeechAddins packages (MAUI uses ISpeechToTextService, Blazor uses Web Speech API). Tools are TextEntryTool subclasses on both hosts with lifecycle hooks for parent text access (MAUI + Blazor)Mask property enables declarative input formatting with # as digit placeholder and auto-inserted literal characters. Supports phone numbers (###) ###-####, credit cards #### #### #### ####, dates ##/##/####, SSN, ZIP codes, and custom patterns. Text always contains raw digits for clean binding/validation; FormattedText provides the display value. Keyboard auto-sets to Numeric, cursor positioning handled on both platforms (MAUI + Blazor)TextEntryTool subclass that increments or decrements the numeric value in a TextEntry by a configurable Step amount on each tap. Auto-displays +N or -N as button text when Text is not explicitly set. Place in LeftTools (decrement) and RightTools (increment) for a numeric stepper pattern (MAUI + Blazor)ChatMessage.IsSent property dims the bubble (50% opacity) for user messages until set to true, providing visual feedback for pending server confirmation (MAUI + Blazor)ChatMessage.Identifier optional string property for attaching user-defined context (e.g., server message ID) to a message after it is sent (MAUI + Blazor)ChatMessage.Acknowledgements list of Acknowledgement objects (Glyph, UserId, Timestamp) rendered as grouped reaction badges below the chat bubble. Badges show the glyph emoji with a count when more than one user reacted with the same glyph (MAUI + Blazor)Value/Minimum/Maximum, indeterminate mode with sliding animation, text overlay with configurable format, and pulse triggers on value change or timed interval. Pulse has configurable PulseLength (sheen width as fraction of fill) and PulseSpeed (ms for one sweep). Gradient mode uses GradientStartColor/GradientEndColor for a linear gradient fill (MAUI + Blazor)Overlay supports any custom content via DataTemplate (MAUI) or RenderFragment (Blazor). The LoadingOverlay subclass provides a built-in loading template with either an indeterminate spinner (ActivityIndicator) or a determinate progress bar (using the ProgressBar control). Bindable IsShown property for show/hide with smooth animation, plus Message text support (MAUI + Blazor)SnapCount property (int, default 1) controls snap behavior. Set to 0 for Netflix-style free scrolling with no snapping. Works across all platforms: Android attaches/detaches LinearSnapHelper, iOS adjusts deceleration rate and targeting, Windows toggles SnapPointsType, Blazor uses CSS scroll-snap-type (MAUI + Blazor)IFeedbackService. The default HapticFeedbackService provides tactile click/long-press feedback. Replace it with SetCustomFeedback<T>() in UseShinyControls() to implement text-to-speech, sound effects, analytics, or any custom response. ChatView passes message text as details, enabling TTS for incoming messages. Every control’s UseFeedback property (default true) gates whether feedback firesShiny.Maui.Controls.Barcodes and Shiny.Blazor.Controls.Barcodes) — Pure-managed 1D and 2D barcode renderer powered by ZXing.Net, with a custom PNG encoder built on zlib + CRC32 + Adler32 (no SkiaSharp, no System.Drawing — AOT-safe on every TFM, ships clean on iOS, Android, Mac Catalyst, Windows, and Blazor WebAssembly). BarcodeView (a ContentView on MAUI, a Razor component on Blazor) renders any of 13 symbologies — QRCode, Aztec, DataMatrix, Pdf417, Code128, Code39, Code93, Codabar, Ean8, Ean13, UpcA, UpcE, Itf — with bindable Value, Format, PixelWidth, PixelHeight, MarginPixels, ForegroundColor, and BarcodeBackgroundColor. QRCodeView is a BarcodeView subclass that locks Format to QRCode, exposes a single square Size property, and adds ErrorCorrection (Low / Medium / Quartile / High — higher tolerates more damage at the cost of capacity). On Blazor, output defaults to inline SVG with shape-rendering="crispEdges" and a single horizontal-run <path> so it scales infinitely without aliasing and stays tiny in DOM size; switching ImageFormat to Png renders an <img> with a data: URI. Optional CssWidth / CssHeight decouple the encoder resolution from the host element’s CSS size. For headless rendering — PDF exports, email attachments, label printing — the static BarcodeRenderer exposes RenderPng(string, BarcodeFormat, BarcodeRenderOptions?), RenderSvg(...), and RenderDataUri(...). Invalid 1D payloads (e.g. EAN-13 with non-numeric content) silently clear the image instead of throwing. XAML namespace xmlns:bc="http://shiny.net/maui/barcodes" (MAUI + Blazor)Desktop add-on (Shiny.Maui.Controls.Desktop) — A single MAUI-desktop-only package that bundles two features sharing the same TFM matrix (net10.0;-windows;-maccatalyst;-macos + Linux GTK4):
Tray Icon (Shiny.Maui.Controls.Desktop.TrayIcon namespace) — Cross-platform system tray / status-bar / menu-bar icon. Supports Windows (Shell_NotifyIcon via Win32 P/Invoke with a message-only window for click routing), macOS AppKit (native NSStatusItem via the net10.0-macos bindings), MacCatalyst (bridges to AppKit at runtime via the Objective-C runtime with [UnmanagedCallersOnly] trampolines for menu callbacks), and Linux (libayatana-appindicator3 + GTK 3 — depends on libayatana-appindicator3-1 and libgtk-3-0 system packages). API: ITrayIconFactory resolved from DI, ITrayIcon with SetIcon(Func<Stream>), Tooltip, Title, Badge, IsVisible, IsTemplateImage (macOS dark/light auto-tint), SetMenu(TrayMenu), ShowMenu(), ShowNotification(title, message), StartAnimation(frames, interval) / StopAnimation() / IsAnimating, and PrimaryClick/SecondaryClick/DoubleClick events. Menus are built fluently with TrayMenu.Build(b => b.Item(...).Check(...).Separator().Submenu(...)); TrayMenuItem supports per-item Icon (Func<Stream> rendered next to the label on all four platforms) and Accelerator strings parsed by TrayAccelerator and dispatched via the OS — RegisterHotKey on Windows (process-global), native KeyEquivalent + modifier mask on macOS / Catalyst (app-foreground), and gtk_widget_add_accelerator on a GtkAccelGroup on Linux (menu-focused, best-effort). Mutating any item rebuilds the native menu automatically. Badge renders as a composited red pill on the Windows HICON (System.Drawing.Common, Windows TFM only) and beside the icon on macOS / Linux. ShowNotification routes to Shell_NotifyIcon NIF_INFO on Windows, NSUserNotificationCenter on macOS / Catalyst, and libnotify on Linux (no-op when libnotify is missing). Windows auto-wraps PNG bytes in an ICO container so the same PNG asset works on every platform. Register with .UseTrayIcon() in MauiProgram.cs. (Migrating from the previous standalone Shiny.Maui.Controls.TrayIcon package: swap your <PackageReference> and change using Shiny.Maui.Controls.TrayIcon; to using Shiny.Maui.Controls.Desktop.TrayIcon; — the UseTrayIcon() extension method in the Shiny namespace is unchanged.)
On-Screen Keyboard (Shiny.Maui.Controls.Desktop.OnScreenKeyboard namespace; companion Shiny.Blazor.Controls.Kiosk.OnScreenKeyboard for Blazor) — Touch / kiosk on-screen keyboard for desktop apps and Blazor. US-QWERTY with three layers (lowercase / Shift / 123-symbols), bottom-docked, auto-shows when an Entry / Editor (MAUI) or <input> / <textarea> (Blazor) gains focus. Critically does NOT steal focus when keys are tapped — every key uses pointerdown + preventDefault() (Blazor) or Focusable = false + intercepted PointerPressed (MAUI). Press-and-hold autorepeat (400ms delay, 50ms interval, both configurable). Dispatches into the focused control via managed Text mutation at CursorPosition (MAUI) or document.execCommand('insertText', char) after focus restore (Blazor) — no native synthetic key events in v0.1, so no macOS Accessibility entitlement required and Mac App Store distribution is fine. Full AutomationPeer (Windows / MAUI / GTK) and ARIA role="button" + aria-keyshortcuts (Blazor) tree so switch-input users can step through keys. Theme tokens (OnScreenKeyboardKeyBrush / --shiny-osk-key-bg etc.) mirror docking’s pattern. Public surface: IOnScreenKeyboard (MAUI) / IOnScreenKeyboardService (Blazor) with Show() / Hide() / Toggle() / IsVisible / VisibilityChanged, and an OnScreenKeyboardOptions for auto-show-on-focus, push-content vs overlay, height, theme, and autorepeat timing. Register with .UseOnScreenKeyboard(opts => ...) on MAUI or services.AddShinyOnScreenKeyboard(opts => ...) on Blazor. Limitations documented up front: MAUI inputs / DOM inputs only (no system-wide injection in v0.1 — opt-in pluggable IKeyDispatcher arrives in v0.4), no Shadow DOM, no IME / dead-key composition (v0.5), no language switching (v0.3 via JSON layout files).
Docking (Shiny.Maui.Controls.Desktop.Docking namespace; companion Shiny.Blazor.Controls.Kiosk for Blazor (kiosk-shaped add-on, namespace Shiny.Blazor.Controls.Kiosk.Docking, also home to the on-screen keyboard)) — Visual-Studio-style window docking for desktop apps. Dockable tool windows, tabbed groups, draggable splitters, auto-hide rails, and tear-off floating windows. DockHostView (MAUI) / <DockHost /> (Blazor) attaches inside any existing page — not a ContentPage subclass, so consumers keep their Shell architecture. Public surface: layout schema POCOs (DockRoot, DockWindowState, DockSplit, DockGroup, DockEmpty, DockTab) with [JsonPolymorphic] + a source-generated JsonSerializerContext for AOT-safe JSON round-trip via DockSerialization.Serialize/Deserialize; contracts IDockHost (per-window controller with LoadAsync / Snapshot / ShowPanelAsync / IsLocked), IDockableContentFactory (async Task<View> CreateAsync(string instanceId, ...) for MAUI / Task<RenderFragment> for Blazor — registered via .AddDockPanel<TView>("panel-id")), IDockLayoutStore (bring-your-own — no default ships), IDockLayoutMigrator (forward-only schema migrations), IDockEvents (LayoutChanged / PanelActivated / DragStarted / DragCompleted / DragCancelled), and IDockCommandScope (scopes Ctrl+W close-tab, Ctrl+Tab MRU, Ctrl+Alt+PgUp/Dn group nav to the dock surface). Schema versioning (SchemaVersion + MinReadableVersion) is wired in from day one, and unknown PanelTypeIds land in a missing-panels tray rather than silently dropping. Register with .UseShinyDocking() + .AddDockPanel<TView>("id") on MAUI, services.AddShinyDocking().AddDockPanel<TComponent>("id") on Blazor. v0.1 ships the package surface (in-window only); drag-drop + diamond drop indicator (v0.2), auto-hide rails + persistence (v0.3), tear-off floating windows on Windows / AppKit / GTK4 via mouse-down implicit capture — no macOS Accessibility entitlement required (v0.4) follow on the roadmap.