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.
- Native
<dialog>elements opened and closed withcommandforandcommand. - 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.
- .NET 10 SDK
- A current browser with support for the HTML
commandandcommandforattributes
No Node.js packages, frontend build tools, database, or external services are required.
From the repository root:
cd .\ProjectPulse
dotnet restore .\ProjectPulse.slnx
dotnet run --project .\ProjectPulse.csprojOpen the local URL printed by dotnet run.
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 central idea is that opening a dialog is usually interface behavior, not application state.
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>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.@onclickinvokes the Blazor business action.
This keeps transient UI mechanics out of the server-side component state while preserving Blazor for validation and data mutation.
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.razorcomposes the dashboard, portfolio metrics, empty state, and project creation dialog.ProjectCard.razorcontains the native details dialog, popover menu, and hybrid delete confirmation.ProjectDashboardStateowns the in-memory project collection and its business operations.ProjectDashboardStateTestsverifies creation, deletion, validation, and portfolio metric updates.
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.
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.