LilyDesignSystem.Blazor.Headless
0.1.1
dotnet add package LilyDesignSystem.Blazor.Headless --version 0.1.1
NuGet\Install-Package LilyDesignSystem.Blazor.Headless -Version 0.1.1
<PackageReference Include="LilyDesignSystem.Blazor.Headless" Version="0.1.1" />
<PackageVersion Include="LilyDesignSystem.Blazor.Headless" Version="0.1.1" />
<PackageReference Include="LilyDesignSystem.Blazor.Headless" />
paket add LilyDesignSystem.Blazor.Headless --version 0.1.1
#r "nuget: LilyDesignSystem.Blazor.Headless, 0.1.1"
#:package LilyDesignSystem.Blazor.Headless@0.1.1
#addin nuget:?package=LilyDesignSystem.Blazor.Headless&version=0.1.1
#tool nuget:?package=LilyDesignSystem.Blazor.Headless&version=0.1.1
Lily Design System™ - Blazor Headless
A comprehensive headless Blazor component library with accessible, unstyled Razor components for building design systems. Every component follows WCAG 2.2 AAA guidelines with full ARIA support, keyboard navigation, and internationalization readiness.
Headless means zero CSS, zero styles, zero opinions about appearance. You provide all styling. Components provide structure, semantics, accessibility, and behavior.
Features
- Headless Blazor Razor components
- .NET 10 with C#
- WCAG 2.2 AAA accessibility compliance
- Full keyboard navigation support
- ARIA attributes and roles
- Internationalization-ready (no hardcoded strings)
- Zero dependencies beyond Blazor
- Works with any CSS framework or custom styles
Quick Start
Install
Add a ProjectReference to the library:
<ProjectReference Include="../lily-design-system-blazor-headless/src/LilyBlazorHeadless/LilyBlazorHeadless.csproj" />
Basic Usage
@using LilyBlazorHeadless.Components
<Form Label="Contact" OnSubmit="HandleSubmit">
<Field Label="Name" Required="true" Error="@GetError("name")">
<TextInput Label="Name" Value="@name" ValueChanged="v => name = v" Required="true" />
</Field>
<Button Type="submit">Submit</Button>
</Form>
Commands
| Command | Description |
|---|---|
dotnet build |
Build the project |
dotnet test |
Run all tests |
Project Structure
lily-design-system-blazor-headless/
├── AGENTS.md
├── CLAUDE.md
├── README.md -> index.md
├── index.md
├── spec/index.md
├── AGENTS/
│ ├── accessibility.md
│ ├── components.md
│ ├── headless.md
│ ├── internationalization.md
│ ├── lily.md
│ └── theme.md
├── src/LilyBlazorHeadless/
│ ├── LilyBlazorHeadless.csproj
│ └── Components/
│ └── {ComponentPascalCase}.razor
└── tests/LilyBlazorHeadless.Tests/
├── LilyBlazorHeadless.Tests.csproj
└── Components/
└── {ComponentPascalCase}Tests.cs
Architecture
Component Patterns
Each component is a Razor component (.razor file) in Components/:
@namespace LilyBlazorHeadless.Components
<button class="@($"button {CssClass}")" @attributes="AdditionalAttributes">
@ChildContent
</button>
@code {
[Parameter] public string CssClass { get; set; } = "";
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? AdditionalAttributes { get; set; }
}
Blazor Patterns
| Pattern | Example |
|---|---|
| Two-way binding | @bind-Value, @bind-Checked, @bind-Open or manual Value/ValueChanged |
| Events | OnSubmit (Form), @onclick (Button) |
| Child content | RenderFragment / RenderFragment<T> for templating |
| Cascading values | CascadingValue / CascadingParameter for shared state |
| Attribute splatting | [Parameter(CaptureUnmatchedValues = true)] for rest props |
Root Element CSS Class
Every component's first HTML element sets a class combining the kebab-case name with consumer CssClass:
<button class="@($"button {CssClass}")">
<div class="@($"banner {CssClass}")">
<nav class="@($"breadcrumb-nav {CssClass}")">
Headless Principles
- Zero CSS in any component -- fully headless
- Semantic HTML structure
- ARIA attributes for accessibility
- Consumers provide all CSS via CssClass parameter
- Consumers provide all user-facing text via parameters (i18n-ready)
- No inline styles, colors, sizes, spacing, or visual treatment
Testing
Stack
- bUnit -- Blazor component testing library
- xUnit -- test framework
- dotnet test -- test runner
Test File Pattern
using Bunit;
using Xunit;
using LilyBlazorHeadless.Components;
public class ButtonTests : TestContext
{
[Fact]
public void Renders_With_Correct_Tag()
{
var cut = RenderComponent<Button>(parameters =>
parameters.AddChildContent("Click me"));
var button = cut.Find("button");
Assert.NotNull(button);
Assert.Contains("Click me", button.TextContent);
}
}
Related Projects
- Lily Design System - Parent project
- Blazor Web Examples - Blazor styled example app
- React Headless - React equivalent
- Svelte Headless - Svelte equivalent
- Vue Headless - Vue equivalent
- Angular Headless — Angular 20 equivalent
License
MIT or Apache-2.0 or GPL-2.0 or GPL-3.0, or contact us for more options.
Contact
Joel Parker Henderson (joel@joelparkerhenderson.com)
Lily™ and Lily Design System™ are trademarks.
| 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
- Microsoft.AspNetCore.Components.Web (>= 10.0.11)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on LilyDesignSystem.Blazor.Headless:
| Package | Downloads |
|---|---|
|
LilyDesignSystem.Blazor.LocalePicker
Lily Design System Blazor locale picker: an icon button opening an APG listbox that sets lang and dir on the document. Headless, SSR-safe, no CSS. |
|
|
LilyDesignSystem.Blazor.SharePicker
Lily Design System Blazor share picker: an icon button opening the native share sheet, or a disclosure of consumer-supplied links plus copy-to-clipboard. Headless, SSR-safe, no CSS. |
|
|
LilyDesignSystem.Blazor.TextSizePicker
Lily Design System Blazor text size picker: an icon button opening an APG listbox that sets data-text-size on the document. Headless, SSR-safe, no CSS. |
|
|
LilyDesignSystem.Blazor.ThemePicker
Lily Design System Blazor theme picker: an icon button opening an APG listbox that swaps a theme stylesheet and sets data-theme. Headless, SSR-safe, no CSS. |
|
|
LilyDesignSystem.Blazor.DateTimePicker
Lily Design System Blazor date and time picker: a typeable text field paired with an APG date-picker dialog. Headless, SSR-safe, no CSS. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.1 | 100 | 9/2/2026 |