Foundations

Component base classes and shared infrastructure.

Every Sillium component inherits from SilliumComponentBase, which provides universal parameters for color, size, variant, elevation, and HTML attribute merging. Form inputs extend SilliumInputBase for value binding, labels, icons, and validation.

Overview

Every Sillium component inherits from SilliumComponentBase. This abstract base class provides a consistent set of parameters — Color, Variant, Size, Elevation, Disabled — along with infrastructure for HTML attribute merging, CSS class composition, and automatic registration with the DesignDevTool.

For form inputs, SilliumInputBase<TValue> extends SilliumComponentBase with value binding, labels, placeholder text, validation messages, icons, and update behavior. All text inputs, selects, date pickers, and other input components share this common contract.

SilliumComponentBase parameters

These parameters are available on every Sillium component. They control appearance, state, and HTML attribute pass-through.

Parameter Type Default Purpose
Color Color Primary Theme color — 11 values (Primary, Secondary, Success, Warning, Error, Info, Light, Dark, Neutral, Accent, Surface)
Variant Variant Filled Visual style — Filled, Outlined, or Text
Size Size Medium Component size — Small, Medium, Large, ExtraLarge
Elevation int? null Shadow depth (0–10), null means no shadow override
Disabled bool false Disables user interaction
Id string? null HTML id on the root element
Class string? null Additional CSS classes appended to root element
Style string? null Inline styles applied to root element
AdditionalAttributes IReadOnlyDictionary null Unmatched HTML attributes (data-*, aria-*, etc.) splatted onto root element

RootAttributes merge mechanism

The RootAttributes property builds a merged dictionary of all HTML attributes that should be applied to a component's root DOM element. Components apply this via @attributes="RootAttributes".

AdditionalAttributes applied first

All unmatched attributes (data-testid, aria-label, role, etc.) are copied into the dictionary first. These have the lowest priority.

Id / Class / Style override

The explicit Id, Class, and Style parameters overwrite any same-named keys from AdditionalAttributes. These have the highest priority.

Auto data attributes

data-sillium-component (component type name) and data-sillium-id (unique instance id) are always added automatically for DevTool targeting.

Usage in components

Components apply all merged attributes via @attributes="RootAttributes" on their root DOM element.

Using RootAttributes in a component

The root element receives all merged attributes via the @attributes directive. Consumer-provided HTML attributes flow through automatically.

Show code
// Inside a component's .razor file:
<div @attributes="RootAttributes"
     class="@GetMergedClass("my-component-base-css")">
    @ChildContent
</div>

// The RootAttributes property merges everything:
// 1. AdditionalAttributes applied first (lowest priority)
// 2. Id, Class, Style override (highest priority)
// 3. data-sillium-component and data-sillium-id auto-added

// Consumer usage — all extra attributes flow through:
<Button Color="Color.Success"
        Class="mt-4"
        Style="min-width: 200px;"
        data-testid="save-btn"
        aria-label="Save changes"
        Text="Save" />

GetMergedClass helper

GetMergedClass(string baseClasses) concatenates a component's own CSS classes with the user's Class parameter. If Class is null, only the base classes are returned. This keeps component styling composable without losing consumer customization.

CSS class composition

Components call GetMergedClass to combine their internal styling with the consumer's Class parameter.

Show code
// GetMergedClass concatenates component CSS with user's Class parameter.
// Signature: protected string GetMergedClass(string baseClasses)

// Inside a component:
<div class="@GetMergedClass("btn btn--primary btn--md")">
    @ChildContent
</div>

// If user passes Class="mt-4 shadow-lg", the result is:
// class="btn btn--primary btn--md mt-4 shadow-lg"

// If Class is null, only baseClasses are returned:
// class="btn btn--primary btn--md"

SilliumInputBase<TValue> parameters

SilliumInputBase extends SilliumComponentBase for form input components. It adds value binding, labels, validation, icons, and update behavior. All input components (TextInput, NumberInput, SelectInput, DateInput, etc.) inherit these parameters.

Parameter Type Default Purpose
Value TValue? The bound value of the input
ValueChanged EventCallback<TValue?> Callback for two-way binding (@bind-Value)
Label string? null Label text displayed above the input
Placeholder string? null Placeholder text shown when empty
HelperText string? null Help text displayed below the input
ErrorText string? null Error message displayed on validation failure
Required bool false Shows required indicator on the label
ReadOnly bool false Makes the input read-only (visible but not editable)
FullWidth bool true Stretches input to fill container width
Clearable bool true Shows a clear button when the input has a value
UpdateMode InputUpdateMode Instant Controls when ValueChanged fires (Instant, Debounced, OnBlur)
UpdateDelay int 400 Debounce delay in milliseconds when UpdateMode is Debounced
StartIcon string? null Material Symbol icon name displayed before the input
EndIcon string? null Material Symbol icon name displayed after the input

DesignDevTool integration

Every SilliumComponentBase instance automatically registers with the DesignDevToolRegistry on initialization and unregisters on disposal. This enables the DevTool panel to discover, inspect, and live-edit any component on the page.

OnInitialized — Register

During OnInitialized, the component resolves DesignDevToolRegistry from DI and calls Register with its unique instance ID.

Dispose — Unregister

When the component is disposed, it calls Unregister to remove itself from the registry.

WeakReference strategy

The registry stores WeakReference<SilliumComponentBase> entries. If a component is garbage-collected without explicit disposal, stale entries are cleaned up on next access.

SetDevOverride / ClearDevOverrides

The DevTool panel calls SetDevOverride to live-tweak parameters (Color, Size, etc.) and ClearDevOverrides to reset. Changes apply immediately via reflection and trigger StateHasChanged.

Registration lifecycle

The base class handles registration and disposal automatically — component authors do not need to write any DevTool code.

Show code
// Auto-registration happens in SilliumComponentBase:
protected override void OnInitialized()
{
    base.OnInitialized();
    _registry = ServiceProvider.GetService<DesignDevToolRegistry>();
    _registry?.Register(_instanceId, this);
}

public virtual void Dispose()
{
    _registry?.Unregister(_instanceId);
}

// DesignDevToolRegistry uses WeakReference<SilliumComponentBase>
// to avoid preventing garbage collection of disposed components.

// Live parameter overrides from the DevTool panel:
internal void SetDevOverride(string paramName, object? value)
{
    _devOverrides[paramName] = value;
    ApplyDevOverrides();
    InvokeAsync(StateHasChanged);
}

internal void ClearDevOverrides()
{
    _devOverrides.Clear();
    InvokeAsync(StateHasChanged);
}

Source file reference

File Description
SilliumComponentBase.cs Base class for all components — Color, Variant, Size, Elevation, Disabled, RootAttributes, GetMergedClass
SilliumInputBase.cs Base class for form inputs — Value, Label, Placeholder, HelperText, icons, update behavior
Services/DesignDevTool/DesignDevToolRegistry.cs Component registry with WeakReference storage for DevTool discovery
Services/DesignDevTool/ParameterEditorInfo.cs Parameter introspection — builds editable parameter list for DevTool panel
An unhandled error has occurred. Reload Dismiss