Build better products faster ... but with ASP.NET Blazor!

This project is a Blazor port of the Sitecore Blok design system - production-ready, idiomatic components for building industry-leading martech applications.

Conscious decisions have been made to replicate the Blok component structures as closely as possible, even when Blazor has the capability through RenderFragment Properties to present a more succinct structure. This is done to aid developers in transfering knowledge between libraries, since Razor and React component syntax is quite similar already. Further, it aids in the use of programatic tools being able to detect and maintain feature parity between the libraries if the structural differences are kept to a minimum.

To this end, you should find the documentation on the official Sitecore Blok library useful for this library also, save for specific divergences you will find noted on each component page in this catalogue site.

Introducing Chunks — composed page patterns

Chunks are opinionated compositions of one or more primitives. They package the recurring layout, spacing, and primitive choices that consumers would otherwise repeat — page envelopes, sticky headers, sidebars, KPI tiles, full-page state views, form fields with built-in error tracking, data-table pages, and shells for the Sitecore Marketplace extension points. Chunks know about layout and primitive choice; they never carry domain knowledge.

Use a chunk when you want the well-spaced, accessible composition without writing the Tailwind classes by hand. Drop down to primitives whenever you need to vary one specific aspect of the chunk's behaviour — the catalogue's Primitives tab on every chunk example shows the equivalent first-principles markup so you have a copy-paste starting point.

Prerequisites

.NET 10+

Required runtime

Blazor Server or WASM

Interactive render mode

Tailwind CSS

Blok theme included

Setup

1. Add the NuGet package

dotnet add package PINGWorks.SitecoreBlok.BlazorUI

2. Register services in Program.cs

builder.Services.AddSitecoreBlokUI();

3. Add using directives to _Imports.razor

@using PINGWorks.SitecoreBlok.BlazorUI
@using PINGWorks.SitecoreBlok.BlazorUI.Services

4. Configure App.razor

Add the Blok stylesheet and Prism.js (for CodeViewer syntax highlighting) to your App.razor:

<!DOCTYPE html>
<html lang="en">
<head>
	...
	@* Blok design system stylesheet *@
	<link rel="stylesheet" href="@Assets["_content/PINGWorks.SitecoreBlok.BlazorUI/css/sitecore-blok.css"]" />

	@* Prism.js for CodeViewer syntax highlighting *@
	<link rel="stylesheet" href="@Assets["_content/PINGWorks.SitecoreBlok.BlazorUI/vendor/prism/prism.css"]" />
	...
</head>
<body>
	<Routes />
	...
	@* Prism.js (required for CodeViewer component) *@
	<script src="@Assets["_content/PINGWorks.SitecoreBlok.BlazorUI/vendor/prism/prism.js"]"></script>
	<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>
</html>

5. Add service containers to MainLayout.razor

Components that use floating UI (such as Select, Popover, and DatePicker) require the <Popovers /> container. Toast notifications require the <Toaster /> container. Place both once in your layout with InteractiveServer render mode.

@inherits LayoutComponentBase

<div>
	@* Your header, sidebar, etc. *@

	<main>
		@Body
	</main>
</div>

@* Place service containers once, with InteractiveServer render mode *@
<Popovers @rendermode="InteractiveServer" />
<Toaster @rendermode="InteractiveServer" />

Backlog

Sitecore Blok primitives not yet ported but on the roadmap. Pick one for /blok migrate next.

FilterInputOtp

Won't Do

Sitecore Blok primitives deliberately not ported. Each row records the rationale — React-only dependency, native Blazor alternative, or coverage by another primitive.

