htmxRazor 1.3.0
dotnet add package htmxRazor --version 1.3.0
NuGet\Install-Package htmxRazor -Version 1.3.0
<PackageReference Include="htmxRazor" Version="1.3.0" />
<PackageVersion Include="htmxRazor" Version="1.3.0" />
<PackageReference Include="htmxRazor" />
paket add htmxRazor --version 1.3.0
#r "nuget: htmxRazor, 1.3.0"
#:package htmxRazor@1.3.0
#addin nuget:?package=htmxRazor&version=1.3.0
#tool nuget:?package=htmxRazor&version=1.3.0
htmxRazor
[
](https://dotnet.
microsoft.com/)
Server-rendered UI components for ASP.NET Core with first-class htmx integration.
htmxRazor is a complete UI component library implemented as Razor Tag Helpers. Every component renders clean, semantic HTML styled by its own CSS design system. No client-side framework required — just add htmx attributes to any component for dynamic behavior.
Why htmxRazor?
- Server-rendered — No JavaScript framework. Components are Tag Helpers that render HTML on the server.
- htmx-native — Every component supports
hx-get,hx-post,hx-target,hx-swap, and all htmx attributes directly. - 80+ components — Buttons, forms, data tables, dialogs, command palette, tabs, trees, carousels, toasts, pagination, and more across 11 categories.
- Design tokens — Light/dark themes via CSS custom properties. Toggle with
data-rhx-themeorRHX.toggleTheme(). - Accessible — Semantic HTML, ARIA attributes, keyboard navigation, and screen reader support built in.
- Model binding — Form components integrate with ASP.NET Core model binding, validation, and
ModelExpression. - Zero config — One NuGet package. Two lines of setup. Start using components immediately.
Quick Start
1. Install
dotnet add package htmxRazor
2. Configure
// Program.cs
builder.Services.AddRazorPages();
builder.Services.AddhtmxRazor();
var app = builder.Build();
app.UseStaticFiles();
app.UsehtmxRazor(); // Serves component CSS, JS, and htmx from /_rhx/
app.MapRazorPages();
app.Run();
3. Register Tag Helpers
@* _ViewImports.cshtml *@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, htmxRazor
4. Use Components
<rhx-button rhx-variant="brand" rhx-size="large">
Save Changes
</rhx-button>
Feature Highlights
Buttons with Every Variant
<rhx-button rhx-variant="brand">Brand</rhx-button>
<rhx-button rhx-variant="success" rhx-appearance="outlined">Success</rhx-button>
<rhx-button rhx-variant="danger" rhx-appearance="plain">Delete</rhx-button>
<rhx-button rhx-variant="brand" rhx-pill="true">Pill Shape</rhx-button>
<rhx-button rhx-variant="brand" rhx-loading="true">Saving...</rhx-button>
Form Controls with Model Binding
<rhx-input rhx-for="Email" rhx-with-clear="true" />
<rhx-input rhx-label="Password"
rhx-type="password"
rhx-password-toggle="true"
name="password" />
htmx on Any Component
<rhx-input rhx-label="Search"
rhx-placeholder="Type to search..."
hx-get="/search"
hx-trigger="input changed delay:300ms"
hx-target="#results" />
<rhx-button rhx-variant="danger"
hx-delete="/api/items/42"
hx-confirm="Are you sure?"
hx-target="#item-list"
hx-swap="outerHTML">
Delete
</rhx-button>
Modal Dialogs
<rhx-button rhx-variant="brand" data-rhx-dialog-open="edit-dialog">
Edit Profile
</rhx-button>
<rhx-dialog id="edit-dialog" rhx-label="Edit Profile">
<rhx-input rhx-for="DisplayName" />
<rhx-dialog-footer>
<rhx-button rhx-variant="neutral" rhx-appearance="outlined"
onclick="this.closest('dialog').close()">Cancel</rhx-button>
<rhx-button rhx-variant="brand" type="submit">Save</rhx-button>
</rhx-dialog-footer>
</rhx-dialog>
Data Tables with Server-Driven Sort & Pagination
<rhx-data-table id="products" rhx-striped="true" rhx-hoverable="true"
rhx-sort-url="/Products?handler=TableData"
rhx-label="Product list">
<rhx-column rhx-field="name" rhx-header="Name" rhx-sortable="true" />
<rhx-column rhx-field="price" rhx-header="Price" rhx-sortable="true" />
<rhx-column rhx-field="stock" rhx-header="Stock" />
@foreach (var p in Model.Items)
{
<tr><td>@p.Name</td><td>@p.Price</td><td>@p.Stock</td></tr>
}
<rhx-data-table-pagination rhx-page="1" rhx-page-size="10"
rhx-total-items="@Model.TotalItems"
rhx-url="/Products?handler=TableData"
rhx-target="#products-body" />
</rhx-data-table>
Command Palette (Cmd+K Search)
<rhx-command-palette id="search"
rhx-placeholder="Search components..."
hx-get="/Search"
rhx-debounce="200">
</rhx-command-palette>
<rhx-command-group rhx-heading="Pages">
<rhx-command-item rhx-value="home" rhx-href="/" rhx-icon="home">
Home
</rhx-command-item>
</rhx-command-group>
Theming
<html data-rhx-theme="light">
<rhx-button onclick="RHX.toggleTheme()">Toggle Theme</rhx-button>
<style>
:root {
--rhx-color-brand-500: #6366f1;
--rhx-radius-md: 0.75rem;
}
</style>
Component Catalog
| Category | Components |
|---|---|
| Actions | Button, Button Group, Dropdown |
| Forms | Input, Textarea, Select, Combobox, Checkbox, Switch, Radio, Slider, Rating, Color Picker, File Input, Number Input |
| Feedback | Callout, Badge, Tag, Spinner, Skeleton, Progress Bar, Progress Ring, Tooltip, Toast, Toast Container |
| Navigation | Tabs, Breadcrumb, Tree, Carousel, Pagination, Skip Nav, Landmark |
| Organization | Card, Divider, Split Panel, Scroller |
| Overlays | Dialog, Drawer, Details, Command Palette |
| Data Display | Data Table, Sparkline |
| Imagery | Icon (48 built-in), Avatar, Animated Image, Comparison, Zoomable Frame |
| Formatting | Format Bytes, Format Date, Format Number, Relative Time |
| Utilities | Copy Button, QR Code, Animation, Popup, Popover, Live Region |
| Patterns | Active Search, Infinite Scroll, Lazy Load, Poll |
How It Compares
| htmxRazor | Bootstrap | Blazor | Web Awesome | |
|---|---|---|---|---|
| Rendering | Server (Tag Helpers) | Client (jQuery/JS) | Client (WebAssembly/SignalR) | Client (Web Components) |
| htmx support | Native on every component | Manual attribute wiring | N/A (own reactivity) | Manual attribute wiring |
| Bundle size | CSS + htmx (~14 KB gzip) | ~24 KB JS + ~22 KB CSS | ~2 MB WebAssembly runtime | ~80 KB JS |
| Model binding | ASP.NET Core ModelExpression |
None | Blazor @bind |
None |
| Dependencies | ASP.NET Core | jQuery | .NET runtime in browser | Lit |
| Theming | CSS custom properties | Sass variables | CSS isolation | CSS custom properties |
Solution Structure
| Project | Description |
|---|---|
htmxRazor |
Core Tag Helper library with embedded CSS/JS assets |
htmxRazor.Demo |
Documentation site showcasing all components |
htmxRazor.Tests |
1,652 unit tests for Tag Helper rendering |
Development
# Build
dotnet build
# Run tests
dotnet test
# Run the demo site
dotnet run --project htmxRazor.Demo
# Pack for NuGet
dotnet pack htmxRazor/htmxRazor.csproj --configuration Release
Design System
htmxRazor owns its entire rendering and styling stack:
- CSS Custom Properties for design tokens (colors, spacing, typography, borders, shadows)
- BEM naming with
rhx-prefix (rhx-button,rhx-button--brand,rhx-button__label) - Light/dark themes via
data-rhx-themeattribute on<html> - Utility classes for layout and spacing (
rhx-flex,rhx-gap-md,rhx-p-lg) - Auto-injected assets —
AddhtmxRazor()injects tokens, reset, core, and utilities CSS plus the htmx script into<head>
The project uses a custom CSS design system — not Bootstrap or any other CSS framework.
Key details from the codebase instructions:
- BEM naming convention with an rhx- prefix (e.g., .rhx-button, .rhx-button--loading, .rhx-button__icon)
- CSS custom properties (design tokens) defined in rhx-tokens.css — things like --rhx-color-brand-500, --rhx-radius-md, --rhx-font-size-base
- Light/dark theme support via a data-rhx-theme attribute on <html>
- Each component has its own scoped CSS file in Assets/css/components/
- All CSS is embedded and served at /_rhx/ — no external dependencies
- Hardcoded values are not allowed; everything references var(--rhx-*) tokens
It's a fully self-contained design system built specifically for this component library.
Roadmap
Features ranked by user impact and implementation effort. The library is at v1.3.0 with 80+ components; the roadmap below covers what comes next.
v1.2 — Notifications, Pagination & Quick Wins (Shipped)
- Toast Notification System —
<rhx-toast-container>+<rhx-toast>with auto-dismiss, severity variants, stacking, andaria-liveannouncements. - Pagination —
<rhx-pagination>with htmx-powered page navigation, ellipsis, first/last/prev/next buttons, and size variants. - ARIA Live Region Manager —
<rhx-live-region>for screen reader announcements on htmx swaps. - CSS Cascade Layers — All component CSS wrapped in
@layerfor easy host app overrides without specificity wars. - View Transition Support —
rhx-transitionandrhx-transition-nameattributes for the View Transitions API.
v1.3 — Data Table, Accessibility & Modern CSS (Shipped)
- Data Table —
<rhx-data-table>,<rhx-column>,<rhx-data-table-pagination>with server-driven sort, filter, and pagination. IncludesDataTableRequestmodel binder auto-registered viaAddhtmxRazor(). - Command Palette —
<rhx-command-palette>modal search overlay activated via Cmd+K / Ctrl+K with debouncedhx-get, grouped results via<rhx-command-group>and<rhx-command-item>, and full keyboard navigation. - Focus Management After Swaps —
rhx-focus-after-swapattribute on the base class. On by default for<rhx-dialog>and<rhx-drawer>(WCAG 2.4.3). - Skip Nav & Landmarks —
<rhx-skip-nav>and<rhx-landmark>for semantic page regions (WCAG 2.4.1). - Container Queries — Card, dialog, split panel, and data table CSS use
@containerqueries for container-responsive layouts. - APG Keyboard Audit — Tabs, tree, dropdown, and combobox audited against W3C ARIA Authoring Practices Guide. Added type-ahead,
*expand siblings,Alt+Arrowpatterns.
v1.4 — Real-time, Wizard & Patterns
| Feature | Description | Impact | Effort |
|---|---|---|---|
| SSE Stream Container | <rhx-sse-stream> wraps hx-ext="sse" + sse-connect into a declarative Tag Helper. Companion HtmxSseExtensions.WriteEventAsync() formats IAsyncEnumerable<string> as text/event-stream. Aligns with htmx 4.0's streaming-first direction. |
High | Medium |
| Multi-step Wizard | <rhx-wizard>, <rhx-wizard-step> with visual stepper indicator, auto-generated navigation buttons with hx-post/hx-get, and server-side step state tracking. |
High | High |
| Response-Aware Form | <rhx-htmx-form> that auto-configures the htmx response-targets extension (hx-target-422, hx-target-5xx) and injects error-handling JavaScript. Removes per-form boilerplate. |
High | Medium |
| Timeline | <rhx-timeline>, <rhx-timeline-item> with variant-colored connectors, icon slots, and metadata regions. Pairs with <rhx-infinite-scroll> for loading additional events. Useful for audit logs, activity feeds, and order tracking. |
Medium | Medium |
| Optimistic UI | rhx-optimistic attribute on <rhx-switch>, <rhx-rating>, and <rhx-button>. Immediately reflects visual state on click before server response; reverts on error via htmx:responseError. |
Medium | Medium |
| Load More Pattern | <rhx-load-more> button-triggered pagination pattern. Simpler alternative to infinite scroll for content feeds. |
Medium | Low |
v2.0 — Platform & DX
| Feature | Description | Impact | Effort |
|---|---|---|---|
| Theme Builder | Interactive page in the demo site with sliders and color pickers for all --rhx-* tokens. Generates a downloadable rhx-theme-overrides.css file. |
High | High |
| Interactive Component Playground | Property toggle panel on each demo page. Users change variant, size, and state props; the server re-renders the component with updated markup via htmx. | High | High |
| SignalR Hub Connector | <rhx-signalr> Tag Helper wrapping SignalR hub connections with hub-url, method, target, and swap attributes. Server-side HtmxSignalRExtensions for sending HTML fragments from hubs. |
Medium | High |
| CSS Anchor Positioning | Replace JavaScript positioning in <rhx-tooltip> and <rhx-popover> with CSS Anchor Positioning API (with JS fallback). Reduces JS footprint and improves edge-of-viewport correctness. |
Medium | Medium |
| VS Code Snippet Extension | .code-snippets file with expansions for every <rhx-*> tag and common attribute combinations. Distributed alongside the NuGet package. |
Medium | Low |
| Kanban Board | <rhx-kanban>, <rhx-kanban-column>, <rhx-kanban-card> with native HTML Drag and Drop. Card drop events fire hx-post to update position server-side. |
Medium | High |
Infrastructure Cleanup (ongoing)
| Item | Description |
|---|---|
Implement or remove EnableCssIsolation |
Option is defined in htmxRazorOptions but has no implementation |
Remove IHtmxSupported marker interface |
Dead code — nothing checks for it |
Add hx-replace-url to base class |
Already exists as a response header helper but missing from tag helper attributes |
Adopt HtmlRenderer in components |
Replace raw StringBuilder HTML construction with the fluent HtmlRenderer for better escaping and readability |
| WCAG 2.2 contrast audit | Verify all foreground/background token pairs in rhx-tokens.css meet AA contrast ratios (4.5:1 normal text, 3:1 large text) |
Project Template
A .NET project template for htmxRazor is available in the templates/htmxRazor.Template directory. This template provides a clean starting point with:
- No jQuery or Bootstrap.
- Pre-configured
Program.csfor htmxRazor. - A base
_Layout.cshtmlincluding htmxRazor assets. - A sample
Index.cshtmldemonstrating htmx and htmxRazor components.
Installation
You can install the template locally from the source or from a NuGet package.
To install the template locally from source, run the following command from the project root:
dotnet new install ./templates/htmxRazor.Template
Alternatively, you can pack and install from the template package:
dotnet pack templates/htmxRazor.Templates.csproj -o nupkg
dotnet new install nupkg/htmxRazor.Templates.1.3.0.nupkg
Usage
To create a new project using the template, run:
dotnet new htmxrazor -n YourProjectName
Contributing
See CONTRIBUTING.md for development setup, PR guidelines, and coding standards.
License
MIT - Copyright (c) 2026 Chris Woody Woodruff
| 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
- Htmx (>= 1.12.0)
- Htmx.TagHelpers (>= 1.12.0)
- Microsoft.Extensions.FileProviders.Embedded (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.