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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SyntaxCircus.Blazor.Components" Version="0.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SyntaxCircus.Blazor.Components" Version="0.1.2" />
                    
Directory.Packages.props
<PackageReference Include="SyntaxCircus.Blazor.Components" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SyntaxCircus.Blazor.Components --version 0.1.2
                    
#r "nuget: SyntaxCircus.Blazor.Components, 0.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SyntaxCircus.Blazor.Components@0.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SyntaxCircus.Blazor.Components&version=0.1.2
                    
Install as a Cake Addin
#tool nuget:?package=SyntaxCircus.Blazor.Components&version=0.1.2
                    
Install as a Cake Tool

SyntaxCircus.Blazor.Components

Build NuGet License: MIT

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 the syntax-circus-not-found class;
  • an h1 reading “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:

  1. HeaderContent replaces the generated h1; otherwise Title is rendered as the h1.
  2. ChildContent replaces the generated description; otherwise non-empty Description is rendered.
  3. ActionsContent replaces the default action region; otherwise the home link is rendered only when ShowDefaultActions is true and HomeHref is non-empty.
  4. 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-found re-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 with aria-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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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.

Version Downloads Last Updated
0.1.2 166 8/21/2026
0.1.1 278 8/21/2026
0.1.0 99 8/20/2026