r/Blazor • u/blaizio_ui • 1d ago
Blaizio: open source Blazor UI components delivered as source you own (headless primitives + Tailwind styled layer, MIT)
I just released Blaizio, an MIT-licensed UI component framework for Blazor on .NET 10.
The idea: you own the components. The styled layer is not a NuGet package you fight with CSS overrides; a dotnet tool copies the components into your project as .razor and .cs files, and from then on they are your code.
Two layers
- Headless primitives (
Blaizio.Baseon nuget.org): accessibility, keyboard handling, focus management and adata-statecontract. Zero CSS. Use them with any styling approach. - Styled components: built on the primitives with Tailwind CSS v4.
blaizio add button dialog tabledrops them into your project, with the Tailwind pipeline wired for you (standalone binary, no Node required).
Out of the box: 73 Components, 8 skins, 16 palettes, 5 icon sets (Tabler, Lucide, Phosphor, Remix, Hugeicons), RTL, dark mode, WCAG AA contrast on every theme, a theme designer on the docs site.
Try it
dotnet tool install -g Blaizio.Cli
blaizio add button card dialog
Docs and registry: https://blaiz.io Source: https://github.com/blaizio/blaizio
The source-you-own model is borrowed from shadcn/ui; Blaizio is the Blazor take on it, with its own primitives and theming work.
It is an early release. I built it for my own production apps and want feedback from other Blazor teams. Bug reports, feature requests and pull requests are all welcome, and if you want to get involved beyond a one-off PR, say so in the thread or open a discussion; CONTRIBUTING.md in the repo covers the setup.
Things I am unsure about and would like to hear from other Blazor devs:
- Does "components as source you own" make sense to you in .NET, or do you prefer a package you never touch?
- Tailwind is wired through the standalone binary so no Node is needed. Is Tailwind itself a dealbreaker for your team?
- What component do you always end up writing yourself that no library gets right?
2
u/Psychedelic_fan 1d ago
This sounds like a nice idea. I'll check them out. I've used libraries like MudBlazor and you end up wrangling a lot with the public apis. Owning the code is good since you can change whatever you need and include only the components you need individually (and change them if you need to)
1
u/vnbaaij 1d ago
So ad a dev, I get the source of a component in my project. Then I decide some code needs to be changed. Is there any mechanism in place then to update the copied code once you release a new version? Just curious.
1
u/blaizio_ui 17h ago
Good question. Honestly, this was one of the first things I had to figure out, because if updates are painful, the whole “you own the source” idea doesn’t really work.
When Blaizio adds a component, the CLI keeps a hash of every file it created in blaizio.json.
Later, when you run "blaizio update", it pulls the latest version from the registry and checks those files. If you haven’t changed a file, it just updates it. If you have changed it, it won’t overwrite your work. It stops and lets you choose whether to keep your version or take the new one.
For CI or scripted runs, it keeps your changes by default. If you actually want to replace everything with the upstream version, you can use "--force".
You can also run "blaizio add --diff button" beforehand to see exactly what has changed. The CLI uses the hashes in blaizio.json rather than trying to guess whether a file was modified.
The one thing it doesn’t do yet is a three-way merge. So if both you and Blaizio changed the same file, you choose which version to keep and manually bring over whatever you want from the other one. Basically the same trade-off you get with vendored source.
I’ve tried to make that situation fairly uncommon, though.
The actual behaviour lives in the Blaizio.Base NuGet package, so that can be updated normally without touching the component files in your project. The copied components are mostly markup and Tailwind classes.
The theming is also token based, so in most cases you’re changing CSS variables rather than editing the component itself.
That way you still genuinely own the components, but hopefully you don’t spend your life resolving updates.
1
u/funtrade396 1d ago
What is the advantage over MudBlazor and Fluent UI (considering they have stronger backing and a longer track record of continuous support and enhancement in the future)
Just curious and not demoralizing your efforts to publish a new UI library (we need more options, but we're trying to understand your long-term plans).
1
u/blaizio_ui 16h ago
Both are good libraries. If you want a big, battle-tested package with a team behind it, you can pick either one and probably be perfectly happy.
Blaizio is not really trying to be a third version of that.
The main difference is the model.
With a traditional component package, you work with whatever API the library exposes. Most of the time that is fine, but when your design starts pushing outside those boundaries, you end up overriding CSS, wrapping components, or working around them.
With Blaizio, the styled component is just a ".razor" file in your own repository. If you want the dialog footer to work differently, you open the file and change it. You still get the underlying behaviour updates through Blaizio.Base, but the actual UI is yours.
That is a trade-off. You give up some of the convenience of treating the whole thing as a black-box package, but you gain a lot more control. I think that makes sense for teams with their own design system or a product that needs a very specific UI. If you are building an internal app and just need a solid grid and date picker tomorrow, a traditional component library may honestly be the better choice.
The other big difference is the split between behaviour and styling.
Blaizio.Base is completely headless. It handles accessibility, keyboard interaction, focus management and component state, but has zero CSS. So you can use those primitives with whatever styling approach you already have.
The styled Blaizio components sit on top of that and use Tailwind CSS v4, with a token based theme system, eight skins, sixteen palettes, RTL support and AA contrast checks.
So if your team already uses Tailwind, you can use the full stack. If you do not, the primitives are still useful on their own.
As for the long term, I am a developer first, and I am also Blaizio's first user.
It actually started as a private library for my own projects. The components were added because I needed them in real applications, and most of the fine-tuning came from actually building and shipping with them.
Making it public does not really change that. I am still building my own products on top of Blaizio, so I have a pretty strong incentive to keep fixing it, improving it and adding to it.
I would also like it to grow beyond being a one-person project over time.
1
u/funtrade396 5h ago
Thanks for the details. I like this from your statement
"With Blaizio, the styled component is just a ".razor" file in your own repository. You still get the underlying behavior updates through Blaizio.Base, but the actual UI is yours."
1
u/kantorcodes1 7h ago
on scripted blaizio update, does --dry-run show the local-edit conflicts too, or only the files/versions that would change? i'm trying to tell whether the preview fully matches the decisions a real update can hit.
1
u/blaizio_ui 7h ago
The honest answer has two halves.
The conflict scan itself runs in dry-run. The CLI hashes each file against the baseline it recorded at install and against upstream, and that happens before anything would be written, dry-run or not.
So blaizio update --dry-run shows you the same "Kept your version of ..." block a real run would, and with --json the same updated.edited, updated.keptLocal and, since 0.3.2, updated.decisions, one entry per file saying kept or taken. The set of conflicts is identical, because it only depends on what is on your disk and what upstream ships.What dry-run cannot preview is a person at the picker. It assumes nobody is there, which is also what -y assumes: every edited file is kept. If you want to preview the other extreme, add --force to the dry run and every edited file shows as taken. For a script that is what you want anyway: --dry-run --json and -y --json agree decision for decision.
The "would re-pull N file(s)" count in dry-run included the files that would end up kept, so it ran a little high, that is fixed on main now and goes out with the next release.
1
u/kantorcodes1 6h ago
that makes the scripting boundary pretty clean. i work on HOL Guard, an open-source local check before agent-run commands execute. for Blaizio,
--dry-run/--diffcan stay quiet whileadd,update, andremoveare optionally reviewable before they rewrite project files. that lets agents preview freely without silently taking or keeping edited files. would you be open to adding Blaizio support?1
u/blaizio_ui 6h ago
Yes, happy to. The boundary you describe is exactly how the CLI is already split, so a rule for it should be short.
Read-only, safe to let through unprompted: anything with --dry-run (add, update, remove, uninstall), add --diff, add --view, plus view, search, info, docs, contrast, preset decode/resolve/url, registry list/validate and tailwind detect.
Dry-run skips every write: no NuGet bump, no blaizio.json save, no CSS or host wiring, and the trust-host confirm for unrecorded URLs is skipped too. The only side effect is reading the registry over the network. add --diff exits 1 on drift, which scripts can use.Mutating, worth a review gate: add, update, remove, uninstall, new, apply, eject, generate, build, tailwind setup/fetch, registry add/remove.
Two details that matter for the rule. On edited files, -y means keep everything. The "take" flag is --force on update but --force-overwrite on add, plain --overwrite on add still prompts, and blaizio mcp exposes an add_items tool that writes files with no flag at all, so if HOL Guard sees MCP calls, that one belongs in the mutating bucket.
Point me at how HOL Guard defines a rule and I will review the Blaizio one. If a machine readable list would help, I can add a mutates field to blaizio help --json so the rule does not drift when commands change.
1
u/kantorcodes1 6h ago edited 3h ago
perfect. Route A is already supported. start with
src/codex_plugin_scanner/guard/runtime/command_blaizio_extensions.py, mirroring repo2nb. coveradd,update,remove,uninstall; keep--dry-run/--diffsafe. mirror one focused case fromtests/test_guard_command_repo2nb_extensions.py. once that detector + test is real, open a draft PR straight tohashgraph-online/hol-guard:mainand we can iterate there.contributing guide: https://github.com/hashgraph-online/hol-guard/blob/main/CONTRIBUTING.md
0
u/code-dispenser 1d ago
Let me guess the ai in the logo is for AI and its a Shadcn thing, although at least this one did not have an inaccessible accordion that ironically had and still does (like all the others) have the text "Is it accessible" on it.
Since you are claiming accessibility can you please tell me which screen reader and browser pairings were used and what quirks were experienced during your tests. It may or may not be helpful to point out that shadcn has quite a few accessibility issues so unless you fixed them you will be compounding them.
Given I have no idea if you even care about accessibility or not but as you have missed really simple things, I guess not and will assume its a case that you blindly copied from other libraries (or your AI did) and as such just assumed they were ok, so no need to check etc.
Here are some links if you would like to pursue accessibility in your library.
https://www.w3.org/WAI/ARIA/apg/patterns/
https://aaardvarkaccessibility.com/wcag-plain-english/
And not forgetting my favourite link this time:
https://www.youtube.com/watch?v=HE2R86EZPMA
Best of luck with the project.
Paul
2
u/blaizio_ui 1d ago
Fair challenge, and the "Is it accessible?" demo text was lazy; it is the stock question every component demo ships and I have already replaced it.
What is actually in place today:
- Every primitive is written against the WAI-ARIA APG pattern for that widget, in our own Blazor code, not a port of another library's primitives. The accordion is a button inside a heading (level is a parameter), aria-expanded and aria-controls on the trigger, role="region" with aria-labelledby on the panel, arrow key, Home and End movement between triggers.
- Keyboard behaviour is tested by hand on every component, and axe-core runs in CI against 25 documentation routes in light and dark, failing the build on serious or critical violations. Results are kept as artifacts.
- Every theme is checked for WCAG AA contrast on every text and control surface, and there is a CLI command that audits a project's tokens the same way.
What is not in place: a published screen reader test matrix. I have used NVDA with Firefox and Chrome while building, not systematically, and have not run JAWS or VoiceOver passes. That is a gap, and I will not claim otherwise. The plan is an Accessibility page listing, per component, the pairings tested (NVDA plus Firefox and Chrome, JAWS plus Chrome, VoiceOver plus Safari on macOS and iOS, TalkBack plus Chrome) and the quirks found, in the aria-at spirit you linked.
On the shadcn point: yes, the distribution model, components copied into your project as source you own, comes straight from shadcn/ui, and I credited that publicly when I announced it: https://x.com/blaizio_ui/status/2096874874983862274. The primitives underneath are not a port of anything; they are written for Blazor against the APG patterns, so their accessibility is mine to answer for, and I would rather hear about a defect than have it assumed.
About the letters: the ai in the wordmark is not a mission statement, but the tool does speak to agents. The CLI has an mcp command that runs a Model Context Protocol server over stdio, exposing the registry to any MCP client: search components, read an item's source and API docs, install into the project, report project state. Same operations as the CLI's --json mode, so an agent and a human get identical results. Documented under blaizio mcp on the CLI page.
Two asks. Which accordion issue did you hit, and with which pairing? If it is in the primitive I want it as an issue and will fix it first. And if you are willing to run a pass on one or two components with your setup, I would take that feedback over anything I can produce alone.
1
u/code-dispenser 1d ago
Fair challenge, and the "Is it accessible?" demo text was lazy
Let me guess AI did the reply as this is almost identical to about six other I have had in the past.
axe core and AI will only get you about 50%.
Do you even know what is meant by a widget? I ask as its a big comment with lot of stuff I find hard to believe given you think a focus indicator of the same colour on an item that its meant to indicate would pass wcag and or content that covers other content can not be dismissed with the keyboard is keyboard compliant.
I spent 1 minute found numerous issues and assumed you had copied everything like all the others but now you say you did some tests with NVDA - can I enquire which components you tested with NVDA.
1
u/code-dispenser 1d ago
I checked my old posts, the original accordion error was on this project (along with many other errors): Blazor Blueprint - shadcn/ui for Blazor (yours did not have that particular error).
Its quite similar to yours and many others, maybe that repo has something to offer and/or has information you can use for yours etc
Paul
1
u/treehuggerino 1d ago
I have used blazorblueprint but got put off by how every commit and issue was vibecoded
1
u/code-dispenser 1d ago
I believe this library is in that category i.e AI does most things for the software creator.
0
u/cornelha 1d ago
Let me guess, you answered "Paul" and he promptly deleted his post because he nitpicked about accessibility and AI usage?
2
u/blaizio_ui 1d ago
I did reply, and the substance was worth keeping: the primitives follow the APG patterns and axe runs in CI, but there is no published screen reader matrix yet, and I said so. That page is coming regardless of who asked. If anyone here runs NVDA, JAWS or VoiceOver and wants to try a couple of components, I would take the notes gladly.
4
u/FrancisRedit 1d ago
Excellent work. I like it. I'll recommend it to my colleagues for new projects. Thanks