Skip to content

Repository files navigation

Project Pulse

Project Pulse is a .NET 10 Blazor Server demo showing how HTML Invoker Commands can own transient interface behavior—such as opening dialogs and toggling popovers—without JavaScript handlers, JS interop, or Blazor visibility state.

The application presents a responsive project dashboard where the browser manages UI mechanics and Blazor manages application data.

What the demo shows

  • Native <dialog> elements opened and closed with commandfor and command.
  • A native popover menu toggled without JavaScript or @onclick.
  • A hybrid delete flow where the browser closes the dialog and Blazor removes the project.
  • A project creation flow where the dialog remains browser-owned while Blazor validates and creates the project.
  • Responsive layouts for mobile, tablet, and desktop widths.
  • Keyboard-accessible controls, semantic headings, labeled dialogs, and native focus behavior.

Requirements

  • .NET 10 SDK
  • A current browser with support for the HTML command and commandfor attributes

No Node.js packages, frontend build tools, database, or external services are required.

Quick start

From the repository root:

cd .\ProjectPulse
dotnet restore .\ProjectPulse.slnx
dotnet run --project .\ProjectPulse.csproj

Open the local URL printed by dotnet run.

Commands

Run these commands from the ProjectPulse directory:

Command Description
dotnet run --project ProjectPulse.csproj Start the Blazor Server application.
dotnet test ProjectPulse.slnx Run the dashboard state tests.
dotnet build ProjectPulse.slnx Build the application and test project.
dotnet build ProjectPulse.slnx --configuration Release Produce a release build.

The architectural boundary

The central idea is that opening a dialog is usually interface behavior, not application state.

Browser-owned behavior

The details dialog is opened declaratively:

<button commandfor="details-dialog-phoenix" command="show-modal">
    View details
</button>

<dialog id="details-dialog-phoenix">
    <!-- Project details -->
    <button commandfor="details-dialog-phoenix" command="close">
        Close brief
    </button>
</dialog>

The browser owns opening, closing, top-layer presentation, and focus behavior. There is no _showDialog field and no JavaScript event handler.

The Actions menu follows the same approach with toggle-popover:

<button commandfor="project-menu-phoenix" command="toggle-popover">
    Actions
</button>

<div id="project-menu-phoenix" popover="auto">
    <!-- Menu actions -->
</div>

Blazor-owned behavior

Deleting a project changes application data, so that operation remains a Blazor concern:

<button commandfor="@DeleteDialogId"
        command="close"
        @onclick="() => OnDelete.InvokeAsync(Project.Id)">
    Delete project
</button>

One button crosses the boundary deliberately:

  • command="close" lets the browser close the dialog immediately.
  • @onclick invokes the Blazor business action.

This keeps transient UI mechanics out of the server-side component state while preserving Blazor for validation and data mutation.

Project structure

ProjectPulse/
├── Components/
│   ├── Pages/
│   │   ├── Home.razor
│   │   └── Home.razor.css
│   └── Projects/
│       ├── ProjectCard.razor
│       └── ProjectCard.razor.css
├── Features/Projects/
│   ├── ProjectDashboardState.cs
│   └── ProjectSummary.cs
├── ProjectPulse.Tests/
│   └── ProjectDashboardStateTests.cs
├── wwwroot/app.css
├── Program.cs
├── ProjectPulse.csproj
└── ProjectPulse.slnx
  • Home.razor composes the dashboard, portfolio metrics, empty state, and project creation dialog.
  • ProjectCard.razor contains the native details dialog, popover menu, and hybrid delete confirmation.
  • ProjectDashboardState owns the in-memory project collection and its business operations.
  • ProjectDashboardStateTests verifies creation, deletion, validation, and portfolio metric updates.

Data and persistence

The application is intentionally self-contained. Project data is stored in memory for the current Blazor circuit and resets when the application or user session is restarted. This keeps the demo focused on the boundary between native HTML behavior and Blazor application behavior.

Verification

The demo has been verified with:

  • Four passing .NET tests.
  • Native dialog open and close commands.
  • Native popover toggle and dismissal commands.
  • Blazor-backed create and delete flows.
  • Responsive checks at 320, 768, 1024, and 1440 pixels.
  • A clean browser console with no warnings or errors.

About

Cool project showing how to use HTML invokers inside of your Blazor applications.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages