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.BlazorUI2. Register services in Program.cs
builder.Services.AddSitecoreBlokUI();3. Add using directives to _Imports.razor
@using PINGWorks.SitecoreBlok.BlazorUI
@using PINGWorks.SitecoreBlok.BlazorUI.Services4. 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" />Available Primitives
68 primitives available.
Available Chunks
86 chunks across 7 families.
Content
Forms
Data
Backlog
Sitecore Blok primitives not yet ported but on the roadmap. Pick one for /blok migrate next.
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
@base-ui/react/combobox also supports Home/End jumps, typeahead buffering, and tap-to-open on pointer-coarse devices — not yet ported.DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, or DropdownMenuPortal. Consumers roll their own toggle state on top of DropdownMenuItem.NavigationMenuViewport (shared popup) or NavigationMenuIndicator (arrow/caret). Trigger/Content are named RenderFragment slots inside NavigationMenuItem rather than sibling sub-components.InputGroupButton or InputGroupTextarea sub-components. Nest a plain <Button> inside <InputGroupAddon> for the button case.CurrentIndex/TransitionDuration only.value/defaultValue.side (top, bottom, left, right) and align via Radix Popover.PopoverService API instead of Blok's declarative <Popover><PopoverTrigger/><PopoverContent/></Popover> composition. Idiomatic for Blazor but a migration hurdle for Blok users.xs/sm/md/lg/xl), no thickness or min props. Blok's Chakra-based version exposes all of these.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).react-day-picker compat surface. Props like captionLayout, formatters, buttonVariant, and the components override don't exist.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.
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.HoverElevation parameter. Blok bakes hover effects into the elevation variants; ours separates them for more control.RenderFragment body for custom action content (buttons, links). Blok's Sonner wrapper has a simpler action label API.Color and Neutral variants. Blok serves these from a CDN; ours are bundled for offline use.ValueChanged). Not present in Blok's Radix-based Tabs.RangeStart/RangeEnd binding and multi-month popup. Blok has this as a separate component; ours unifies both modes.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<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 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).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.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.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.ChildContent slot instead of Blok's buttons[]/menuItems[] prop arrays. Fewer API surfaces, more flexible — any <Button>, <Tooltip>, or <DropdownMenu> composition works inline.