Component Reason
Chart
Recharts-backed; React-only. Established Blazor alternatives exist (ApexCharts.Blazor, ChartJs.Blazor, Radzen) — use those instead of porting.
Command
Command palette wrapping the React-only cmdk library. The Input + filtered list pattern can already be composed from SearchInput + Popover when needed.
DnD
Built on @dnd-kit — React-specific hooks and context. Blazor DnD follows the native HTML5 drag-event model with a different idiom; reimplementing would be a large JS-interop project without a parity goal.
Drawer
Functionality already covered by Sheet, which supports side- and bottom-sliding panels. Adding Drawer as a separate primitive would duplicate behaviour.
Form
Wraps react-hook-form. Superseded by native Blazor EditForm + DataAnnotationsValidator + Input* primitives — paradigm mismatch means a port would fight both frameworks.

Known Feature Gaps

Dropdown / ContextMenu No keyboard navigation (arrow keys, Enter, Escape). The Blok source includes full keyboard support via Radix primitives.
Select No keyboard navigation or type-ahead search. The Blok source supports these via Radix Select primitives.
Combobox Keyboard nav covers Arrow Up/Down, Enter, Escape, and Backspace-to-clear. Blok's @base-ui/react/combobox also supports Home/End jumps, typeahead buffering, and tap-to-open on pointer-coarse devices — not yet ported.
Dialog / Sheet / AlertDialog No Escape key to close. No focus trapping within the modal. The Blok source provides both via Radix Dialog primitives.
Dialog / Sheet / AlertDialog sub-components Trigger, Portal, Overlay, and (for Dialog/Sheet) Content sub-components are collapsed into the root component with built-in overlay and close button. Blok exports them as separate siblings so consumers can swap portals or layer overlays manually.
DropdownMenu items No DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, or DropdownMenuPortal. Consumers roll their own toggle state on top of DropdownMenuItem.
NavigationMenu No NavigationMenuViewport (shared popup) or NavigationMenuIndicator (arrow/caret). Trigger/Content are named RenderFragment slots inside NavigationMenuItem rather than sibling sub-components.
InputGroup No InputGroupButton or InputGroupTextarea sub-components. Nest a plain <Button> inside <InputGroupAddon> for the button case.
Tooltip CSS hover-based with no configurable show/hide delay. The Blok source supports delay control via Radix Tooltip.
Carousel No touch/swipe support, autoplay, or plugin API. The Blok source wraps Embla Carousel; we roll our own with CurrentIndex/TransitionDuration only.
Slider Uses a styled native range input. No multi-thumb (range) support or vertical orientation. The Blok source uses Radix Slider with array value/defaultValue.
Popover positioning Popovers always appear below the trigger. The Blok source supports configurable side (top, bottom, left, right) and align via Radix Popover.
Popover composition Imperative PopoverService API instead of Blok's declarative <Popover><PopoverTrigger/><PopoverContent/></Popover> composition. Idiomatic for Blazor but a migration hurdle for Blok users.
CircularProgress No indeterminate mode, no size presets (xs/sm/md/lg/xl), no thickness or min props. Blok's Chakra-based version exposes all of these.
Toggle No square or rounded shape variants, no xs size, and no pressed-state icon swap (Blok replaces the child icon with a check mark when pressed).
Calendar / DatePicker Hand-rolled calendar implementation — no react-day-picker compat surface. Props like captionLayout, formatters, buttonVariant, and the components override don't exist.
ActionBar API shape Composition-first (ChildContent slot) instead of Blok's declarative buttons[] / menuItems[] prop arrays with hardcoded publish/duplicate/archive/delete callbacks.

Additions Beyond Blok

Components and features in this library that are not present in the Sitecore Blok design system.

