- name
- shiny-controls
- description
- Generate UI for .NET MAUI (Shiny.Maui.Controls) and Blazor (Shiny.Blazor.Controls) - includes TableView with 14 cell types, TreeView with lazy loading, drag/drop reorder (above/below/into), and configurable expand/collapse icons, FloatingPanel/OverlayHost/ShinyContentPage (bottom/top overlay panels) with detents and header peek, DurationPicker (duration picker with FloatingPanel), FrostedGlassView (native blur/glass effect), Toast service (code-invoked toast notifications with queue/stack, auto-dismiss, spinner, progress bar, pill/fill modes), PillView status badges, BadgeView (content-wrapping corner badge with text/dot/count overflow and pulse), ShinyImage (remote image loading on both hosts — placeholder artwork, a loading ring that fills to a real percentage when the response carries a Content-Length and spins when it does not or when the request is still queued, error artwork, and full LoadingTemplate/ErrorTemplate overrides; on MAUI an IImageService owns memory + disk caching with LRU trimming and expiry, a bounded download queue, and de-duplication of concurrent requests for the same URI, with a replaceable IImageDownloader for authenticated images and ClearCacheAsync/GetCacheSizeAsync/PrefetchAsync for cache management; on Blazor the image is streamed through fetch for genuine progress with an automatic plain-img fallback when CORS blocks it, and caching is left to the browser), ImageViewer with pinch/pan/double-tap zoom, ImageEditor with crop/rotate/draw/text/undo/redo/export, ChatView with bubbles/typing/load-more/input-bar and custom MessageTemplate/MessageTemplateSelector for per-message rendering, SecurityPin entry, ShinyButton (stateful button on both hosts with Normal/Busy/Success/Error states, per-state text and icons, an auto-revert delay, three busy modes (ReplaceLeftIcon/ReplaceContent/KeepContent), leading and trailing icon slots that each take an ImageSource, a motion-icon name, or an arbitrary view, and Appearance × Type styling (Filled/Tonal/Outlined/Text/Elevated × Primary/Secondary/Success/Warning/Critical/Info) resolved from the theme tokens; on MAUI it follows its Command's CanExecute through IsEnabledCore — so an explicitly disabled button stays disabled — and drives its own busy state while an async command runs, with no IsBusy binding needed; on Blazor the equivalent is that Clicked is awaited), Fab and FabMenu (floating action button and expanding action menu), Scheduler views (calendar grid, agenda timeline, event list), Markdown controls (MarkdownView renderer, MarkdownEditor with toolbar), Barcodes & QR codes (separate Shiny.Maui.Controls.Barcodes / Shiny.Blazor.Controls.Barcodes packages — BarcodeView and QRCodeView with 13 symbologies including QR, Aztec, Data Matrix, PDF417, Code 128/39/93, Codabar, EAN-8/13, UPC-A/E, ITF — pure-managed ZXing.Net renderer, PNG output via built-in encoder on MAUI, SVG or PNG data-URI on Blazor, with a static BarcodeRenderer for raw bytes / SVG / data-URI from code), CameraView (separate Shiny.Maui.Controls.Camera / Shiny.Blazor.Controls.Camera packages — cross-platform camera preview on iOS, Android, Windows, macOS AppKit, and Blazor WASM with zoom, torch, lens/device selection, photo + video capture, and live color filters (Mono/Noir/Sepia/Vivid/Cool/Warm/Fade/Chrome/Instant/Tonal) applied to the live preview and captured photos; a pluggable IFrameAnalyzer pipeline where each analyzer raises its own strongly-typed event (or bindable Command), can be declared right in XAML, added/removed live or toggled on/off via IsEnabled, and draws styled OverlayBoxes via the built-in CameraOverlayView; modular analyzer add-ons Shiny.Maui.Controls.Camera.Barcode/.Face/.Motion/.Ocr/.Documents scan barcodes, detect faces and motion (a box per distinct moving region), run OCR, and extract structured documents — invoices with order lines, AAMVA driver's licenses, health cards, credit cards (brand via IIN+Luhn), and passports (deterministic MRZ) each as their own analyzer returning a strong record with nullable fields + a typed event; registered with .UseShinyCamera()), …
- auto_invoke
- true
- triggers
- ["tableview","table view","settings page","settings view","settingsview","treeview","tree view","tree control","hierarchical view","hierarchy","file browser","folder browser","folder picker","directory tree","lazy load tree","expandable list","nested list","tree node","org chart","blazor treeview","blazor tree view","sheet view","sheetview","bottom sheet","bottomsheet","floating panel","floatingpanel","overlay host","overlayhost","shiny content page","shinycontentpage","pill","[Truncated]"]
- references
- ["layout.md","toolbar-tabbar.md","tableview.md","datagrid.md","treeview.md","floating-panel.md","pillview.md","shiny-image.md","image-viewer.md","image-editor.md","media-picker-button.md","chatview.md","security-pin.md","button.md","fab.md","markdown.md","scheduler.md","autocomplete.md","country-picker.md","address-entry.md","signature-pad.md","pickers.md","frosted-glass.md","toast.md","dialogs.md","textentry.md","slider.md","range-slider.md","progressbar.md","overlay.md","skeleton.md","wizard.md","[Truncated]"]
# Shiny Controls Skill
You are an expert in the Shiny Controls library, which ships a single shared control surface across two hosts:
- **.NET MAUI** — `Shiny.Maui.Controls` (plus `Shiny.Maui.Controls.Markdown`, `Shiny.Maui.Controls.MermaidDiagrams`)
- **Blazor** — `Shiny.Blazor.Controls` (plus `Shiny.Blazor.Controls.Markdown`, `Shiny.Blazor.Controls.MermaidDiagrams`)
Every control below is available on **both** MAUI and Blazor. The feature set (properties, events, behavior) is intentionally mirrored — the same concepts apply on either host; only the syntax differs (XAML + `BindableProperty` on MAUI, Razor markup + `[Parameter]` on Blazor).
The library contains:
- **TableView**: A pure MAUI settings-style TableView with 14 cell types, cascading styles, sections, drag-sort reordering, and full MVVM/binding support
- **DataGrid** (MAUI + Blazor): A feature-rich data grid modeled on MudBlazor. Blazor is a generic `DataGrid<TItem>` rendering an HTML `<table>` with child `PropertyColumn`/`TemplateColumn`; MAUI is a pure cross-platform composite (`shiny:DataGrid` + `DataGridColumn`/`DataGridTemplateColumn`, items as `object`) built on a `Grid` header + virtualized `CollectionView` (no native handlers). Sorting (single/multi), filtering (menu/row/toolbar), grouping + aggregates, single/multi selection w/ checkboxes, inline editing (cell/form), paging, virtualization, column resize/reorder, sticky header, `ServerData` delegate, density/striped/bordered/hover. See datagrid.md
- **TreeView**: Hierarchical tree with lazy-loaded branches (`ChildrenLoader` for per-node async, `RootLoader` for async root), `ChildrenSelector` for sync data, `HasChildrenSelector`/`CanExpandSelector`/`CanSelectSelector` predicates, configurable `ExpandedIcon`/`CollapsedIcon`/`RetryIcon` (ImageSource on MAUI, RenderFragment slots on Blazor), single/multi selection with two-way `SelectedItem`/`SelectedItems` (multi-select renders a checkbox per row — `ShowSelectionCheckBoxes` to turn it off — and switching modes clears the selection), events + ICommand mirrors for `ItemSelected`/`ItemExpanded`/`ItemCollapsed`/`LoadFailed`/`ItemDropped`, indent + guide lines, drag/drop reorder with above/below/into drop positions and visual drop indicators (event-only — never mutates your data; native HTML5 drag via JS interop on Blazor for Safari/Firefox support, pan-gesture fallback on Catalyst/AppKit/GTK4), programmatic API (`ExpandAll`/`ExpandAllAsync` — both materialize every sync branch and cap at a `maxDepth` of 32 — plus `CollapseAll`/`Expand`/`Collapse`/`SelectAll`/`DeselectAll`/`SetBranchSelected`/`Refresh`/`ReloadAsync` with state preservation/`FindNode`), and keyboard navigation on Blazor
- **FloatingPanel + OverlayHost**: A floating panel overlay system (MAUI only). Panels slide from bottom or top with configurable detents, header peek when closed, backdrop dimming, and feedback. Multiple panels coexist without blocking touches. Use with `OverlayHost` (manual Grid setup) or `ShinyContentPage` (convenience ContentPage with built-in overlay). Blazor uses `SheetView` with CSS-based overlays instead
- **PillView**: A status badge/label control with 6 preset themes, custom colors, and WCAG-accessible contrast
- **BadgeView**: A content-wrapping overlay that pins a small badge to one of the four corners (`TopLeft`/`TopRight`/`BottomLeft`/`BottomRight`) of a wrapped view. Setting `Text` to an empty string auto-hides the badge — bind your unread/count value directly. Supports configurable `BadgeColor`/`BadgeTextColor`/`BadgeBorderColor`/`BadgeBorderThickness`, `IsDot` mode for simple notification indicators, `MaxCount` numeric overflow rendering ("99+"), per-corner `OffsetX`/`OffsetY` nudge (default hangs the badge slightly outside the corner), scale-in/out animation (`IsAnimated`), and optional continuous `IsPulsing` to draw attention. Blazor honors `prefers-reduced-motion`
- **ImageViewer**: A tappable thumbnail plus a full-screen image overlay with pinch-to-zoom, pan when zoomed, double-tap to toggle zoom, animated open/close, and a close button. On MAUI both surfaces are a `ShinyImage`, so binding `Uri` instead of `Source` adds placeholder artwork, a loading ring, error artwork and `IImageService` memory/disk caching — the overlay opens off the cache the thumbnail already warmed. See image-viewer.md
- **ImageEditor**: An inline image editor with cropping (drag-handle selection with dimmed overlay), rotation, freehand drawing with color, text annotations, undo/redo, reset, and export to PNG/JPEG/WEBP at configurable resolutions
- **MediaPickerButton**: A button that adds photos from the gallery and/or camera (built-in `MediaPicker` on MAUI; `<input type=file>`/`capture` on Blazor), compresses/re-encodes each to PNG or JPEG at a chosen quality (with optional max-dimension downscale), caps the count with `MaxPhotos` (added one at a time), and shows the collected photos inline as a tappable carousel (`ShowAsCarouselInView`, opening the ImageViewer with an optional Edit button that reuses the ImageEditor) or a compact pinch/zoom overlay. `AllowGallery`/`AllowCamera`/`AllowPhotoEdit` toggles, `PermissionDeniedText`, `NoImagesTemplate`, and a two-way `Photos` collection of `MediaPickerItem`. See media-picker-button.md
- **ChatView**: A modern chat UI with message bubbles, per-participant colors and avatars, visual grouping by sender/minute, typing indicators, virtualized message list with load-more, auto-link detection, image messages, and a bottom input bar with send/attach
- **SecurityPin**: A PIN/OTP entry control with individual cells, configurable length, keyboard, and optional character masking
- **Fab**: A Material-style floating action button with Icon, Text, Command, custom colors, border, and shadow
- **FabMenu**: A floating action menu with an expanding, animated child `FabMenuItem` stack and two-way `IsOpen`
- **SchedulerCalendarView**: Monthly calendar grid with swipe navigation, event display, and pinch-to-zoom
- **SchedulerAgendaView**: Day/multi-day timeline (`DaysToShow` 1–7) with overlap detection, switchable date picker modes (`DatePickerMode`: Carousel / Calendar / None), additional timezone columns, auto-updating current time marker, and 12/24-hour time — full feature parity on MAUI and Blazor
- **SchedulerCalendarListView**: Vertically scrolling event list grouped by day with infinite scroll and sticky day headers (`StickyDayHeaders`, default true, pins the current day header while scrolling)
- **MarkdownView**: A read-only markdown renderer that converts markdown text to native MAUI controls with theming and link handling
- **MarkdownEditor**: A markdown editor with formatting toolbar, live preview toggle, and customizable toolbar items
- **BarcodeView / QRCodeView** (separate `Shiny.Maui.Controls.Barcodes` / `Shiny.Blazor.Controls.Barcodes` packages): Pure-managed barcode rendering powered by ZXing.Net. Supports 13 symbologies (`QRCode`, `Aztec`, `DataMatrix`, `Pdf417`, `Code128`, `Code39`, `Code93`, `Codabar`, `Ean8`, `Ean13`, `UpcA`, `UpcE`, `Itf`). MAUI renders to PNG via a built-in pure-managed encoder (no SkiaSharp / `System.Drawing` dependency, AOT-safe) and feeds an `Image`. Blazor renders inline SVG by default (crisp at any size, single-path output with `shape-rendering="crispEdges"`) or a PNG `data:` URI. `QRCodeView` is a `BarcodeView` subclass that locks `Format = QRCode` and adds `Size` (square edge length) and `ErrorCorrection` (`Low`/`Medium`/`Quartile`/`High`). The static `BarcodeRenderer` exposes `RenderPng`, `RenderSvg`, and `RenderDataUri` for raw output without a view. XAML namespace `xmlns:bc="http://shiny.net/maui/barcodes"`
- **AutoCompleteEntry**: A text input with debounced search, dropdown suggestions, busy indicator, custom item templates, and full styling control via CSS custom properties (Blazor) or bindable properties (MAUI)
- **CountryPicker**: A country search control built on AutoCompleteEntry with flag emoji, country name, and dial code
- **AddressEntry**: An address search control built on AutoCompleteEntry with geocoding (Nominatim/OpenStreetMap by default) and structured address results
- **SignaturePad**: A signature capture control that opens in a FloatingPanel (MAUI) or SheetView (Blazor). Users draw on a canvas and export to PNG. Configurable stroke color/width, background, export dimensions, sign/cancel buttons, and panel styling. Like FloatingPanel, it must be placed inside an `OverlayHost` or `ShinyContentPage` (MAUI). The Sign button is disabled until the user draws something
- **Toast**: A service-first toast notification system invoked via DI-injected `IToaster` (registered by `UseShinyControls()`). 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, feedback, and screen reader announcement. No XAML or OverlayHost required — the overlay auto-attaches to the current page. Blazor uses `IToastService` with `<ToastHost>` component
- **Dialogs** (MAUI + Blazor): A service-first dialog system that emulates `alert`/`confirm`/`prompt` with owned (non-native), animated, themeable dialogs. Inject `IDialogService` and await `Alert` (Task), `Confirm` (Task<bool>), or `Prompt` (Task<PromptResult>). Queued/modal, backdrop cancel (Escape/Enter on Blazor), theme-token colors. Per-call `configure` sets the `DialogAnimation` (None/Fade/SlideTop/SlideBottom/SlideLeft/SlideRight/Zoom/Pop) and styling; customize globally via `ConfigureDialogs` (MAUI) / `AddShinyDialogs(o => ...)` (Blazor) or fully replace the card with a `ContentTemplate` (MAUI `DataTemplate`) / `<DialogHost Template>` (Blazor `RenderFragment<DialogContext>`). MAUI auto-attaches (just `UseShinyControls()`); Blazor needs `AddShinyDialogs()` + a single `<DialogHost>`
- **TextEntry**: A Material Design-inspired text entry control with animated floating placeholder, customizable border, left/right tool slots, hint text for validation, character count, read-only/password modes, and reusable tools (ClearButtonTool, TextEntrySpeechToTextTool)
- **Slider**: A slider control with a two-color gradient track, blended thumb border that samples the gradient at the current position, tooltip with custom templates, and full drag/tap interaction
- **RangeSlider**: A two-thumb variant of Slider selecting a lower/upper value pair (`LowerValue`/`UpperValue`). Reuses the gradient (shown across the active segment between thumbs), blended thumb borders, and per-thumb tooltips, and adds `MinimumRange` (hard-stop gap) and `MaximumRange` (pushes the other thumb) constraints. See range-slider.md
- **ProgressBar**: A progress bar with gradient fill and a Vista-style shimmer pulse that sweeps left-to-right. Configurable `PulseLength` (width of sheen) and `PulseSpeed` (sweep duration). Triggers on value change or timed interval. Supports indeterminate mode and text overlay
- **Overlay & LoadingOverlay**: Full-screen overlay with configurable backdrop color and opacity, fade animation, and custom content via `DataTemplate` (MAUI) or `RenderFragment` (Blazor). `LoadingOverlay` extends it with built-in spinner (indeterminate) or progress bar (determinate) plus optional message text. On MAUI it also carries `ContentAlignment` (`Start`/`Center`/`End`, default Center) + `ContentMargin` for content that should sit off-centre — a prompt bar near the top rather than a dialog in the middle — and `ShowEdgeGlow` + `GlowOptions`, which rim the page with the Siri-style animated colour wash for as long as the overlay is up (behind the content, in front of the backdrop, click-through). Quick entry's in-app presentation is built on exactly these rather than its own scrim, so it shares the page's `OverlayHost` backdrop with everything else instead of stacking a second one. A `DataTemplate` that returns the **same** view instance each time is supported, which is how you host one long-lived view rather than rebuilding it per show
- **SkeletonView**: A content-wrapping control (similar to `RefreshView`) that shows animated shimmer placeholders while `IsBusy` is true, then reveals the real content when loading finishes. Built-in line placeholders (configurable `ItemCount`/`ItemHeight`/`ItemSpacing`/`CornerRadius`/`BaseColor`/`ShimmerColor`) or a custom placeholder layout via `SkeletonTemplate` (MAUI) / `SkeletonContent` (Blazor). Shimmer is a sweeping `LinearGradientBrush` band on MAUI and an animated CSS gradient (honoring `prefers-reduced-motion`) on Blazor. Use it for inline content regions; use `LoadingOverlay` for whole-page loading
- **StateView & Wizard** (both hosts, **core** packages): `StateView` shows exactly one of several named branches chosen by a string - the declarative form of the `IsVisible` / `@if/else` ladder. States are `StateViewState` (MAUI `ContentProperty` is `Content`; Blazor renders nothing itself and hands its `ChildContent` to the host, so an unreached branch is never built). Matching is ordinal and case-insensitive, and an unmatched name falls back to `DefaultState` then the first declared state, so a typo shows something rather than a blank rectangle. MAUI adds a lazy `ContentTemplate` (built on first show, cached unless `CacheContent="False"`). `Transition` is `None`/`Fade`/`Slide` (direction taken from the move)/`SlideLeft|Right|Up|Down`/`Scale`. `Wizard` builds on the same model: `WizardStep` **is** a `StateViewState` plus rules. Validity gates are layered cheapest-first - `IsValid`, `IsOptional`, `ValidateCommand` (MAUI, runs *before* `IsValid` is read so a command that sets the flag is enough), `Validate` (Blazor, `Func<Task<bool>>`, so a server round-trip is a first-class validator), then a cancellable `StepChanging`. `IsVisible="False"` takes a step out of the run entirely - skipped by Next/Back, dropped from the indicator, excluded from `StepCount` - which is how a conditional branch is modelled; `IsEnabled="False"` leaves it drawn but unreachable. The default indicator is the **pointed breadcrumb** (`ProgressStyle="Chevron"`, plus `Dots`/`Bar`/`None`, or `Progress` to replace it wholesale) - drawn on a `GraphicsView` on MAUI so it renders on every head including AppKit and GTK4, and a CSS `clip-path` on Blazor. The wizard owns `GoNextCommand`/`GoBackCommand`/`FinishCommand`/`CancelCommand`/`GoToStepCommand` (MAUI) and `GoNextAsync`/`GoBackAsync`/`FinishAsync`/`CancelAsync`/`GoToAsync` (Blazor), so a button inside a step navigates without the view-model re-implementing it; `CanGoBack`/`CanGoNext` stay yours and are ANDed with the wizard's own checks. `Finishing` is cancellable so a submit rejected server-side leaves the user on the last step. See wizard.md
- **Walkthrough & Tooltip** (both hosts, **core** packages): `Walkthrough` is a guided tour - dim the page, cut an animated spotlight around one control at a time, say what it does. **Steps are declared together on the walkthrough, in order** (`Steps` is the content property), *not* attached to the controls they describe: on a real screen attached ordering scatters the sequence where nothing can see it whole, so reordering means hunting and a conditionally-hidden control derails the rest silently. `IsVisible="False"` takes a step out of the run and re-numbers the counter. A step **advances three ways** - the Next command (`NextCommand`/`NextAsync`, or the built-in nav row), tapping the highlighted control itself (`AdvanceOnTargetTap`/`AdvanceOnTargetClick`, which implies `AllowTargetInteraction`), or a dwell timer (`Duration` in ms; `DurationIn`/`DurationOut` are the *animation* lengths, which is the one naming trap). Four displays: `Popover` (card + tail, the default), `Tooltip` (compact, no buttons), `Inline` (card, no tail), `Spotlight` (no card - text on the dim; needs `UseOverlay` and falls back to `Popover` without it). `RememberRunKey` is what makes onboarding run once - backed by `IWalkthroughStore` (Preferences on MAUI, `localStorage` on Blazor via `AddShinyWalkthrough()`, both replaceable); `Restart()` clears it and re-runs, which is the "show me the tour again" menu item. `AllowTargetInteraction` fences the backdrop with four panels *around* the hole rather than one catcher, because hit testing has no notion of a hole. Targets are `{x:Reference}` on MAUI (prefer it - compile-checked) or a CSS selector on Blazor. `Tooltip` is the bubble underneath it, usable on its own: it either **wraps** its target or **points at one** by reference/selector, opens on `Manual`/`Tap`/`LongPress`/`Hover`/`Focus`, and is bound with **`IsOpen`** - never `IsVisible`, which is `VisualElement.IsVisible` and would hide the anchor. Placement is a preference, not a promise: a side with no room flips to its opposite, the bubble is clamped inside `ScreenMargin`, and the tail slides along its edge to keep pointing at the target it was moved away from. The bubble is drawn in a page-level layer (MAUI) or the browser's top layer (Blazor), so it is never clipped by a scroll view or card. See walkthrough.md and tooltip.md
- **Keyframe** (MAUI only, separate `Shiny.Maui.Controls.Keyframe` package): Declarative keyframe animation — the CSS `@keyframes` model in XAML (`kf:Animate.Keyframes` attached property with `Keyframes`/`Track`/`Key`, `Duration`/`Delay`/`Iterations`/`Direction`/`Fill`/`Speed`/`AutoPlay`), plus a fluent C# `TimelineBuilder` and composable `Storyboard` (`Add`/`Then`/`With`/`Stagger`). Evaluation is a pure function of time, so animations **seek** — scrub from a Slider or gesture via `Player.SeekProgress`, reverse mid-flight with a negative `Rate`, and export deterministically — which is exactly what MAUI's own fire-and-forget `Animation.Commit` cannot do. `Easing` takes named curves (`CubicOut`, `BounceOut`, `Emphasized`, …) **and** CSS function syntax (`cubic-bezier(...)`, `steps(n)`, `spring(...)`) so design-tool curves paste in verbatim; omitting `Value` on a key resolves it to the target's live value at start. Properties resolve through an explicit hand-registered `AnimatableProperties` registry (AOT-safe, no reflection) covering transforms/opacity/colors/layout, extensible via `AnimatableProperties.Register`. `KeyframeView` renders a `KeyframeScene` layer tree (rectangle/ellipse/path/text/image layers) to a canvas with two-way bindable `Progress`. Optional `Shiny.Maui.Controls.Keyframe.Export` adds headless deterministic frame export and a pure-managed GIF encoder — the only piece that pulls SkiaSharp. See keyframe.md
Auf GitHub ansehen