Skip to content

Repository files navigation

Soenneker.Lepton.Suite

Small, composable Blazor component base classes for libraries that need clean defaults without buying into a UI framework.

Lepton gives component authors a consistent foundation for child content, element attributes, IDs, async disposal, and cancellation. It is not a component library. It is the base layer you build component libraries on.

Why Lepton

  • Pick exactly the component capabilities you need.
  • Keep class, style, and unmatched attributes consistent across components.
  • Get disposal and cancellation patterns without rewriting them in every base class.
  • Type against matching interfaces when you need capability-based APIs.

Install

dotnet add package Soenneker.Lepton.Suite

Pick A Base

Need Use
Plain Blazor base LeptonComponent
Child content LeptonContent
Element attributes LeptonElement
Child content + element attributes LeptonContentElement
Id + child content + element attributes LeptonIdentifiableContentElement
Async disposal LeptonDisposable
Disposable content LeptonDisposableContent
Disposable content element LeptonDisposableContentElement
Disposable identifiable content element LeptonDisposableIdentifiableContentElement
Disposal-bound cancellation LeptonCancellable
Cancellable content element LeptonCancellableContentElement
Cancellable identifiable content element LeptonCancellableIdentifiableContentElement

Every public base has a matching interface in Soenneker.Lepton.Suite.Abstract.

Product Spotlight

Consistent Element Attributes

Element bases expose Class, Style, and AdditionalAttributes, then build render-ready attributes for you.

public sealed class Card : LeptonContentElement
{
    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "section");
        builder.AddMultipleAttributes(1, BuildAttributes("data-slot", "card"));
        builder.AddContent(2, ChildContent);
        builder.CloseElement();
    }
}
<Card Class="card" style="padding: 1rem" data-state="open">
    Content
</Card>

class and style values are merged instead of clobbered.

Disposal Without Boilerplate

Disposable bases expose ThrowIfDisposed() and track disposal state.

public abstract class ModuleBackedComponent : LeptonDisposable
{
    private IAsyncDisposable? _module;

    public override async ValueTask DisposeAsync()
    {
        if (_module is not null)
            await _module.DisposeAsync();

        await base.DisposeAsync();
    }
}

Cancellation That Follows Component Lifetime

Cancellable bases cancel their token during DisposeAsync().

public abstract class LoadingComponent : LeptonCancellable
{
    protected Task Load()
    {
        ThrowIfDisposed();

        return Task.Delay(TimeSpan.FromSeconds(1), CancellationToken);
    }
}

Design

Cancellable types are an add-on over disposable shapes:

LeptonDisposableContentElement
  -> LeptonCancellableContentElement

LeptonDisposableIdentifiableContentElement
  -> LeptonCancellableIdentifiableContentElement

So if you choose a cancellable element, you still get the disposable element behavior underneath it.

Notes

  • AdditionalAttributes is the unmatched-attribute parameter for element bases.
  • Identifiable element bases add id when Id is set.
  • Cancellable bases expose a protected CancellationToken.
  • Base classes are abstract and intended for component-library authors.

Releases

Sponsor this project

Packages

Used by

Contributors

Languages