CodeViewer Syntax-highlighted code block component with Prism.js support for 6+ languages. Not present in Blok.
CopyableToken post-click feedback After the token is copied the tooltip swaps to a configurable confirmation (CopiedMessage, default "Copied") for 1s before auto-dismissing. Adds CopyMessage for the pre-click label and a Clicked EventCallback<string> for reacting to the copy. Blok renders a static Copy to clipboard tooltip with no post-click state or callback.
Card.HoverElevation Opt-in hover shadow effect via a separate HoverElevation parameter. Blok bakes hover effects into the elevation variants; ours separates them for more control.
ErrorState Variants Pre-built HTTP status code variants (400, 401, 403, 404, 500, 503) with default titles, descriptions, and colour illustrations. Blok provides the same but our enum-driven approach is more ergonomic for Blazor.
Toaster.Content Toast messages accept a RenderFragment body for custom action content (buttons, links). Blok's Sonner wrapper has a simpler action label API.
IllustrationSvg Inline SVG illustration constants in Color and Neutral variants. Blok serves these from a CDN; ours are bundled for offline use.
Tabs.OnTabChanged Dedicated event callback that fires only when the active tab changes (separate from the two-way binding ValueChanged). Not present in Blok's Radix-based Tabs.
Carousel.TransitionDuration User-configurable slide transition speed in milliseconds. Blok's Embla-based carousel does not expose this directly.
Stack A layout utility component for quickly composing flex or grid layouts with configurable gap, padding, max-width, orientation, and border. Supports both row and column flex modes. Not present in Blok.
Calendar.NumberOfMonths Multi-month calendar display with per-panel month/year dropdowns and automatic range-end scrolling. Blok supports this via react-day-picker; our implementation is pure Blazor.
DatePicker Range Mode DatePicker supports both single date and range selection modes with RangeStart/RangeEnd binding and multi-month popup. Blok has this as a separate component; ours unifies both modes.
Dialog Viewport Widths Dialog sizes use viewport-relative widths (25%/50%/75%/95%) with minimum pixel floors. Blok uses fixed max-width classes.
Text A simple text paragraph component with pre-applied muted, centered, small styling. Useful for descriptions and helper text. Not present in Blok.
ThemeToggle A one-click light/dark mode switcher. Writes the selected mode to localStorage and applies the dark class to any data-dark-mode-target element. Re-applies the stored preference after Blazor enhanced navigations so the theme survives client-side route changes. Not present in Blok.
TreeView A generic TreeView<TItem> for hierarchical data with single/multi selection, cascading checkboxes with indeterminate parents, debounced search with match highlighting and ancestor auto-expansion, lazy loading on expand, label/actions templates, and expand-all/collapse-all APIs. Takes inspiration from BlazorBlueprint's TreeView but styled with BlazorUI tokens. Not present in Blok.
Icon wrapper + IconSvg + extras Blazor-side <Icon Svg="@IconSvg.X" /> wrapper around Material Design Icon paths. Blok consumers import individual paths from @mdi/js and render with @mdi/react directly. Our IconSvg static class bundles 300+ common paths; the companion PINGWorks.SitecoreBlok.BlazorUI.Icons package ships 7,500+. Additional Blazor-specific parameters: Scale (glyph scale without changing the container box), AiGradient (purple-to-red gradient fill), ViewBox, and ResetClassName (opt out of layout defaults for direct SVG embedding).
Button shortcuts Title (string label), StartIconSvg/EndIconSvg (pass an IconSvg path and the icon + spacing render automatically), Click, and an explicit Disabled parameter. All additive — Blok-style ChildContent composition still works.
Checkbox ergonomic helpers Label, Description, and Enhanced (wraps the control in a bordered card) parameters for the common checkbox-with-text pattern. Plus Indeterminate and DefaultChecked. Blok's primitive is bare — compose your own label sibling for bare usage.
RadioGroupItem.Label Inline Label string parameter rolls the button + label layout into a single component. Blok's Item returns just the circular button and expects an adjacent <label> — our helper keeps the call site tidy.
CircularProgress.ShowLabel Opt-in percentage label rendered in the centre of the ring. Blok's Chakra-based version has no equivalent out of the box — consumers overlay text themselves.
ActionBar composition Single ChildContent slot instead of Blok's buttons[]/menuItems[] prop arrays. Fewer API surfaces, more flexible — any <Button>, <Tooltip>, or <DropdownMenu> composition works inline.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.