SyntaxCircus.Blazor.Components
0.1.2
dotnet add package SyntaxCircus.Blazor.Components --version 0.1.2
NuGet\Install-Package SyntaxCircus.Blazor.Components -Version 0.1.2
<PackageReference Include="SyntaxCircus.Blazor.Components" Version="0.1.2" />
<PackageVersion Include="SyntaxCircus.Blazor.Components" Version="0.1.2" />
<PackageReference Include="SyntaxCircus.Blazor.Components" />
paket add SyntaxCircus.Blazor.Components --version 0.1.2
#r "nuget: SyntaxCircus.Blazor.Components, 0.1.2"
#:package SyntaxCircus.Blazor.Components@0.1.2
#addin nuget:?package=SyntaxCircus.Blazor.Components&version=0.1.2
#tool nuget:?package=SyntaxCircus.Blazor.Components&version=0.1.2
SyntaxCircus.Blazor.Components
Reusable, semantic Razor components for Blazor applications.
The package is Blazor/Razor-dependent and targets net10.0, but is deliberately UI/CSS-framework-agnostic. It does not bring Bootstrap, Tailwind, stylesheets, a layout, a router, middleware, or a design system. A consuming application owns all of those choices.
No support guaranteed. Published as-is and maintained on a best-effort basis. Issues and pull requests are welcome, but there is no SLA.
Install
dotnet add package SyntaxCircus.Blazor.Components
Import the component namespace in a page or in the application's _Imports.razor:
@using SyntaxCircus.Blazor.Components.Feedback
No service registration, JavaScript, CSS import, or middleware registration is required.
Components
| Component | Namespace | Purpose |
|---|---|---|
NotFoundView |
SyntaxCircus.Blazor.Components.Feedback |
Accessible, customizable markup for a not-found experience. |
ReconnectModal |
SyntaxCircus.Blazor.Components.Feedback |
Extensible Blazor Server circuit reconnect UI and behavior. |
LoggingErrorBoundary |
SyntaxCircus.Blazor.Components.Feedback |
Blazor error boundary that logs unhandled render failures. |
GlobalErrorBoundary |
SyntaxCircus.Blazor.Components.Feedback |
Recoverable, customizable application error boundary. |
GlobalErrorView |
SyntaxCircus.Blazor.Components.Feedback |
Presentation-only fallback view for a rendering failure. |
ReconnectModal |
SyntaxCircus.Blazor.Components.Feedback |
Extensible Blazor Server circuit reconnect UI and behavior. |
NotFoundView
NotFoundView renders an accessible not-found section with sensible defaults. It is presentation only: it never decides whether a resource is missing, navigates, sets an HTTP response status, changes a document title, or applies authorization.
Minimal usage
<NotFoundView />
The default output contains:
- a
<section>with thesyntax-circus-not-foundclass; - an
h1reading “Page not found”; - “The page you requested could not be found.”;
- a “Go home” link to
/.
Style the default class in the host application, or supply CssClass:
<NotFoundView CssClass="my-product-not-found" />
Public parameters
| Parameter | Type | Default | Behavior |
|---|---|---|---|
Title |
string |
"Page not found" |
Text for the default h1. Ignored when HeaderContent is supplied. |
Description |
string? |
"The page you requested could not be found." |
Text for the default paragraph. Ignored when ChildContent is supplied; set to null or empty to omit it. |
HomeHref |
string? |
"/" |
Destination for the default action link. Set to null or empty to omit the default link. |
HomeLabel |
string |
"Go home" |
Text for the default action link. |
CssClass |
string |
"syntax-circus-not-found" |
Class applied to the outer section. |
MediaContent |
RenderFragment? |
null |
Optional media/template rendered before the heading. |
HeaderContent |
RenderFragment? |
null |
Replaces the default h1; the host owns heading semantics when it is used. |
ChildContent |
RenderFragment? |
null |
Replaces the default description region. |
ActionsContent |
RenderFragment? |
null |
Replaces the default action-link region. |
ShowDefaultActions |
bool |
true |
Set to false to suppress the default action when ActionsContent is not supplied. |
Content precedence
The component intentionally uses predictable replacement rules:
HeaderContentreplaces the generatedh1; otherwiseTitleis rendered as theh1.ChildContentreplaces the generated description; otherwise non-emptyDescriptionis rendered.ActionsContentreplaces the default action region; otherwise the home link is rendered only whenShowDefaultActionsistrueandHomeHrefis non-empty.MediaContent, if present, is always rendered before the header.
Use a slot when the host needs richer markup. Do not duplicate the default region and the replacement slot unless that repetition is intentional.
Text and action customization
<NotFoundView Title="That page wandered off."
Description="Check the address or choose a destination below."
HomeHref="/catalog"
HomeLabel="Browse the catalog">
<ActionsContent>
<a class="button" href="/catalog">Browse the catalog</a>
<a class="button button-secondary" href="/support">Contact support</a>
</ActionsContent>
</NotFoundView>
Because ActionsContent is present, the generated “Go home” link is not rendered.
ReconnectModal
ReconnectModal supplies the standard Blazor Server reconnect, retry, pause, resume, and rejected-circuit behavior. Render it once in the host page body before blazor.web.js:
@using SyntaxCircus.Blazor.Components.Feedback
<Routes />
<ReconnectModal CssClass="my-product-reconnect" />
<script src="@Assets["_framework/blazor.web.js"]"></script>
The component deliberately supplies no visual CSS. Style CssClass and the stable data-reconnect-state regions in the host application. It uses a native dialog, so hosts should define the dialog surface, backdrop, spacing, contrast, focus treatment, and motion behavior for their design system.
Public parameters
| Parameter | Type | Default | Behavior |
|---|---|---|---|
CssClass |
string |
"syntax-circus-reconnect-modal" |
Class applied to the dialog. |
LoadingContent |
RenderFragment? |
null |
Optional content shown during first and repeated reconnection attempts. |
FirstAttemptContent |
RenderFragment? |
null |
Replaces the initial reconnect message. |
RetryingContent |
RenderFragment? |
null |
Replaces the repeated-attempt message. Include components-seconds-to-next-attempt when showing the Blazor retry delay. |
FailedContent |
RenderFragment? |
null |
Replaces the failed-reconnect message. |
PausedContent |
RenderFragment? |
null |
Replaces the paused-session message. |
ResumeFailedContent |
RenderFragment? |
null |
Replaces the failed-resume message. |
RetryActionContent |
RenderFragment? |
null |
Replaces the retry action. Its interactive element must have data-reconnect-action="retry". |
ResumeActionContent |
RenderFragment? |
null |
Replaces the resume action in both paused states. Its interactive element must have data-reconnect-action="resume". |
Only one element with the components-reconnect-modal ID may exist in a rendered host. The component's JavaScript is limited to the standard Blazor circuit APIs and is loaded automatically with the component.
Error boundaries
LoggingErrorBoundary is a standard Blazor ErrorBoundary that logs each unhandled rendering exception. GlobalErrorBoundary composes it with an accessible fallback, recovers when the user retries or navigates, and accepts the protected application content as ChildContent.
@using SyntaxCircus.Blazor.Components.Feedback
<GlobalErrorBoundary BoundaryName="admin UI"
CssClass="my-product-error"
Title="We couldn't load this screen.">
<ChildContent>
<Routes />
</ChildContent>
<ActionsContent>
<button type="button">Try again</button>
<a href="/">Home</a>
</ActionsContent>
</GlobalErrorBoundary>
GlobalErrorView may also be used directly when the host owns error detection and retry behavior. Both components retain these default parameters: Title, Description, RetryLabel, HomeHref, HomeLabel, and CssClass. GlobalErrorBoundary additionally exposes BoundaryName.
HeaderContent, body content (ChildContent on the view and ErrorBodyContent on the boundary), and ActionsContent replace their default regions. ExceptionContent is a typed RenderFragment<Exception> and renders only when the host explicitly provides it; exception details never appear by default. Supply custom actions only when they preserve a clear recovery or navigation path.
The components use semantic elements and stable syntax-circus-global-error/data-global-error-* hooks, but ship no visual CSS. Hosts provide theme, layout, focus, and responsive styling.
Branded header and body
Use the header and body slots to retain a host design system without making this package depend on it:
<NotFoundView ShowDefaultActions="false">
<HeaderContent>
<div class="hero hero--not-found">
<p class="eyebrow">Page not found</p>
<h1>That page wandered off.</h1>
<p>The address may be mistyped, moved, or no longer available.</p>
</div>
</HeaderContent>
<ChildContent>
<div class="content-card">
<h2>Try one of these instead</h2>
<a href="/">Home</a>
<a href="/support">Support</a>
</div>
</ChildContent>
</NotFoundView>
When supplying HeaderContent, include an appropriate heading in that fragment. The component does not generate a second h1 and therefore does not assign aria-labelledby to the outer section.
Images, illustrations, and arbitrary media
MediaContent accepts any Razor fragment. The package does not prescribe an image component, image source, dimensions, or alt text policy:
<NotFoundView>
<MediaContent>
<img src="/images/lost-page.svg"
width="320"
height="180"
alt="A map with a missing destination" />
</MediaContent>
</NotFoundView>
Give meaningful media meaningful alternative text. Mark purely decorative media as hidden from assistive technology in the host markup:
<MediaContent>
<img src="/images/confetti.svg" alt="" aria-hidden="true" />
</MediaContent>
Wiring a Blazor 404 flow
Rendering a not-found view and producing an HTTP 404 are related but separate responsibilities. Choose the path that matches the source of the missing content.
1. An unmatched Blazor route
Create a local adapter page in the host application. The local page owns route metadata, layout, SEO metadata, authorization, and product-specific content:
@page "/not-found"
@layout MainLayout
@attribute [AllowAnonymous]
<PageTitle>Page not found</PageTitle>
<NotFoundView Title="That page wandered off."
Description="The address may be mistyped, moved, or no longer available.">
<ActionsContent>
<a href="/">Home</a>
<a href="/support">Support</a>
</ActionsContent>
</NotFoundView>
[AllowAnonymous] is appropriate only when the host intends the adapter to be public. Applications that use a fallback authorization policy must also ensure their Razor Components endpoint and status-code re-execution path permit the intended request; page metadata alone may not run before endpoint authorization.
Point the root router at that local adapter:
<Router AppAssembly="typeof(Program).Assembly"
NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
Use AuthorizeRouteView instead of RouteView if the host application already requires route authorization:
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
In .NET 10, Router.NotFoundPage is the appropriate route-miss integration point. Add an integration test that requests a nonexistent public route and asserts both the expected page content and HttpStatusCode.NotFound.
2. A page or component discovers a missing resource
The router can match a route while a database/API lookup later establishes that the requested resource does not exist. In that case, the host decides to signal not-found:
@page "/products/{Slug}"
@inject NavigationManager Navigation
@inject IProductClient Products
@code {
[Parameter]
public string Slug { get; set; } = string.Empty;
protected override async Task OnParametersSetAsync()
{
var product = await Products.GetBySlugAsync(Slug);
if (product is null)
{
Navigation.NotFound();
return;
}
// Render the product.
}
}
NavigationManager.NotFound() is a .NET 10 host API. It tells Blazor that the current route result is not found; it is not called by NotFoundView, because a presentation component cannot know whether a domain resource is absent.
If the missing result is an authorization or privacy boundary, do not turn it into a public 404 without making that product/security decision explicitly. Preserve the host’s established behavior for 401, 403, and non-enumerating resources.
3. A non-Blazor endpoint or static-resource response is 404
API endpoints, file middleware, reverse proxies, and static-resource handling can generate a 404 outside the Blazor router. NotFoundView does not intercept those responses.
For a host that deliberately wants status-code re-execution to a local adapter, configure it in the HTTP pipeline:
app.UseStatusCodePagesWithReExecute(
"/not-found",
createScopeForStatusCodePages: true);
This middleware preserves the original status code while re-executing the request path. It is host-specific and has important consequences:
- register it at the deliberate pipeline location for the application, before endpoint mapping;
- ensure the
/not-foundre-execution path is compatible with the application’s authorization policy; - do not use it merely because a Blazor router already has
NotFoundPage; - do not apply an HTML error-page strategy to API endpoints that must return problem details, JSON, or an empty response;
- test the direct request, including status code and body, rather than assuming the rendered component changed the status.
For many component applications, Router.NotFoundPage covers unmatched UI routes and status-code middleware is unnecessary. Keep the decision local to the host.
Accessibility and semantics
- The default heading is an
h1, and the default outer section references it witharia-labelledby. - A custom header must contain a meaningful heading; the host owns the relationship between custom header content and surrounding landmarks.
- Default links are standard anchors. Host-provided action controls must remain keyboard-operable and have clear text or accessible names.
- The package does not set color, spacing, contrast, focus indicators, or responsive behavior. The host CSS must provide those qualities.
What this package does not do
This library deliberately does not:
- register services or middleware;
- call
NavigationManager.NotFound(); - set
HttpResponse.StatusCode; - choose a layout, render mode, router, authorization policy, SEO metadata, canonical URL, or robots directive;
- ship a CSS framework, image assets, icon library, or design system;
- translate or localize copy automatically.
These exclusions keep the public component contract reusable across server-rendered, interactive, authenticated, public, and mobile Blazor hosts.
Validation
dotnet test SyntaxCircus.Blazor.Components.slnx
dotnet pack src/SyntaxCircus.Blazor.Components/SyntaxCircus.Blazor.Components.csproj
The test suite covers default markup, replacement slots, and action suppression. Consumers should additionally test their own router and HTTP pipeline behavior.
Contributing
Add a component only when it has a stable, UI/CSS-framework-agnostic contract and at least two concrete consumer styles. Keep application layouts, branding, routing, HTTP middleware, and CSS systems in host applications.
See AGENTS.md for contributor and AI-agent guidance.
License
MIT — see LICENSE.txt.
| 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
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.