Opx.MudBlazor.FlatUi
2.1.45
dotnet add package Opx.MudBlazor.FlatUi --version 2.1.45
NuGet\Install-Package Opx.MudBlazor.FlatUi -Version 2.1.45
<PackageReference Include="Opx.MudBlazor.FlatUi" Version="2.1.45" />
<PackageVersion Include="Opx.MudBlazor.FlatUi" Version="2.1.45" />
<PackageReference Include="Opx.MudBlazor.FlatUi" />
paket add Opx.MudBlazor.FlatUi --version 2.1.45
#r "nuget: Opx.MudBlazor.FlatUi, 2.1.45"
#:package Opx.MudBlazor.FlatUi@2.1.45
#addin nuget:?package=Opx.MudBlazor.FlatUi&version=2.1.45
#tool nuget:?package=Opx.MudBlazor.FlatUi&version=2.1.45
Opx.MudBlazor.FlatUi
Shared PDF printing: IFlatPrintService, Web desktop/mobile adapter and Android/Windows sample adapters. Print authorized PDF bytes through the existing viewer OnPrint callback; Submitted is distinct from confirmed completion. Native and physical-printer validation remain separate.
Mobile reliability P0–P2: unified refresh mode, scroll restoration, startup validation, cancellable latest-search, keyboard-aware CRUD and development-only diagnostics. Shared demo: /experience-toolkit.
See P0 compatibility and lifecycle gates for exact-package tests, live Web circuit regressions and native validation boundaries.
P1/P2 productivity adds unified saved views, guarded company/branch/site selection, nested filters, record workspaces and per-record bulk progress. Try the shared /enterprise-toolkit demo; persistence, authorization and business execution remain host-owned.
See Multipurpose operational toolkit for reusable ERP/HR/IoT work inbox, freshness, scan, telemetry, record relationships and personal-workspace composition, including native/backend ownership and validation boundaries.
Global panel-header sizing: set OpxFlatUi:Display:PanelHeaderMinHeight to 48 and PanelHeaderPaddingY to 10 (pixels; defaults). Headers may grow for subtitles/actions. See display settings.
Copyright © 2026 opx. All rights reserved.
Opx.MudBlazor.FlatUi is a reusable Razor Class Library for Blazor Web and MAUI Blazor Hybrid projects. It provides Fluent-like colors, compact page spacing, responsive application shells, mobile-first grid cards, bottom-sheet filters, paging, CRUD editor shells, safe-area-aware mobile dialogs, and consistent empty/detail/stat components.
Repository development guidance is available under .agents. Agents creating pages or reusable controls must follow the repo-local skill and use samples/Opx.MudBlazor.FlatUi.Showcase as the shared behavioral source of truth. The Web and MAUI sample hosts both load that assembly and its navigation catalog; native adapters remain MAUI-specific.
The template is intentionally multi-purpose. It can be used for ERP/business operations, IT operations, ecommerce/admin back offices, blogs/content sites, front pages, landing pages, dashboards, monitoring consoles, and reporting portals without locking the reusable components to one business domain.
Reporting controls include grouped operational reports, a typed responsive Pivot Grid, and FlatPdfViewer with packaged Mozilla PDF.js rendering, search, thumbnails, zoom, built-in Web print, and host-overridable native print/share/open callbacks. The /pivot showroom demonstrates runtime row/column dimensions, measure selection, five aggregate operations, totals, and exact-cell drill-down with copy-ready Razor usage; /pdf-viewer demonstrates the responsive document surface. The /enterprise-toolkit showroom covers 1.2-1.5, /experience-toolkit covers the 1.6-1.9 application experience APIs, and /operations-workspace demonstrates the 2.0 operational compositions.
Release line
The current source line is 2.1.x: 1.1-1.5 established the enterprise component foundation; 1.6-2.0 added accessibility, command, schema, collaboration, conflict, and operational compositions. Version 2.1 adds unified overlay/Back coordination, transaction validation, result-based editable-grid mutations, enterprise data/offline/native capability contracts, and a release-quality dashboard. See the roadmap, 2.1 contracts, application experience guide, and global application guide.
Preview
Web themes
| Light | Dark / Night |
|---|---|
Mobile Web
<img src="docs/images/preview-mobile.png" width="390" alt="Opx MudBlazor Flat UI mobile CRUD preview" />
Settings
Settings provides live preview for Light, Dark/Night, and Auto themes; Vertical, Horizontal, and Bottom navigation; Bottom child presentation (Sheet or icon-and-text MainView); color palette; interface density; font size; and backdrop opacity. Its modal owns the resolved semantic surface tokens independently from the shell: Light keeps neutral/white panel surfaces while the selected palette colors only accent selection and interaction states. Font size scales text globally across the shell, navigation, pages, grids, dialogs, menus, Settings, and reusable components while leaving icons and the selected spacing preset unchanged. Save persists the browser preference, Cancel restores the previously applied values, and Restore application defaults returns to the host configuration. FlatDisplaySettingsConfiguration can select, reorder, lock, localize, or template individual sections; IndonesianEssentials provides the focused Tema, Palet warna, Ukuran font, and Target sentuh surface. See Composable display settings.
Install into a host app
An executable Android/Windows MAUI Blazor Hybrid reference is available at
samples/Opx.MudBlazor.FlatUi.MauiHost.Sample.
It shows the root session gate, typed configuration, Debug/Release asset selection,
viewport-only Bottom/Sidebar navigation, and host-owned native adapter boundaries.
The project defaults to a source ProjectReference; consumers can switch its documented
UseFlatUiProjectReference property off to validate the matching NuGet package.
Reference the package/project and MudBlazor.
In
_Imports.razor:@using Opx.MudBlazor.FlatUi @using Opx.MudBlazor.FlatUi.Components @using Opx.MudBlazor.FlatUi.Components.Grid @using Opx.MudBlazor.FlatUi.Models @using Opx.MudBlazor.FlatUi.ServicesIn the host HTML/head, keep the stylesheet static and resolve the JavaScript from
FlatAssetOptions. Debug always uses the readable source; Release defaults to the generated minified asset.<link href="_content/Opx.MudBlazor.FlatUi/opx-flat-ui.css" rel="stylesheet" /> <script src="@AssetOptions.ResolveJavaScriptPath(IsDebugBuild)"></script> @code { [Inject] private FlatAssetOptions AssetOptions { get; set; } = new(); #if DEBUG private const bool IsDebugBuild = true; #else private const bool IsDebugBuild = false; #endif }Wrap the app layout with
FlatMudProvidersor put equivalent MudBlazor providers in the host. If the host restores a saved session, mount an interactive root startup gate beforeRouter; keepFlatSessionRestoreinside those providers while blocked, and constructRouteronly after the host check succeeds. This applies to anonymous routes such as Login too.Register application branding and display preferences. Application defaults come from configuration; each user/browser display override is stored in
localStorageand survives navigation/reload without modifying the server configuration file.var applicationOptions = builder.Configuration .GetSection("OpxFlatUi:Application") .Get<FlatApplicationOptions>() ?? new FlatApplicationOptions(); builder.Services.AddSingleton(applicationOptions); var displayOptions = builder.Configuration .GetSection("OpxFlatUi:Display") .Get<FlatUiDisplayOptions>() ?? new FlatUiDisplayOptions(); builder.Services.AddSingleton(displayOptions); builder.Services.AddScoped<FlatUiPreferencesService>(); var reconnectOptions = builder.Configuration .GetSection("OpxFlatUi:Reconnect") .Get<FlatReconnectOptions>() ?? new FlatReconnectOptions(); builder.Services.AddSingleton(reconnectOptions); var gridOptions = builder.Configuration .GetSection("OpxFlatUi:Grid") .Get<FlatGridOptions>() ?? new FlatGridOptions(); builder.Services.AddSingleton(gridOptions); var loadingOptions = builder.Configuration .GetSection("OpxFlatUi:Loading") .Get<FlatLoadingOptions>() ?? new FlatLoadingOptions(); builder.Services.AddSingleton(loadingOptions); var assetOptions = builder.Configuration .GetSection("OpxFlatUi:Assets") .Get<FlatAssetOptions>() ?? new FlatAssetOptions(); builder.Services.AddSingleton(assetOptions);Initial
appsettings.jsonUse this baseline for a new Web or MAUI Hybrid host, then change only the values the application intentionally owns. The global grid default is a compact searchable header with search/sort affordances and no metadata/type icons; individual grids can still override both settings.
{ "OpxFlatUi": { "Localization": { "Culture": "en-US", "UiCulture": "en-US", "TimeZone": "Asia/Jakarta", "DateFormat": "dd MMM yyyy", "DateTimeFormat": "dd MMM yyyy HH:mm", "Currency": "IDR", "RightToLeft": false }, "Assets": { "UseMinifiedJavaScript": true }, "Application": { "AppName": "OPX Flat UI", "CompanyName": "OPX", "Logo": null, "Copyright": "© {Year} {CompanyName}", "LoginBrandBackgroundColor": "#5274b9", "LoginBrandBackgroundImageUrl": null, "LoginBrandPanelVisible": true, "LoginBrandOverlayColor": "#000000", "LoginBrandOverlayOpacity": 0.0, "LoginLayout": "Default" }, "Grid": { "DefaultPageSize": 15, "PageSizes": [10, 15, 25, 50, 100], "DefaultHeaderStyle": "CompactSearch", "ShowHeaderIcons": false }, "Loading": { "InitialSkeletonEnabled": true, "DefaultTemplate": "Auto", "DataGridColumnCount": 5, "RowCount": 8, "MobileRowCount": 6, "MobileFieldCount": 4 }, "Snackbar": { "HideTransitionDurationMs": 200 }, "Reconnect": { "StartupTitle": "Loading page...", "StartupMessage": "Please wait a moment.", "ReconnectingTitle": "Rejoining the server...", "ReconnectingMessage": "Please wait a moment.", "PausedTitle": "Connection paused", "PausedMessage": "The app will resume automatically.", "FailedTitle": "Connection lost", "FailedMessage": "Check the network, then try again.", "RetryText": "Try again" }, "DeviceNotification": { "SampleTitle": "OPX Flat UI", "SampleMessage": "This notification is delivered through the local device notification system.", "SampleTag": "opx-flat-ui-sample" }, "Display": { "AppBarSearchVisible": true, "DefaultFabShape": "Circle", "DefaultRoundedSizePx": 0, "HostKind": "Web", "DefaultThemeMode": "Auto", "DefaultDensity": "Default", "DefaultInputStyle": "Outlined", "DefaultNavigationLayout": "Vertical", "DefaultBottomNavigationChildPresentation": "Sheet", "DefaultColorPalette": "blue", "UseAppFontSize": false, "DefaultFontSizePx": 16, "MinimumFontSizePx": 12, "MaximumFontSizePx": 18, "DefaultBackdropOpacity": 0.48, "MinimumBackdropOpacity": 0.30, "MaximumBackdropOpacity": 0.80, "AutoScaleHighDensityTouchButtons": true, "HighDensityTouchButtonHeightPx": 42, "HighDensityTouchFloatingLabelFontSizePx": 12.5, "SidebarGroupFontWeight": 400, "SidebarItemFontWeight": 400, "LightSidebarBackground": "#f3f6f9", "LightSidebarForeground": "#495057", "DarkSidebarBackground": "#212529", "DarkSidebarForeground": "#ced4da", "StorageKey": "opx.flat-ui.display" } } }Sidebar menu colors start from host defaults in
appsettingsand are also available in Settings for per-user live preview and persistence. SetLightSidebarBackground,LightSidebarForeground,DarkSidebarBackground, andDarkSidebarForegroundunderOpxFlatUi:Displayusing six-digit hex values. Empty, whitespace, null, invalid settings, or invalid saved overrides fall back independently to the normalized host value, then to#f3f6f9/#495057in Light and#212529/#ced4dain Dark/Night. Cancel restores the saved values and Restore application defaults returns all four values to appsettings. They affect the drawer/menu surface and ordinary menu text/icons, while hover and active states retain their semantic accent treatment; keep text contrast at least 4.5:1.The NuGet package contains both
opx-flat-ui.jsandopx-flat-ui.min.js. The readable file remains the development source; Release/Pack generates the minified file from the pinned build toolchain. See JavaScript asset pipeline.
Component usage examples
Responsive page, toolbar actions, pull-to-refresh, and FAB
FlatPage owns proportional page/panel spacing. Configure a standard CRUD create action once; it automatically renders a Filled desktop button above 900px and an icon-only FlatFab at 900px and below. Data actions remain icon-only in the toolbar.
The source after 2.1.20 also accepts optional Title="..." for compatibility. A nonblank title labels the page root as an accessible region; it does not render a duplicate heading, change the browser document title, or override the host AppBar PageTitle. Null/blank leaves the existing unlabeled wrapper unchanged. Consumers must upgrade to a package containing this addition before passing Title; older packages reject it during parameter binding.
Bind the page's first empty request to InitialLoading; FlatPage automatically chooses grid, form, dashboard, or list/detail skeleton geometry from FlatPageKind. SkeletonTemplate, count parameters, and LoadingContent provide per-page customization. Do not set InitialLoading for later refresh/filter/sort/paging/CRUD reloads; preserve established content and use FlatPageLoadingState for the AppBar line.
<FlatPage Kind="FlatPageKind.Module"
RefreshEnabled="true"
OnRefresh="LoadAsync"
ExportVisible="true"
OnExport="ExportAsync"
PullToRefreshEnabled="true"
NativePullToRefreshEnabled="true"
PrimaryActionVisible="true"
PrimaryActionLabel="Add"
PrimaryActionIcon="@Icons.Material.Outlined.Add"
PrimaryActionAriaLabel="Add record"
OnPrimaryAction="OpenCreate">
<ToolbarContent>
<MudTextField @bind-Value="_search"
Placeholder="Search records..."
Variant="Variant.Outlined"
Margin="Margin.Dense" />
</ToolbarContent>
<ChildContent>
<FlatDataGrid TItem="AssetRow"
State="_gridState"
Columns="_columns"
Items="_rows"
ExportVisible="true"
ExcelFileName="asset-view.xlsx"
RowTemplate="RenderRow" />
</ChildContent>
</FlatPage>
When FlatDataGrid.ExportVisible is enabled without an OnExport callback, the grid generates and downloads a native .xlsx workbook containing its visible columns in rendered order and the localized values of its materialized rows. ExcelExportItems can supply the complete already-filtered/sorted view instead of the displayed page. Existing OnExport remains the server/virtualized/large-dataset override. See Data-grid Excel export.
Enable PullToRefreshEnabled only on eligible Web data/feed pages and always provide a real OnRefresh handler. Dashboard/DashboardList are the default-enabled exception when that handler exists; set DashboardPullToRefreshEnabled="false" to opt out. FlatPage automatically recognizes its primary .mobile-grid-list; set PullToRefreshScrollSelector when a page owns a different primary mobile scroll region. The gesture begins only when that owner and the document are at the top. A mounted CrudEditorShell suspends Web/native pull-to-refresh and closing it restores the underlying page state.
Inside FlatAppShell HostKind="FlatUiHostKind.MauiHybrid", NativePullToRefreshEnabled="true" registers the same callback with the Android/Windows host RefreshView. The MAUI host must register singleton FlatNativePullToRefreshState, wrap its persistent BlazorWebView, bind IsRefreshEnabled, and dispatch with TryDispatchAsync. Native mode takes precedence over the JavaScript gesture when both flags are true. An active gesture suppresses duplicate page and nested report/PDF Refresh actions; without a real handler the button remains. Web ignores the native flag and keeps its package gesture behavior.
Responsive CRUD form modal
The same component renders centered on desktop/wide tablet and fullscreen on mobile. Browser Back closes the active modal before navigating the page.
<FlatFormModal @bind-Open="_editorOpen"
Title="Edit record"
Mode="Update"
IsDirty="_dirty"
CanSubmit="@IsValid"
CloseOnOutsideClick="false"
ConfirmClose="ConfirmDiscardAsync"
SubmitHandler="SaveAsync"
OnResult="HandleModalResult"
AutoRefreshOnSuccess="true"
OnRefreshRequested="ReloadPageAsync">
<div class="flat-crud-form-grid">
<MudTextField @bind-Value="_model.Code"
Label="Code"
Variant="Variant.Outlined"
Margin="Margin.Dense" />
<MudTextField @bind-Value="_model.Name"
Label="Name"
Variant="Variant.Outlined"
Margin="Margin.Dense" />
</div>
</FlatFormModal>
Back, Cancel, and an enabled backdrop close return false through OnResult and never request a caller refresh. A submit returns true only after OnSubmit or SubmitHandler completes successfully. FlatFormModal is CRUD-oriented, so AutoRefreshOnSuccess defaults to true; when OnRefreshRequested is supplied it invokes the caller's existing load pipeline after a successful close without hard-reloading the browser or resetting query/filter/paging state. Set AutoRefreshOnSuccess="false" for non-CRUD forms.
Searchable combo box
<FlatSearchComboBox T="string"
Label="Department"
Items="_departments"
@bind-Value="_departmentId" />
@code {
private string? _departmentId;
private readonly IReadOnlyList<FlatSearchComboOption<string>> _departments =
[
new("FIN", "Finance") { Description = "Accounting and treasury" },
new("HR", "Human Resources") { Keywords = "people employees" },
new("OPS", "Operations")
];
}
For API-backed lookup, supply the cancellable SearchAsync delegate instead of loading an unbounded option list.
Shared message box
Register FlatMessageBoxService, inject it into the page, and call the semantic helper rather than duplicating dialog markup.
@inject FlatMessageBoxService MessageBox
@code {
private async Task DeleteAsync()
{
var confirmed = await MessageBox.QuestionAsync(
"Delete the selected record?",
title: "Delete record",
confirmText: "Delete");
if (!confirmed)
return;
// Call the authorized application service here.
}
}
Documentation
Official release roadmap: delivered release history, the active
2.1.7gate, and the ordered ERP release train.Migration from 1.0.x to 1.1.0: opt-in APIs, ownership boundaries, compatibility notes, and validation.
Message box: reusable reference-aligned question, warning, information, and error prompts.
Processing state: reusable page/form disabled state, loading backdrop, cancellation, and lifecycle callbacks.
NuGet publishing: safe PackOnly default, explicit
-Publish, automatic patch/minor/major version increment, package validation, and secure API-key handling.Multi-select component: reusable option model, permission-style example, and theming hooks.
Search combo box: searchable single-value combo with local options or a cancellable async/API provider.
ERP sample pages: route matrix, UX architecture, responsive behavior, extension workflow, real-service integration guidance, and validation checklist.
Authentication and navigation templates: login, two-step verification, vertical/horizontal navigation, configuration, responsive fallback, and security boundaries.
Sidebar typography: appsettings-backed group and leaf font weights, defaults, normalization, and host integration.
Design contracts
- Responsive design is adaptive, not a scaled desktop. OPX retains its established
900pxtable/card boundary,601-900pxtwo-card range,600pxphone refinement, device/browser1remdefault, optional app-controlled16pxbaseline, density presets, and high-density touch settings. Use shared tokens and viewport/container CSS—not Android/iOS detection or page-local type scales—to adapt navigation, hierarchy, forms, actions, and information density. Mobile prioritizes readable primary content, touch geometry, one-column forms, and equivalent shared-state cards/lists; desktop remains compact, multi-column, and data-oriented. Validate desktop, responsive/tablet, phone, and no-reload live resize in Light/Dark/Auto; native MAUI behavior still needs device/emulator evidence. See Responsive design. - Treat viewport and host capability independently: breakpoints choose Web/MAUI/Windows mobile, tablet, or desktop composition;
FlatUiHostKindchanges only genuine host integrations such as native gestures, notifications, status/safe-area handling, file/camera, system Back, print/share/open, and lifecycle. A narrow Web viewport is not automatically a native device, and a wide MAUI window still retains its native host capabilities. - Desktop/wide tablet CRUD forms are centered/panel based; mobile forms are always fullscreen with visible close/back actions. This mobile modal geometry is owned by the shared editor and is independent from page FAB/no-FAB spacing.
CrudEditorShell.CloseOnOutsideClickcontrols backdrop dismissal and defaults tofalse: usetruefor click-anywhere/backdrop close, or keepfalsewhen closing must go through Back/Cancel. While an editor is open, a same-URL history guard consumes the first browser Back action, including for a clean form; the same close guard then handles processing and dirty confirmation. A rejected close re-arms the guard and keeps the modal and route unchanged. Visible Back/Cancel removes the guard without adding a phantom Back step. - CRUD editor forms use compact
Margin.Densecontrols and the reusable.flat-crud-form-grid: two columns with a10pxcolumn gap and7pxrow gap on desktop/tablet, then one column with a6pxrow gap at600pxand below. Direct editor-body children use a7pxvertical gap. Direct field margins are normalized to4px 0 0, editor body padding is14px 16px, and helper/error text may add only the height it actually needs. Fullscreen mobile editor space stays below the top-aligned form; it never stretches grid rows or input controls to fill the viewport. Editor headers use a54pxdesktop/wide-tablet minimum, a56pxmobile minimum before safe-area expansion, and a compact2pxmode-to-title gap while retaining the Back button touch target. - Save/update/delete operations use the shared processing contract.
DisableContentlocks all descendant controls;Backdropadds a theme-synchronized blocking overlay and progress indicator. Prefer cancellableSubmitHandler/RunAsyncoperations and use completion, cancellation, and failure callbacks; always restore interaction in every success, failure, and cancellation path. - Mobile page gutters are equal: top panel gap, left gutter, and right gutter default to
16px. - Internal component rhythm is compact: keep panel/card/filter spacing tight, while preserving the outer
16pxmobile gutters. - AppBar terminology is fixed: row 1 is
AppName, row 2 remainsPageTitle. Do not rename the second row toAppTitle, and do not leavePageTitlestatic when navigation changes.AppNameis compact and bold for brand recognition;PageTitleis compact and regular so the title block does not dominate the toolbar. At the app-controlled16pxbaseline they resolve to approximately12pxand11px, and density presets preserve those ratios. - AppBar page titles are normalized for readability: route/module tokens such as
Operations-CrudAssetrender asOperations - Crud Asset. - Keep reusable component naming, defaults, and layout contracts domain-neutral. Domain wording such as IT, ecommerce, retail, landing, or operations belongs in the consumer app/sample data, not in shared component internals.
- New operational pages default to no visible description/intro heading. Rely on the AppBar page title and show only the content panel/grid/form; add visible explanatory copy only when intentionally requested. Use
FlatPageHeadingonly for optional explicit descriptions/actions, so placeholder blocks likeCRUD / Asset Management / Contoh grid...are not created by default. - Hamburger/drawer behavior follows the reference Hybrid shell: drawer starts closed until breakpoint is known, hamburger is visible on desktop and mobile, desktop toggles layout offset without leaving stale margin, and mobile/tablet opens an overlay drawer that closes after navigation or after clicking/tapping anywhere outside it. Interactions inside the drawer do not dismiss it.
- On responsive/mobile AppBar, the hamburger button is intentionally closer to the left edge so the icon visually aligns with the
16pxcontent gutter. - AppBar settings/overflow action uses a three-dot icon (
MoreVert), not a gear, unless the page opens a dedicated settings screen. - AppBar device-notification and settings/overflow actions are borderless, shadowless icon buttons whose normal surface matches the AppBar. Hover, focus, active, and open states use a slightly raised theme color so interaction remains visible.
- MudBlazor button states remain visibly distinct on mobile and desktop. Standard/Default, Primary, Secondary, Tertiary, Info, Success, Warning, Error, and Dark use a strong family color while enabled; disabled Filled, Outlined, and Text variants use a quieter desaturated family tint, border, and foreground in both Light and Dark/Night. Disabled state keeps native semantics and no shadow, and does not rely only on cursor or one global opacity.
- Default MudBlazor checkboxes use the active accent when checked/indeterminate, a readable theme-aware outline when unchecked, and normal foreground label text. Disabled checkbox glyphs and labels are deliberately quieter in Light and Dark/Night, while the checkbox icon surface stays transparent and explicit semantic checkbox colors remain available.
- High-density mobile touch devices automatically increase ordinary text buttons to a configurable touch target (default
42px) and edit-form floating labels to a readable caption size (default12.5px). Detection combines a mobile viewport, coarse/touch input, and at least1.75dppx, so a 4K desktop with a mouse is not enlarged accidentally. ConfigureOpxFlatUi:Display:AutoScaleHighDensityTouchButtons,HighDensityTouchButtonHeightPx(38-52px), andHighDensityTouchFloatingLabelFontSizePx(11.5-15px); specialized FAB, compact icon-toolbar, input adornment geometry, empty placeholder-like labels, field height, and form gaps remain independent. - Sidebar search updates the menu tree immediately with case-insensitive matching, auto-expands matching parent groups, hides unrelated groups/items, shows an empty state when no item matches, and restores the full tree when cleared. Split sidebar/menu components must propagate a new cascading search-state snapshot (or an equivalent explicit change notification) for every query update.
- Sidebar search keeps a compact
30pxinput with4pxvertical breathing room inside a38pxwrapper; this spacing applies consistently on desktop and overlay drawers without changing menu indentation. - Sidebar search placeholder text is intentionally compact and regular weight (
10-11px, weight400). This navigation-specific style is scoped to the sidebar and does not change AppBar search or form placeholders. - Blocking backdrops lock scrolling and interaction on the underlying page for overlay drawers, settings/about, CRUD/form editors, bottom sheets/filters, and dialogs. Backdrop opacity is configurable from
OpxFlatUi:Displayand the Settings live-preview slider, then follows the same Save, Cancel, Restore, and browser-persistence contract as other display preferences. - Confirmation/message boxes require an explicit visible action: Question closes through Confirm or Cancel; Warning, Information, and Error close through their acknowledgement button. Backdrop click, Escape, and route navigation do not dismiss the prompt; each variant uses its semantic color, and Dark/Night keeps the title and outlined Cancel label at readable contrast.
- AppBar page/component search is a host-supplied navigation autocomplete. Pass
FlatNavigationSearchItementries throughFlatAppShell.SearchItems; focus shows menu choices, typing matches title/group/keywords, Arrow Up/Down changes the active choice, Enter navigates, Escape closes, and an unmatched query shows an English empty state. SetFlatAppShell.SearchVisible="false"to remove the search and its focus target completely. Hosts may bind this toOpxFlatUi:Display:AppBarSearchVisible, which defaults totruefor compatibility. Keep domain routes and keywords in the consumer host, not in the reusable library. - The AppBar settings/overflow menu should use the dot-3 icon as a top-level overflow list that can contain
Settingsand other app menus.Settingsopens a dedicated settings form modal, not an inline dropdown; desktop is centered and mobile is fullscreen/safe-area aware. Theme choices belong underTheme settings:Light,Dark / Night, andAuto.Autofollows the device/system preference on the first paint and on later system-theme changes; loadopx-flat-ui-theme-bootstrap.jsin<head>before theme stylesheets and bind its storage/default attributes as documented in Theme startup and Auto mode. - AppBar overflow menu labels use the active foreground token at full opacity. In Dark/Night mode, enabled labels use
#ced4daand may increase to white on hover/focus; only genuinely disabled items use reduced contrast. - Dark/Night theme uses one consistent graphite hierarchy: workspace
#1a1d21, surface/sidebar#212529, input/secondary surface#262a2f, hover#2a2d31, header/raised surface#292e32, border#32383e, primary text#ced4da, secondary text#878a99, and default filled Primary#005f91. Settings, AppBar menus, Kanban, Chat, dialogs, and portals share these tokens; legacy pure-black component islands are normalized away. - Light semantic theme tokens use primary
#004a77, secondary#865ce2, success#13c56b, info#50c3e6, warning#e8bc52, and danger#ed5e5e. UseFlatColorReferenceor the/colorssample to inspect solid, subtle, border, emphasis, surface, and opacity variants under the active theme. - All MudBlazor controls must follow the active theme, including overlay/portal controls such as combo/select dropdowns, notification menus, menus, popovers, pickers, dialogs, list items, input adornments, hover, unread, and selected states. Dark mode must not leave a white menu body or item surface unless the page explicitly renders media/content that should stay light.
- Dark/Night multi-select popovers keep their list on
#212529; the optional Select All header is raised to#31363cwith readable#e9eceftext and a#495057divider. - Dark/Night combo/list selections use a palette-aware raised accent surface instead of the near-black hover color. Normal portal items use
#ced4da, selected items use white, and the selected background remains visibly distinct from the#212529list surface and#2a2d31hover state. - Outlined combo/select wrappers remain transparent so label margins do not render as a larger background block. Apply the themed control surface only to the visible outlined input area; dropdown/popover surfaces still follow the active theme.
- Textbox and textarea placeholders use a small relative
2pxsize increase and a subtle theme-specific secondary-text mix at full opacity: Light mixes92%active secondary text with8%white, while Dark/Night mixes it with8%black. Native placeholders, empty/non-floating labels, floating labels, entered textbox/textarea values, and selected combo values all use normal400weight. Empty labels retain their minimum13pxsize and2pxupward optical offset; CRUD values retain their responsive12.5pxscale. Typography continues to scale with display settings without changing input height or floating-label geometry. - MudBlazor outlined floating labels use one library-wide minimum formula of
11.5pxbefore MudBlazor applies its0.75floating transform. The same baseline applies to textbox, textarea, select/combo, CRUD, account/settings, modal, desktop, tablet, and mobile fields; page-scoped reductions are not allowed. High-density mobile touch devices may raise only the floating caption to the configuredHighDensityTouchFloatingLabelFontSizePxdefault of12.5px. Compact forms useMargin.Denseso control height, value, adornment, validation geometry, and form gaps remain synchronized. - Browser autofill is theme-safe by default. Inputs, textareas, and selects keep the resolved Light, Dark/Night, or Auto field surface, text, and caret colors across autofill hover/focus/active states, including fields with transparent adornments. No page-specific Login CSS is required.
- Outlined field containers use one continuous theme-resolved surface across value and adornment areas, including autofill. Adornment wrappers, glyphs, and clickable icon buttons stay transparent, borderless, and shadowless over that field surface, while standalone, AppBar, toolbar, and grid icon buttons retain their own interaction-state styling.
- Desktop grid column headers use compact glyphs: 14px for sort and 15px for filter. Keep the filter button hit area at 24x24px with accessible labels and visible hover/focus/active states. The global default is
FlatGridHeaderStyle.CompactSearchwithShowHeaderIcons=false, so search/sort remains available without metadata/type icons. Configure optionalHeaderIconandSearchPlaceholderonGridColumnDefinition; set componentHeaderStyleorShowHeaderIconsonly for a deliberate local override, includingStandardfor the legacy filter-row presentation. - Desktop
FlatDataGridhas one theme-synchronized two-axis scroll region. Excess rows show a vertical scrollbar and wide columns show a horizontal scrollbar, while the grid toolbar and pager remain fixed outside the scrolling body. A custom directdivhost under.module-panelneeds no special class: the package bounds it on desktop and hides it when the equivalent mobile grid is active. Opening a modal locks document scrolling without removing the internal grid scrollbar geometry.FlatDataGrid,FlatGroupedDataGrid, andFlatEditableGridindependently exposeAlternatingRows(defaultfalse),ShowVerticalLines(defaulttrue), andShowHorizontalLines(defaulttrue).AutoRowHeightdefaults tofalse; enabling it wraps non-numeric content, grows each row to its tallest cell, and top-aligns the row while numbers stay single-line/right-aligned. Responsive cards keep their own record geometry and separators. GridColumnDefinitionaccepts proportionalWidthPercentor fixedWidthPx(fixed wins). Automatic cells infer public properties by column key;ValueSelectormaps custom keys. Numeric/currency columns are right-aligned and formatted withOpxFlatUi:Localization, while custom templates receiveFlatGridCellContext.FormattedValue. See API grid loading.- The
/data-grid-largesample deliberately exercises both axes with 120 deterministic in-memory records, 12 columns, and a 50-row initial page. At900pxand below, the same filtered/paged records render as responsive cards without document-level horizontal overflow. - The AppBar notification action means a local OS/device notification, not a snackbar, dialog, or in-app notification-feed menu. Use
FlatDeviceNotificationwith anIDeviceNotificationServicehost adapter; permission, scheduling, cancellation, tap routing, and native lifecycle remain platform-owned. - Sidebar tree menus (
MudNavGroup) follow the reference shell behavior: search filters menu items, matching groups auto-expand, active routes expand their parent group, collapsed children are clipped, transitions are disabled for stable MAUI Hybrid rendering, and child indicators use dotted vertical/horizontal connectors aligned to the child-icon center axis. - Sidebar group and leaf labels both default to font weight
500so a menu that owns children does not look inconsistently lighter than a normal item. ConfigureOpxFlatUi:Display:SidebarGroupFontWeightandSidebarItemFontWeightin appsettings when a host intentionally needs different hierarchy weights. - Sidebar parent and child links follow the reference geometry: root links use a
6pxicon-to-text gap and every nested link uses a compact2pxgap. At every nesting depth, a child or sub-child icon aligns horizontally with the start of its immediate parent label—for example, ERP Overview aligns with ERP and HR Overview aligns with Human Resources. Each dotted connector ends 3px before its child icon. The menu tree and collapse wrappers fill their parent width, each nested collapse subtracts only its own indent, and the scroll region reserves a stable scrollbar gutter. Computed link width, padding, and icon/text coordinates remain stable when overflow appears, a deeper group opens, or a child becomes active. - Sidebar leaf links and group titles support
FlatNavigationBadgefor compact counts, text statuses, or labeled dots. Parent groups useTitleContentwhile retaining a plainTitlefor accessibility. Badges use semantic Light/Dark colors, truncate long values, and do not alter sidebar icon/text/connector/chevron geometry. See Authentication and navigation templates. - Blazor Server reconnect/rejoining UI follows the reference compact notice:
#components-reconnect-modal.server-reconnect-notice, bottom-right on desktop, 12px side gutters on mobile, English status text, spinner while reconnecting, dot for paused/failed, and no blocking full-screen backdrop. - Web and MAUI host documents replace the built-in
#blazor-error-uimessage with a static, theme-safe OPX full-page recovery surface. It exposes no exception details or Dismiss action and offers oneRestartaction because a terminated circuit cannot safely continue. - Public frontend websites should use a dedicated website shell/layout instead of the admin drawer shell. Use it for landing pages, storefronts, blog/content pages, front pages, and campaign pages.
- AppBar hamburger spacing must keep the icon close to the left edge while preserving a small breathing gap before the title block; current rule adds 2px more space between hamburger and title.
- Include auth reference screens where applicable: login should be a standalone full-screen page, and logout should be reachable from the signed-in user block.
- Login/auth password controls with show/hide use
opx-password-visibility-field: the transparent eye/eye-off action is white in resolved Dark/Night and#212529in resolved Light, and retains that contrast after toggling the input between password and text. Production hosts must retain an accessible label and keyboard action. - Two-step verification templates are UI workflow samples only. Use one-time-code input semantics, masked delivery targets, resend/back actions, and clear error/success states, but leave code generation, delivery, expiry, retry/rate limits, replay protection, trusted-device policy, recovery, and session issuance to the consumer authentication service.
- Reset-password templates include reset-request, temporary-code, new-password, confirmation, requirement feedback, success, and back-to-login states. Keep passwords transient and clear code/password fields after completion; server-side token validation, expiry, rate limits, password policy, credential update, session revocation, and audit remain consumer responsibilities.
- Admin navigation can be configured as
Vertical,Horizontal, orBottom. Horizontal is Web desktop-only and uses a compact module bar; tablet/mobile falls back to the reference drawer. Bottom is available on Web and MAUI Hybrid, activates only at phone widths, and falls back to the sidebar on tablet/desktop. It reuses the shared route tree, limits the bar to five equal-width roots, moves overflow intoMore, and opens parent children in a locked, recursive bottom sheet. Wherever Web global search is visible, the AppName/PageTitle block takes the rendered width of its wider line and the search border starts exactly16pxafter that block; unusually long titles are capped and ellipsized. Layout changes preview immediately in Settings and persist throughFlatUiPreferencesService. - AppBar global search renders one focus indicator on its composite wrapper. The inner text input remains transparent and does not add a second nested focus border; the wrapper ring remains visible in Light and Dark/Night.
- Profile avatars should accept any image URL while still supporting configurable initials as fallback or intentional initials-only display.
- Sample charts must use MudBlazor chart components (
MudChart) instead of hand-drawn div/SVG bars, so chart behavior, legends, and responsive rendering follow MudBlazor. The/chartsshowroom renders all eleven chart types available in MudBlazor 9.7.0 and provides expandable copy-ready Razor samples; see MudBlazor chart showroom. - Do not show online/live/realtime indicators in the AppBar by default. Only pass
RealtimeTextwhen a consumer app has a real live connection state worth showing. - Standard CRUD primary actions use the
FlatPagePrimaryAction*parameters andOnPrimaryAction; one declaration automatically creates the desktop Filled button and mobile icon-only FAB. Specialized manual mobile actions may still useFlatFab, which is hidden on desktop and fixed above the bottom safe-area. Keep the FAB visually flat with no shadow in normal, hover, focus, or active states; keyboard focus uses an outline instead. FlatFabis icon-only by default. Keep text inAriaLabel/titlefor accessibility, but do not show a visible text label unless an explicit exception setsExtended=true.- Do not combine the automatic primary-action API with manual
HeaderActionsorMobilePrimaryActionfor the same action.FlatPageowns responsive mutual exclusion and hides the complete inactive wrapper so mobile spacing is not reserved accidentally. - Grid/list pages without a mobile FAB must have root class
no-mobile-faband keep proportional mobile gutters: top16px, left16px, right16px, bottom16px. Pages with a FAB usehas-mobile-fab, keep extra bottom padding so the FAB never covers content, and cap the grid/panel scroll area between the top content gutter and the top of the FAB with at least16pxclearance. - Responsive record cards keep their outer boundary
1px solid, while dividers inside the same record use1px dottedfor the header, fact rows/columns, references, progress, and action footer. The final internal divider is removed where it would duplicate the solid outer boundary. - Grid sizing must be verified proportionally, not by source inspection only. On mobile, use computed layout values: top/left/right page gutters
16px, no-FAB bottom16px, FAB bottom reserve, panel left/right gutter equal againstdocument.documentElement.clientWidth, bounded panel height around88vh/88dvh, and internal scrolling in the grid/list area. - Responsive cards use two fact columns from
601pxthrough900px. Keep the card/header/footer boundaries solid while internal fact-row and fact-column separators are dotted; at600pxand below return to the single-column mobile separator geometry. - Grid data actions belong in the grid/panel toolbar. Put
Filter,Import,Export,Download CSV,Print, andRefreshinFilterEnabled,ToolbarActions,RefreshEnabled, or a.module-toolbardirectly above the grid; do not place them in the page heading/AppBar/hero action area. Keep these toolbar actions icon-only, inline, and one row, with text only inaria-label/title. - Operational grid/list pages must not reserve a
BeforePanelor.page-actions-onlyrow for data actions. A writable page may expose one create action per viewport: a desktop action that is hidden at the responsive cutoff and an icon-only mobile FAB, never both at once. Read-only pages must not expose Add, Edit, Delete, or a create FAB. ReadOnlySourceis reserved for genuinely non-mutating samples. Do not apply the read-only marker to an in-memory CRUD sample that can add or edit records.- Built-in
FlatPagetoolbar actions are individually toggleable:FilterVisible/FilterEnabled,RefreshVisible/RefreshEnabled,ImportVisible,DownloadVisible,ExportVisible, andPrintVisible. Add custom extra buttons withToolbarActions; custom buttons should use.grid-action-buttonand stay in the same one-line action row. FlatPagehides its Filter action unlessFilterVisible/FilterEnabledresolves to true andOnFilterhas a real handler. Do not show a separate Filter icon for a grid that only has inline search or has no filter UI; enable it only when it opens an actionable filter sheet, panel, popover, or equivalent experience.- Default grid filtering is column-driven: use one
GridColumnDefinitioncollection for desktop headers and the responsive filter sheet, and oneGridViewStatefor current criteria. Derive toolbar Filter visibility fromColumns.Any(column => column.FilterEnabled); never maintain separate mobile filter metadata or state. - On responsive/mobile grid toolbars, search/filter text inputs must use a full-width row and must not be clipped; the icon-only action row sits below/after the text input.
- When a responsive/mobile toolbar has at least two actions,
FlatPageadds a compact action-grid toggle to collapse or expand the complete action row. Search/filter text remains full width and visible, while the action row defaults collapsed to preserve content space. Configure it withMobileToolbarActionsCollapsible; setMobileToolbarActionsExpandedByDefault="true"only when a page intentionally starts expanded. Desktop actions always remain visible. - In desktop inline filter forms, action buttons align their visible top and bottom edges with adjacent dense outlined controls. On responsive layouts, move the action to its own full-width row instead of preserving desktop alignment offsets.
- Grid toolbar actions are icon-only and kept on one horizontal line. Use accessible
aria-label/titletext forImport,Export,Download CSV,Print, andRefresh, but do not show those labels as button text in the toolbar. - Mobile pull-to-refresh is page-level opt-in and becomes active only when
PullToRefreshEnabled=trueand a realOnRefreshhandler are both supplied. Enable it explicitly for mobile data/list/grid, monitoring, report, or feed pages where the gesture unambiguously reloads the latest data; never infer it fromFlatPageKindor enable it globally. - Keep pull-to-refresh off by default for login/authentication, settings and account editing, create/edit forms, detail pages with unsaved state, dialogs/bottom sheets, and public landing/content pages unless that page deliberately defines the gesture. It starts only at the top of the document and the page-owned primary mobile scroll region on touch/coarse input. Incidental nested scrollers and editor/overlay/input/button/FAB targets remain excluded. The native-friendly handler uses non-passive
touchmoveso Android/iOS WebView scrolling cannot consume an active downward pull, while refresh still reuses the same single-flight pipeline and preserves query state. - Responsive Web/Hybrid behavior uses desktop tables/header filters above
900px; dedicated cards retain the identical query state at900pxand below; two card columns are used from601pxthrough900pxand one at600pxand below. The transition is reversible during live window resize without reload, desktop overflow returns to the grid-owned scroll region, and operational grids never create page-level horizontal scrolling. - Sidebar menu glyphs stay compact at
18pxfor root/parent items and17pxfor nested items. Keep the existing icon column, text offset, dotted connector, and recursive parent/child alignment unchanged; reducing the glyph must not shift menu geometry. - Nested sidebar typography and geometry are depth-driven, never expansion-state-driven. A child group such as
ERP - Human Resourceskeeps the same11pxtext,17pxicon,32pxrow, and text coordinate before and after its first expand/collapse interaction. - Browser preview validates responsive Web layout only. MAUI claims additionally require emulator/device checks for keyboard/IME resize, safe areas/notch, status bar, system back/swipe, orientation, lifecycle, permissions, native gestures, and offline/reconnect behavior.
- Android MAUI hosts use host-owned transparent edge-to-edge status-bar integration: obtain the real top
WindowInsets, render the AppBar at60px + inset, keep its controls in the lower60px, and refresh status-icon contrast on Light/Dark/Auto, system-theme, and palette changes. Do not hardcode status-bar height or apply this native geometry to Web/Windows. - Mobile grid filters use
MobileGridFilterSheet: dimmed overlay, top drag handle, compactFilter dataheader, full-width fields, and a fixed footer withReset/Apply. - Grid filtering supports desktop column filters and mobile bottom-sheet filters; disabled columns stay out of mobile filters.
- Save/submit actions should pass
Saving=trueto disable form actions and prevent accidental close while processing. - Release builds remove PDB output by default.
Core components
FlatMudProvidersFlatAppShellFlatAppBarFlatSidebarFlatPageFlatPageHeadingFlatPanelFlatStatCardFlatEmptyStateFlatInfoItemFlatDetailSectionFlatDataGrid<TItem>FlatGroupedDataGrid<TItem>: expandable stable-key groups, localization-aware host-supplied summaries, typed toggle/row callbacks, and equivalent responsive cards; see Grouped Data Grid.FlatHierarchyDesigner: compact ordered outline editing with Web drag/drop, accessible move actions, cycle prevention, exact parent/order results, and versioned nested JSON export; see Compact Hierarchy Designer.FlatEditableGrid<TItem>: one-draft inline Add/Edit/Delete grid with typed canonical save results and per-row Create/Update/Delete outcome callbacks; switches to equivalent card editing at900pxand below.FlatModelCrud<TItem>andFlatModelForm<TItem>: metadata-driven list/card CRUD and form generation from DataAnnotations, with outlined floating labels by default,Display(Prompt)hints, localized numericDisplayFormat, built-in local/async searchable combos, per-field visualEditorTemplate, explicit image templates, reusable visual layouts, and host-owned persistence.FlatModelFormDesigner<TItem>: drag/drop or keyboard-accessible field ordering, visible/span controls, bounded margin/padding, validated CSS class tokens, and exact desktop/mobileFlatModelFormlive preview for native, searchable-combo, image, and custom visual editors.- ERP application building blocks:
FlatTransactionWorkspace<THeader,TLine>,FlatEntityLookup<TItem>with a sortable/searchable table grid,FlatMoneyInput,FlatQuantityInput,FlatJournalEntryGrid<TLine>,FlatReconciliationWorkspace<TLeft,TRight>,FlatPlanningBoard<TItem,TResource>,FlatRecordLifecycleHeader, andFlatBackgroundOperationCenter. Lookup headers toggle ASC/DESC, search targets the active sorted column, search autofocuses on open, and letter/number typing elsewhere inside the modal routes directly into search. These components own responsive presentation and typed intent only; business rules and persistence remain host-owned. See ERP toolkit. FlatImageUpload: multiple image selection with responsive preview, configurable high-resolution autoscale, exact original/output metadata, progress/cancel/retry, and host-owned API/storage callbacks.FlatDynamicMenu: autoload and validate recursive sidebar navigation fromMenuText,Id,ParentId,Url, andIcon, with conversion for horizontal and bottom navigation.IFlatNavigationRouteResolverapplies consumer-owned label mappings consistently in Web/MAUI, normalizes hidden Unicode, and rejects unsafe fallback schemes.FlatMobileGrid<TItem>FlatPagerFlatFabFlatProfileAvatarFlatProfileListItemfor compact responsive people/member directories with a circular avatar, identity metadata, host-defined badges, and a navigation callbackFlatDisplaySettingsFlatHorizontalNavigationFlatBottomNavigation: phone navigation bar backed by the shared route tree, with active-route state, overflow, and recursive child-menu sheets.FlatKanbanBoard<TItem>FlatKanbanCardFlatPipelineCardandFlatKanbanBoardVariant.Pipelinefor aggregate stage/deal layoutsFlatChatShellFlatChatConversationItemFlatChatMessageFlatChatTypingIndicatorFlatChatWebSocketClient- AI Chat template composition: provider-neutral assistant history, prompts, responding/stop states, and mobile history/thread navigation built from the shared Chat components.
FlatWidgetFlatMetricWidgetFlatActionMetricWidgetFlatCompactMetricFlatProgressWidgetFlatSegmentProgressWidgetFlatActivityItemFlatTaskItemFlatEmailShellFlatEmailFolderItemFlatEmailMessageItemFlatCatalogGrid<TItem>FlatCatalogCardFlatFilterWorkspace: desktop filter rail plus result toolbar/content; switches to a staged mobileBottomSheetwith Apply/Reset/Dismiss callbacks.FlatProductDetailandFlatProductMetric: responsive gallery/summary detail shell with host-owned metadata, metrics, variants, tabs, and actions.FlatEditorWorkspaceandFlatEditorSection: responsive main-editor/settings-rail composition for create/edit pages.MobileGridFilterSheetBottomSheetCrudEditorShellFlatFormModalFlatProcessingContainer: reusable single-flight processing boundary for pages, panels, and forms with disabled content, optional backdrop/cancel action, and lifecycle callbacks.Cancel operationis hidden by default; opt in withCanCancel="true"plusCancelActionVisible="true"(orAllowProcessingCancellationplusProcessingCancelVisibleon form modals).FlatDataGridSkeleton: responsive MudSkeleton-based initial-load placeholder with desktop table rows and equivalent mobile/tablet cards. Keep established data visible on later refresh/filter/sort/paging operations.FlatPageSkeleton: automatic responsive initial-load templates selected byFlatPageKind, with globalFlatLoadingOptionsand per-page template/count/custom-content overrides.FlatCardGrid<TItem>FlatProfileCardFlatTimeline<TItem>: center and left timeline shell with marker/date selectors and host-owned item templates.FlatMultiSelect<T>- responsive dense multi-value selector with standardized compact field geometry, one native selection indicator, optional icon/avatar content, and hideable checkbox column; see Multi-select component
FlatSearchComboBox<T>: searchable single-value selector with typed binding, local text/description/keyword matching, and optional cancellable async search.FlatMaterialIconPicker: searchable Material icon selector backed by the installed MudBlazor Filled and Outlined catalogs. It pages large result sets, supports keyboard/touch selection, and returns a typedFlatMaterialIconSelectioncontaining the stable icon name, SVG value, and style. See IconPicker usage for Indonesian button/empty-state labels and host-owned persistence.FlatReconnectModal: library-owned Blazor Server reconnect notice with theme-aware responsive states and appsettings-backed text.FlatSessionRestore: full-page session-bootstrap status using the exact shared reconnect spinner; host session lookup, validation, authentication state, and failure handling remain host-owned.FlatDeviceNotification: borderless notification action that invokes a host-owned local OS/device notification service and reports shown, denied, unsupported, or failed state without falling back to a snackbar.
Core services
FlatSessionCartService<TItem>: scoped per user/session cart-like state for ecommerce carts, selection baskets, wishlist-like flows, and other per-session item collections.FlatUiPreferencesService: scoped display-preference state withVertical, Web-onlyHorizontal, and Web/MAUIBottomnavigation resolution, host-configured color palettes,Compact/Default/Comfortabledensity presets, and a configurable font size. SetOpxFlatUi:Display:HostKindtoWeborMauiHybrid. Host defaults and palette definitions are read fromappsettings; user overrides store only the selected palette ID and display choices per browser throughlocalStorage.FlatPageLoadingState: reference-counted shared loading state for the AppBar loading line. Register it as scoped in Blazor Web or singleton in a MAUI Blazor Hybrid host, inject it into page/service operations, and wrap work withusing var loading = PageLoading.Begin();. Real route/query navigation also shows the same compact 2px indeterminate line automatically; same-URL modal history guards are ignored so modal open/close does not flash loading.IDeviceNotificationService: host boundary for local device notifications. Blazor Web can useFlatWebDeviceNotificationService; MAUI registers a native platform adapter.
Implementation guides
- Loading table/grid data from an API: recommended typed-client and Razor pattern for server paging, sorting, filtering, cancellation, stale-response protection, AppBar loading, error/empty states, authentication boundaries, and desktop/mobile parity.
- Grouped Data Grid: expandable grouped rows, host-owned summary values, responsive cards, typed callbacks, and usage.
- Editable grid: reusable Add, inline Edit, Save, Cancel, Delete, validation, host-owned persistence callbacks, and responsive card editing.
- Model-driven CRUD: automatic list grid, responsive cards, and create/edit form generation from model metadata.
- Visual model form designer: reusable form layout metadata, live preview, spacing/class validation, and host-owned persistence.
- Dynamic menu: recursive autoload navigation, validation, search, active ancestry, and host-owned API/authorization boundaries.
- ERP sample pages: route matrix, responsive behavior, extension workflow, and static-versus-live integration boundaries.
- Authentication and navigation templates: two-step verification workflow and optional horizontal desktop navigation.
- Email template: reusable mailbox folders, message list, reading pane, compose workflow, responsive behavior, and mail-service boundaries.
- Kanban template: generic board contract, card movement, WIP limits, filtering, responsive behavior, and persistence boundary.
- Filter workspace: desktop filter rail, mobile filter sheet, status/search toolbar, grid/card parity, and host-owned query state.
- Product detail: responsive gallery, metrics, variants, specification tabs, edit boundary, and host-owned data contract.
- Editor workspace: main form/settings rail, responsive stacking, upload/tags composition, and host-owned save contract.
- Calendar: reusable Year/Month/Week/Day/List calendar, responsive year month-grid, mobile agenda, typed callbacks, and host-owned scheduling boundary.
- Vector map: provider-neutral SVG floor plans, projected locations, tracking trails, routes, markers, viewport state, and host-owned GPS/routing boundaries.
- Asset layout: positioned machines, computers, servers, and devices with optional type/zone metadata, searchable selection, responsive detail, and typed host-owned move/rotation intents.
- Chat template: conversation list, responsive thread shell, message/composer components, accessibility, and live integration boundaries.
- AI chat template: provider-neutral assistant workspace, local simulation, responsive history/thread flow, cancellation, and secure host integration boundaries.
- Widgets: Velzon-inspired metric, progress, activity, and content widget components.
- Form modal: simple
@bind-Openform dialog with size, saving, validation, close, and custom-footer parameters. - Card grid: searchable Grid/List container with reusable profile/member cards and responsive behavior.
- Reconnect notice: default Blazor Server override, appsettings text, host placement, framework state contract, and safe visual preview.
- Device notifications: reusable action, Web Notification API adapter, MAUI native adapter boundary, permissions, and security guidance.
Sample application
This repository includes a Blazor Web sample app:
dotnet run --project samples\Opx.MudBlazor.FlatUi.Sample\Opx.MudBlazor.FlatUi.Sample.csproj
Sample pages:
/file-uploaddemonstrates host-owned multiple upload, validation, progress, cancel, retry, and removal./grid-preferencesdemonstrates visibility, order, width, pinning, saved-view callbacks, reset, and virtualization contracts./tree-griddemonstrates reusable hierarchy rows, expand/collapse, drag/drop, cycle prevention, and host-persisted parent keys./hierarchy-designerdemonstrates a compact report-style outline, drag/drop and accessible movement, edit intent, and versioned JSON export./tree-griddemonstrates reusable hierarchy rows, expand/collapse, drag/drop, cycle prevention, and host-persisted parent keys./file-uploaddemonstrates host-owned multiple upload, validation, progress, cancel, retry, and removal./grid-preferencesdemonstrates visibility, order, width, pinning, saved-view callbacks, reset, and virtualization contracts.Dashboard: KPI cards, multipurpose chart, timeline, and priority table. Its default composition has no visible Refresh action; eligible mobile refresh is provided through the explicit pull-to-refresh handler and synchronized AppBar loading line.
Jobs dashboard: hiring KPIs, trend chart, activity feed, filtered role board, and sample create-job modal.
Login: standalone full-screen auth page with compact text/combo style and sample-only sign-in flow.
CRUD: desktop grid, mobile cards, filter bottom sheet, paging, and an editor shell demonstrating
CloseOnOutsideClick="true".CRUD Simple: minimal list page with only
Addaction and a compact CRUD editor form demonstrating the default explicit Back/Cancel-only dismissal.Email: responsive mailbox folders, searchable message list, reading pane, attachment card, reply/forward/delete, compose editor, mobile FAB, and sample-only pull-to-refresh.
Edit Account: responsive user-account form with photo/initial avatar fallback, profile details, locale preferences, security summary, optional password change, and in-memory Save/Cancel behavior.
Monitoring: service health table, incident feed, and device cards.
Monitoring Database: mobile-first read-only database status list with search, source marker, filter, status chips, and compact fact cards.
Static / Master: read-only master-data style page.
Reports: reusable operational report viewer with filter parameters, KPI summary, grouped desktop table, subtotal/grand total, drill-down, export callbacks, and grouped mobile cards; see reporting documentation.
Calendar: reusable Year/Month/Week/Day/List scheduling surface with a responsive 12-month grid, optional category/upcoming-events rail, host-owned event callbacks, and a compact mobile agenda.
Vector Map: interactive SVG floor-plan regions, projected GPS marker snapshots, tracking trails, preferred/alternative routes, zoom/reset controls, and exact host-owned selection callbacks.
Spatial Operations: reusable list-to-map workspace with mutually exclusive floors, overlay layers, polygon/circle geofences, route playback intents, exact item selection, and responsive desktop/mobile composition.
Asset Layout: reusable machine/computer/device map over typed vector regions with optional type/zone selectors, controlled selection/edit state, and host-validated movement requests.
Product Catalog: ecommerce-style product cards, desktop filter rail, result-toolbar search, staged category/price filter sheet at tablet/mobile widths, stock, rating, wishlist, and cart action.
Website Front: public landing/front page shell with hero, CTA buttons, featured catalog cards, feature blocks, and footer.
Blog: public content listing with article cards.
ERP Overview: cross-module KPI, workflow inbox, responsive business-exception cards with collision-safe status columns, and drill-down module launcher.
Human Resources: overview, employee directory, and attendance/leave sample pages.
Production: production plan, work orders, progress, and quality-control sample pages.
Finance: overview, general ledger, accounts payable, and accounts receivable sample pages.
Supply Chain: procurement dashboard and responsive inventory sample pages.
Sales & Distribution: sales overview, fulfillment pipeline, and sales-order sample page.
Components: palette, empty state, stat cards, detail section, and usage snippet.
Charts: all eleven MudBlazor 9.7.0 chart types with responsive rendering and expandable copy-ready Razor samples.
Theme
Use FlatUiTheme.CreateTheme() for the MudBlazor theme and FlatUiTheme.CreateCssVariables() for runtime CSS variables when a host app needs branding overrides.
Set OpxFlatUi:Display:DefaultThemeMode to Auto, Light, or Dark. The default is Auto. Include _content/Opx.MudBlazor.FlatUi/opx-flat-ui-theme-bootstrap.js before stylesheets so a dark device starts on the dark background without a Light-theme flash. Theme mode is stored with the scoped display preferences; Cancel restores the prior mode and Restore clears the override.
Configuration and environment
OpxFlatUi:Display:DefaultDensity:Compact,Default, orComfortableapplication default.OpxFlatUi:Display:DefaultInputStyle:Standard,Filled, orOutlined; default and invalid-value fallback areOutlined. Settings live-previews and persists this scoped per-user choice. Reusable controls map it to the native MudBlazorVariantthroughFlatUiPreferencesService.InputVariant; an explicit componentVariantremains an intentional override.OpxFlatUi:Display:LightSidebarBackground,LightSidebarForeground,DarkSidebarBackground, andDarkSidebarForeground: six-digit hex app defaults for theme-specific navigation surfaces. Settings exposes accessible color and hex controls, live-preview, Save, Cancel, and Restore; invalid per-user values fall back independently to these normalized app defaults.OpxFlatUi:Application: mandatory initial host metadata and branding used by the host document and Login template; configure it during scaffolding before feature-page development. ProvideAppName,CompanyName, aCopyrighttemplate with{Year}/{CompanyName}tokens, plusLoginBrandBackgroundColor, optionalLoginBrandBackgroundImageUrl,LoginBrandPanelVisible,LoginBrandOverlayColor,LoginBrandOverlayOpacity, andLoginLayout(DefaultorBoxed).DefaultwithLoginBrandPanelVisible=truepreserves the split desktop/current mobile composition;falsehides the brand panel and centers the unboxed form.Boxedcenters the same theme-safe form over the configured brand background. Render<meta name="author" content="@ApplicationOptions.ResolvedAuthor" />once in the host document<head>so it applies to every route.LogoandLogoUrlare optional; leave both blank/null to render no logo or reserved gap. A configuredLogoaccepts a supported icon alias or trusted MudBlazor SVG path, whileLogoUrlaccepts a validated relative/HTTP(S) image. Colors require six-digit hex and opacity is clamped to0-0.85; invalid values use safe defaults.- Login omits the duplicate top mobile identity row and any static security/sample footer banner. The local sample accepts
operator@opx.local/sample; required or invalid credentials use the shared Error MessageBox with generic wording. Replace that local comparison in production hosts. - Unknown routes resolve the AppBar PageTitle to
Not found; the Not Found sample uses the standard responsive page gutters instead of edge-aligned copy. OpxFlatUi:Display:DefaultThemeMode:Auto,Light, orDark;Autoresolves the device preference before first paint when the documented bootstrap is installed. Explicit Light/Dark overrides the device for the complete root and component tree; the bootstrap isolatesopx-root-theme-*classes from shelltheme-*classes to prevent mixed backgrounds and surfaces.OpxFlatUi:Display:DefaultColorPalette: palette ID selected when no user override exists. Built-in IDs areblue,teal,violet,orange,trust,slate,ocean,emerald,rose, andfluent-blue.OpxFlatUi:Display:ColorPalettes: optional replacement palette list. Each item definesId,Label,Description, four Light accent tokens (Accent,AccentHover,AccentSubtle,AccentDark), four Dark/Night tokens (DarkAccent,DarkAccentHover,DarkAccentSubtle,DarkAccentDark), and optional semantic tokens (Secondary,Success,Warning,Danger). Colors must use six-digit hexadecimal notation.OpxFlatUi:Display:UseAppFontSize: initial user preference for font ownership.falseselects Device by default so the component tree follows the device/browser root (1rem) and accessibility scaling;trueinitially selects Manual. Users can switch Device/Manual in Settings and save that choice per user.OpxFlatUi:Display:DefaultFontSizePx: initial Manual font size; the cross-platform OPX baseline is16px. The saved Manual value is retained while Device mode is active, so switching back restores the user's last size.OpxFlatUi:Display:DefaultFabShape: global mobile FAB shape,Circle(default) orSquare. Invalid values fall back toCircle; an individualFlatFabmay deliberately override it throughShape.OpxFlatUi:Display:DefaultRoundedSizePx: shared button and bottom-sheet corner radius, clamped to0-12. The default0preserves the flat design; cards, inputs, dialogs, menus, and other surfaces are intentionally unaffected. Users can preview and persist this value from Settings.- The
16pxapp baseline resolves information-dense screens to roughly14pxoperational copy,13pxsupporting copy, and11pxmetadata. Interface density remains independent:Compact,Default, andComfortablechange spacing/control geometry without changing the selected font size. OpxFlatUi:Display:MinimumFontSizePxandMaximumFontSizePx: limits exposed byFlatDisplaySettingswhen app-controlled font sizing is enabled.OpxFlatUi:Display:StorageKey: browser storage key; use a unique value per host application.OpxFlatUi:Grid:DefaultPageSize: global initial page size forGridViewState; normalized to1-500. Construct page state withnew GridViewState(gridOptions)so the initial API request also uses the configured value.OpxFlatUi:Grid:PageSizes: global page-size choices forFlatPager. Values outside1-500are removed, duplicates are removed, and the normalized default is always included. A page may override these choices with thePageSizesparameter and may override its current size throughSetPageSize(...).OpxFlatUi:Grid:DefaultHeaderStyle: global header presentation forFlatDataGrid,FlatGroupedDataGrid, andFlatEditableGrid; package default/fallback isCompactSearch.OpxFlatUi:Grid:ShowHeaderIcons: globally shows optionalGridColumnDefinition.HeaderIconmetadata in compact headers; package default isfalse. Search, sort, and filter affordances remain available.OpxFlatUi:Reconnect: reconnecting, paused, failed, and retry text used byFlatReconnectModal; restart the host after changing these startup-bound values.- A server restart discards the old Blazor Server circuit. The reconnect notice reaches the rejected state and Try again performs the required full reload to create a fresh circuit. The sample enables detailed circuit diagnostics only in Development; keep them disabled in Production.
OpxFlatUi:Snackbar:HideTransitionDurationMs: global snackbar fade-out duration. The OPX baseline is200ms, normalized to100-3000ms; bindFlatSnackbarOptionsbeforeAddMudServicesand assignSnackbarConfiguration.HideTransitionDuration. This does not shorten the visible message duration.OpxFlatUi:DeviceNotification: optional showroom/default notification title, message, icon URL, and tag; real application payloads normally come from the active use case.- The sample provides safe baseline, Development, Staging, and Production configuration files. Environment-specific files inherit the baseline display defaults unless overridden.
- There are no project-specific environment variables. Standard
ASPNETCORE_ENVIRONMENTselectsDevelopment,Staging, orProduction; set it explicitly in deployment and restart the host after changing it.
Example custom host palette:
{
"OpxFlatUi": {
"Display": {
"AppBarSearchVisible": true,
"DefaultColorPalette": "brand",
"ColorPalettes": [
{
"Id": "brand",
"Label": "Brand",
"Description": "Host application accent.",
"Accent": "#0067c0",
"AccentHover": "#005a9e",
"AccentSubtle": "#e5f1fb",
"AccentDark": "#004578",
"DarkAccent": "#4cc2ff",
"DarkAccentHover": "#75d1ff",
"DarkAccentSubtle": "#102c3b",
"DarkAccentDark": "#a6e2ff"
}
]
}
}
}
When ColorPalettes is supplied it replaces the built-in choice list. Invalid color values fall back to safe OPX defaults. Restart the host after changing appsettings; Restore application defaults clears the browser override and applies the configured default palette.
- Accordion: reusable default/flush disclosure groups with optional icons, single/multiple expansion, disabled state, and responsive theme parity.
- Job Landing: public career portal composition with search hero, hiring process, category discovery, responsive role results, featured employers, typed email-application callback, and host-owned delivery/storage.
- Page identity and prompt routing defines stable unique PageIds for every sample route and maps future page prompts to the correct source archetype.
- Spatial operations documents layer/floor selection, geofences, synchronized work items, route playback, responsive behavior, and host-owned integration boundaries.
Hybrid reliability hardening
See P0–P2 hybrid hardening for native scroll arbitration, overlay Back, keyboard refresh, resume retention, explicit retry and artifact evidence.
| 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
- HtmlSanitizer (>= 9.2.1039)
- Markdig (>= 1.3.2)
- Microsoft.AspNetCore.Components.Authorization (>= 10.0.12)
- Microsoft.AspNetCore.Components.Web (>= 10.0.12)
- MudBlazor (>= 9.10.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.45 | 71 | 9/30/2026 |
| 2.1.44 | 82 | 9/27/2026 |
| 2.1.43 | 87 | 9/24/2026 |
| 2.1.42 | 90 | 9/23/2026 |
| 2.1.41 | 96 | 9/23/2026 |
| 2.1.40 | 99 | 9/21/2026 |
| 2.1.38 | 94 | 9/20/2026 |
| 2.1.37 | 97 | 9/18/2026 |
| 2.1.36 | 105 | 9/17/2026 |
| 2.1.35 | 94 | 9/17/2026 |
| 2.1.34 | 115 | 9/15/2026 |
| 2.1.33 | 99 | 9/15/2026 |
| 2.1.32 | 100 | 9/14/2026 |
| 2.1.31 | 93 | 9/14/2026 |
| 2.1.30 | 99 | 9/13/2026 |
| 2.1.29 | 104 | 9/12/2026 |
| 2.1.27 | 99 | 9/11/2026 |
| 2.1.26 | 101 | 9/10/2026 |
| 2.1.25 | 106 | 9/10/2026 |
| 2.1.24 | 99 | 9/10/2026 |