Default idle state, ready for input.
Foundations
Forms and validation architecture.
Form wraps EditForm + Card, FormField wraps inputs with label/helper/error, and SilliumInputBase provides the shared parameter surface for all 19 input components.
Overview
The Form component combines Blazor's EditForm with a Card shell, providing title, description, validation summary, and a footer slot in one composable unit. It accepts either a Model or an EditContext.
FormField wraps any input with a label, required indicator, helper text, and error text. Every input component inherits SilliumInputBase, which defines the shared parameter contract: value binding, labels, icons, validation, and update behavior.
Form / FormField hierarchy
The recommended pattern nests inputs inside FormField inside Form. Form owns the EditForm and Card chrome; FormField owns label, helper, and error display; the input component owns its own value binding and rendering.
Form > FormField > Input pattern
A registration form using the three-layer hierarchy.
Why three layers?
Form handles submission and card layout. FormField handles label/error chrome. Input handles value. Each layer has a single responsibility and can be used independently.
Show code
Copy code
<Form Model="@Model" Title="Registration" Description="Create your account.">
<ChildContent>
<FormField Label="Full name" Required="true">
<TextInput @bind-Value="Model.FullName"
Placeholder="Enter your full name"
HelperText="As it appears on your ID" />
</FormField>
<FormField Label="Email" Required="true">
<EmailInput @bind-Value="Model.Email"
Placeholder="you@example.com" />
</FormField>
</ChildContent>
<FooterContent>
<Button Type="submit" Text="Register" />
</FooterContent>
</Form>Input states
Every input supports five visual states. The focused state is applied by the browser when the user clicks or tabs into the field and cannot be forced programmatically in these demos.
Click or tab into this field to see the focus ring. Cannot be forced programmatically.
Please enter a valid email address.
Disabled inputs cannot be edited or focused.
Read-only inputs can be focused and copied, but not edited.
All input types
The library ships 19 input components, all inheriting SilliumInputBase. They are grouped into five categories.
| Category | Component | Purpose |
|---|---|---|
| Text | TextInput | Single-line plain text entry |
| TextArea | Multi-line text entry with optional auto-resize | |
| PasswordInput | Masked text entry with show/hide toggle | |
| EmailInput | Email entry with built-in format validation | |
| Selection | SelectInput | Single-value dropdown selection |
| MultiSelect | Multi-value selection with chip display | |
| Autocomplete | Searchable dropdown with async data loading | |
| RadioGroup | Exclusive choice from a small set of options | |
| Checkbox | Boolean toggle or tri-state selection | |
| ToggleSwitch | On/off toggle with immediate effect | |
| Numeric | NumberInput | Numeric entry with increment/decrement controls |
| Slider | Numeric value selection via drag handle | |
| Date / Time | DateInput | Date-only picker with calendar popup |
| DateTimeInput | Combined date and time picker | |
| TimeInput | Time-only picker | |
| DateRangePicker | Start/end date range selection | |
| TimeSpanPicker | Duration picker (hours, minutes, seconds) | |
| Special | FileUpload | File selection with drag-and-drop support |
| IconPicker | Material Symbols icon browser and selector |
Shared input features (SilliumInputBase)
Every input component inherits these parameters from SilliumInputBase. They provide a consistent API surface across all 19 input types. See the Component Base foundations page for the full SilliumComponentBase contract.
| Parameter | Type | Default | Description |
|---|---|---|---|
| Value | TValue? | — | The current value of the input, two-way bound via @bind-Value. |
| ValueChanged | EventCallback<TValue?> | — | Callback invoked when the value changes. Used by @bind-Value. |
| Label | string? | null | Text label rendered above the input field. |
| Placeholder | string? | null | Placeholder text shown when value is empty. |
| HelperText | string? | null | Assistive text shown below the input (hidden when error is active). |
| ErrorText | string? | null | Explicit error message. Takes priority over EditContext validation messages. |
| Required | bool | false | Shows a required indicator (*) next to the label. |
| ReadOnly | bool | false | Input is focusable and copyable but not editable. |
| FullWidth | bool | true | When true, the input stretches to fill its container width. |
| Clearable | bool | true | Shows a clear button when the input has a value. |
| UpdateMode | InputUpdateMode | Instant | Controls when ValueChanged fires (Instant, Standard, Enter, FocusLost, Debounced). |
| UpdateDelay | int | 400 | Debounce delay in milliseconds when UpdateMode is Debounced. Default: 400ms. |
| StartIcon | string? | null | Material Symbol icon name rendered at the start (left) of the input. |
| EndIcon | string? | null | Material Symbol icon name rendered at the end (right) of the input. |
Component Base
SilliumInputBase extends SilliumComponentBase, which adds Id, Class, Style, Disabled, Color, Variant, and Size. See the Component Base foundations page for details.
ValidationHelper
ValidationHelper is an internal utility shared by all input components. It encapsulates error display logic: resolving which error text to show, computing ARIA attributes, and determining which description ID to reference.
| Member | Purpose |
|---|---|
| AriaInvalid | Returns "true" when the input has an error, null otherwise. Bound to aria-invalid. |
| DescribedBy | Returns the error element ID when in error state, otherwise the helper text ID. Bound to aria-describedby. |
| ResolvedErrorText | Explicit ErrorText takes priority; falls back to the first EditContext validation message. |
| HasError | True when ResolvedErrorText is not empty. Used for conditional styling. |
Error resolution chain
How ValidationHelper decides which error to display.
Priority rule
An explicit ErrorText parameter always wins over EditContext validation messages. This lets you override framework validation with custom business-rule errors.
Show code
Copy code
// Error resolution chain inside ValidationHelper:
//
// 1. Explicit ErrorText parameter (highest priority)
// <TextInput ErrorText="Email is required" />
//
// 2. EditContext validation messages (automatic)
// Picked up from DataAnnotations or FluentValidation
// when the input has a ValueExpression bound to a model property.
//
// ResolvedErrorText =
// !string.IsNullOrWhiteSpace(ErrorText)
// ? ErrorText
// : ValidationErrorText; // from EditContext
//
// AriaInvalid = HasError ? "true" : null
// DescribedBy = HasError ? errorId : helperIdInputUpdateMode & debounce
InputUpdateMode controls when an input commits its value via ValueChanged. The Debounced mode uses DebounceHelper internally, which cancels and restarts a timer on every keystroke. The default delay is 400ms.
| Mode | Behavior |
|---|---|
| Instant | Fires ValueChanged on every keystroke (oninput). Default mode. |
| Standard | Fires ValueChanged on the browser's onchange event (typically on blur or Enter). |
| Enter | Fires ValueChanged only when the user presses Enter. |
| FocusLost | Fires ValueChanged when the input loses focus (onblur). |
| Debounced | Fires ValueChanged after a configurable delay (UpdateDelay, default 400ms) since the last keystroke. |
Update mode examples
Configure when the input commits its value.
DebounceHelper
DebounceHelper uses CancellationTokenSource + Task.Delay internally. Each Schedule() call cancels the previous timer. The helper is IDisposable and cleans up on component disposal.
Show code
Copy code
// Default: updates on every keystroke
<TextInput @bind-Value="Search"
UpdateMode="InputUpdateMode.Instant" />
// Debounced: waits 400ms (default) after last keystroke
<TextInput @bind-Value="Search"
UpdateMode="InputUpdateMode.Debounced" />
// Custom delay: 800ms debounce
<TextInput @bind-Value="Search"
UpdateMode="InputUpdateMode.Debounced"
UpdateDelay="800" />
// Only commit on Enter key
<TextInput @bind-Value="Search"
UpdateMode="InputUpdateMode.Enter" />
// Only commit on focus lost (blur)
<TextInput @bind-Value="Search"
UpdateMode="InputUpdateMode.FocusLost" />File reference
Key source files in the Sillium.Core.Blazor library related to forms and validation.
| File | Responsibility |
|---|---|
| Components/Forms/Form.razor | Wraps EditForm + Card with title, description, validation summary, and footer slot. |
| Components/Forms/FormField.razor | Wraps any input with label, required indicator, helper text, and error text. |
| SilliumInputBase.cs | Abstract base class defining shared parameters for all 19 input components. |
| Utilities/ValidationHelper.cs | Internal utility for error resolution, ARIA attributes, and describedby logic. |
| Utilities/DebounceHelper.cs | Cancellable debounce timer using CancellationTokenSource + Task.Delay. |