A modern Blazor component library powered by Tailwind CSS v4.
280+ components - Blazor WASM / Server / MAUI Hybrid - Light / Dark / System - Zero external JS dependencies
MyStackBlazor is a production-ready UI library for .NET 10 Blazor applications.
- 280+ components across Common, Form, Layout, Navigation, Overlays, Data, Charts, Media, Chat, Blocks, and Templates
- Tailwind CSS v4 styling (precompiled CSS included)
- Built-in theming via
ThemeServiceandStackThemeProvider - Accessibility-focused patterns and keyboard support
- Optional modular packages for DataGrid, Security, Accessibility, Localization, and Core primitives
dotnet add package MyStackBlazorOptional add-on packages (each has its own README on nuget.org):
| Package | What it adds | Register |
|---|---|---|
| MyStackBlazor.DataGrid | Virtualized server-side grid, grouping, Excel export | AddMyStackBlazorDataGrid() |
| MyStackBlazor.Calendar | Calendar / scheduler (day, week, month, timeline, agenda) | AddMyStackBlazorCalendar() |
| MyStackBlazor.Security | HTML sanitizer, token providers | AddMyStackBlazorSecurity() |
| MyStackBlazor.Localization | RTL provider, localized labels | AddMyStackBlazorLocalization() |
| MyStackBlazor.Accessibility | Focus management, ARIA helpers (included by MyStackBlazor) | AddMyStackBlazorAccessibility() |
| MyStackBlazor.Core | State primitives (included by MyStackBlazor) | — |
All packages ship XML docs for IntelliSense and symbol packages with SourceLink, so you can step into library code while debugging.
Or manually:
<PackageReference Include="MyStackBlazor" Version="1.*" />builder.Services.AddMyStackBlazor();Add in wwwroot/index.html (WASM) or your host/app shell:
<link rel="stylesheet" href="_content/MyStackBlazor/css/mystackblazor.css" />
<script src="_content/MyStackBlazor/js/mystackblazor.js"></script>In _Imports.razor:
@using MyStackBlazor
@using MyStackBlazor.Components
@using MyStackBlazor.Components.Common
@using MyStackBlazor.Components.Form
@using MyStackBlazor.Components.Navigation
@using MyStackBlazor.Components.Layout
@using MyStackBlazor.Components.Overlays
@using MyStackBlazor.Components.Data
@using MyStackBlazor.Components.Charts
@using MyStackBlazor.Components.Calendar
@using MyStackBlazor.Components.PivotGrid@inherits LayoutComponentBase
<StackThemeProvider>
<div class="min-h-screen bg-background text-foreground">
<header>
<StackThemeToggle />
</header>
<main>
<StackToaster />
@Body
</main>
</div>
</StackThemeProvider>All public components use the Stack prefix.
<StackButton>Save</StackButton>
<StackDialog @bind-IsOpen="_open">
<StackDialogTitle>Confirm</StackDialogTitle>
</StackDialog>Special names to note:
StackMsCalendarStackMsVirtualListStackMsPivotGrid
@page "/"
<StackCard Class="max-w-xl">
<StackCardHeader>
<StackCardTitle>Welcome</StackCardTitle>
<StackCardDescription>MyStackBlazor is wired up.</StackCardDescription>
</StackCardHeader>
<StackCardContent>
<StackInput @bind-Value="_name" Placeholder="Your name" />
</StackCardContent>
<StackCardFooter>
<StackButton OnClick="Save">Save</StackButton>
</StackCardFooter>
</StackCard>
@code {
private string _name = string.Empty;
private void Save() { }
}StackThemeProvider applies and persists theme state. Use ThemeService in any component:
@inject ThemeService ThemeService
ThemeService.SetTheme(AppTheme.Light);
ThemeService.SetTheme(AppTheme.Dark);
ThemeService.SetTheme(AppTheme.System);
ThemeService.Toggle();
bool isDark = ThemeService.IsDark;StackButton, StackBadge, StackAvatar, StackIcon, StackTypography, StackLabel, StackSeparator, StackSkeleton, StackSpinner, StackThemeToggle, StackCopyButton, StackCountdown
StackInput, StackTextarea, StackSelect, StackCheckbox, StackSwitch, StackRadioGroup, StackNumericInput, StackSlider, StackRangeSlider, StackDatePicker, StackDateRangePicker, StackDateTimePicker, StackTimePicker, StackInputOtp, StackColorPicker, StackColorPalette, StackMaskedTextBox, StackMultiSelect, StackCombobox, StackAutoComplete, StackListBox, StackFileUpload, StackTagInput
StackCard, StackAccordion, StackCollapsible, StackScrollArea, StackAspectRatio, StackGridLayout, StackLayout, StackSplitter, StackCarousel, StackPanelBar, StackLoader, StackAnimationContainer, StackInfiniteScroll
StackTabs, StackBreadcrumb, StackPagination, StackSidebar, StackAppBar, StackMenubar, StackDropdownMenu, StackContextMenu, StackToggleButton, StackToolbar, StackStepper, StackWizard, StackWorkflow, StackBottomNavigation
StackDialog, StackAlertDialog, StackSheet, StackDrawer, StackPopover, StackPopup, StackTooltip, StackHoverCard, StackWindow, StackToaster, StackImageViewer, StackFileViewer
StackAlert, StackStatCard, StackDescriptionList, StackTable, StackDataTable, StackAdvancedTable, StackPivotGrid, StackTreeView, StackTreeList, StackListView, StackFileManager, StackMsVirtualList, StackMsCalendar, StackMsPivotGrid
StackLineChart, StackBarChart, StackPieChart, StackDoughnutChart, StackGaugeChart, StackRadarChart, StackScatterChart, StackHeatMapChart, StackSankeyChart, StackTimeSeriesChart, StackSparkline
Reusable page blocks and full templates exist under src/MyStackBlazor/Components/Blocks and src/MyStackBlazor/Components/Templates.
For a detailed catalog and notes, see COMPONENTS.md.
Manages light/dark/system theme state.
Global notifications via StackToaster + ToastService:
@inject ToastService Toast
Toast.Show("Saved successfully!", ToastType.Success);
Toast.Show("Something went wrong.", ToastType.Error);builder.Services.AddMauiBlazorWebView();
builder.Services.AddMyStackBlazor();Use the same _content/MyStackBlazor/... CSS/JS asset references in your MAUI web root.
MyStackBlazor(main package, 192 components)MyStackBlazor.CoreMyStackBlazor.DataGridMyStackBlazor.CalendarMyStackBlazor.AccessibilityMyStackBlazor.LocalizationMyStackBlazor.Security
Install any add-on package with:
dotnet add package MyStackBlazor.DataGrid- Theme state is scoped per Blazor Server circuit. Keep
AddMyStackBlazor()registrations scoped when customizing DI. StackDialogtraps keyboard focus, restores focus on close, and closes on Escape by default. UseAriaLabelledByto reference a visible title (or supplyAriaLabel), andAriaDescribedByfor descriptive text. SetCloseOnEscape="false"for flows that require an explicit decision.StackFileUploadenforcesMaxFileSizeBytesand the cumulativeMaxFileslimit. Rejections appear inline and are available throughOnRejected. Validate size, content, authorization, and storage names on the server as well;Acceptis a browser hint.- CSV exports protect against spreadsheet formulas by default. The three-argument
ExportToCsv(..., spreadsheetSafe: false)overload is only for trusted machine-to-machine data. JSON exports preserve native numbers, booleans, and nulls.
StackCurrencyInput accepts an explicit Culture used for both parsing and formatting. For example, CultureInfo.GetCultureInfo("en-IN") displays Indian grouping, while de-DE accepts a decimal comma. Set CurrencySymbol="₹" separately for rupee amounts.
Both StackCurrencyInput and StackNumericInput support ValueExpression, EditContext validation, ReadOnly, accessible stepper labels and a configurable ParsingErrorMessage. Invalid input stays visible and adds a field validation error without overwriting the last valid model value. Use ValidationMessage or ValidationSummary in forms to display these errors. HTML number inputs use invariant wire values regardless of the application's culture.
<StackCurrencyInput @bind-Value="model.Amount"
Culture="@System.Globalization.CultureInfo.GetCultureInfo("en-IN")"
CurrencySymbol="₹" Min="0" />
<ValidationMessage For="@(() => model.Amount)" />Sheets and drawers use the same focus manager as dialogs. Supply AriaLabelledBy with a visible title ID, or set AriaLabel; use CloseOnEscape="false" when dismissal must require an explicit choice.
# Restore
dotnet restore
# Build library
dotnet build src/MyStackBlazor/MyStackBlazor.csproj
# Build demo
dotnet build samples/MyStackBlazor.Demo/MyStackBlazor.Demo.csprojTailwind rebuild from src/MyStackBlazor:
npm ci
npm run build:cssPack NuGet:
./pack.ps1CI builds CSS from package-lock.json, builds the solution, runs unit and Chromium browser tests, and checks the seven packed libraries and their internal dependency versions, and compiles a clean Razor consumer from those packages. Releases reuse this workflow and check out the exact release tag; the publishing job downloads the validated package artifact rather than rebuilding it.
NuGet Trusted Publishing must authorize the ci.yml publishing workflow. For the Release Please path, ensure your NuGet publishing policy also permits the reusable-workflow caller (release-please.yml) as required by your policy. OIDC authentication is verified when a release runs; no credentials belong in this repository.
The sanitizer tests run in a separate project so bUnit’s DOM parser dependency does not constrain the production sanitizer.
Run unit tests:
dotnet test tests/MyStackBlazor.UnitTests -c Release
dotnet test tests/MyStackBlazor.Security.Tests -c ReleaseRun browser tests after building the solution (PowerShell is required for browser installation):
./tests/MyStackBlazor.E2ETests/bin/Release/net10.0/playwright.ps1 install chromium
# Start the demo in a separate terminal:
dotnet run --project samples/MyStackBlazor.Demo -c Release --no-launch-profile --urls http://127.0.0.1:5080
# Then:
dotnet test tests/MyStackBlazor.E2ETests -c ReleaseThe browser tests use http://127.0.0.1:5080/overlays by default. Set DEMO_BASE_URL to the full overlays page URL to test another host.
The compiled mystackblazor.css is committed. Run npm ci once in src/MyStackBlazor and normal builds will rebuild it whenever a .razor file changes. Without node_modules the build uses the committed CSS. Pass /p:SkipTailwind=true to skip the step.
The package version comes from version.txt (release-please bumps it). NuGet versions for every project live in Directory.Packages.props, and shared package metadata lives in src/Directory.Build.props.
dotnet pack src/MyStackBlazor -c Release # -> nupkg/MyStackBlazor.<version>.nupkg + .snupkg- Fork the repo
- Create a branch:
git checkout -b feat/my-change - Commit your changes
- Open a pull request
MIT (c) 2025 Vilas Sagar