Flare.UI
1.7.5
dotnet add package Flare.UI --version 1.7.5
NuGet\Install-Package Flare.UI -Version 1.7.5
<PackageReference Include="Flare.UI" Version="1.7.5" />
<PackageVersion Include="Flare.UI" Version="1.7.5" />
<PackageReference Include="Flare.UI" />
paket add Flare.UI --version 1.7.5
#r "nuget: Flare.UI, 1.7.5"
#:package Flare.UI@1.7.5
#addin nuget:?package=Flare.UI&version=1.7.5
#tool nuget:?package=Flare.UI&version=1.7.5
Flare.UI
Batteries-included Blazor component library for toasts, modals, confirm dialogs, loading bars, loading toasts, typeahead, tag box, clipboard, relative time, relative day, timezone detection, and reusable button primitives — with built-in localization for 25 languages. Zero dependencies.
Install
dotnet add package Flare.UI
Setup
Register the service:
builder.Services.AddFlare();
Wrap your page (or layout) with <FlareProvider>:
@inject IFlareService Flare
<FlareProvider>
@* your content *@
</FlareProvider>
Toast
await Flare.ToastAsync("Item saved.", ToastLevel.Success);
// With options
await Flare.ToastAsync("Check your input.", new ToastOptions
{
Level = ToastLevel.Warning,
DurationMs = 10_000,
Persistent = true,
});
// Rich content
await Flare.ToastAsync("", new ToastOptions
{
Level = ToastLevel.Success,
Content = @<div><strong>Done</strong><div>3 items processed</div></div>,
});
// Dismiss programmatically
var handle = await Flare.ToastAsync("Working...", new ToastOptions { Persistent = true });
handle.Dismiss();
Confirm
var confirmed = await Flare.ConfirmAsync("Delete Item", "This cannot be undone.");
// Custom labels
var confirmed = await Flare.ConfirmAsync("Publish", "Make this visible?", new ConfirmOptions
{
ConfirmText = "Publish",
CancelText = "Keep as Draft",
});
// Destructive confirm — red button, Enter defaults to Cancel (safe UX)
var confirmed = await Flare.ConfirmAsync("Delete Item", "This cannot be undone.", new ConfirmOptions
{
Intent = ConfirmIntent.Danger,
ConfirmText = "Delete",
});
DefaultButton controls which button receives initial focus. Enter and Space both activate the focused button:
ConfirmIntent.Primary→ Confirm is focused → Enter confirmsConfirmIntent.Danger→ Cancel is focused → Enter cancels (prevents accidental destructive actions)
Tab switches focus between buttons. Override the default per-call if needed:
new ConfirmOptions { Intent = ConfirmIntent.Danger, DefaultButton = DefaultButton.Confirm }
Modal
Any Blazor component can be rendered as a modal. Use the cascading ModalContext to return data:
@* EditProfile.razor *@
<div>
<input @bind="Name" />
<button @onclick="() => Modal.Ok(Name)">Save</button>
<button @onclick="Modal.Cancel">Cancel</button>
</div>
@code {
[CascadingParameter] public ModalContext Modal { get; set; } = default!;
[Parameter] public string CurrentName { get; set; } = "";
private string Name = "";
protected override void OnInitialized() => Name = CurrentName;
}
var result = await Flare.ModalAsync<EditProfile>(new ModalOptions
{
Title = "Edit Profile",
CssClass = "my-wide-modal",
Parameters = new() { ["CurrentName"] = "Jane" },
});
if (result.Confirmed)
{
var name = result.GetData<string>();
}
Control modal sizing via CSS custom properties on CssClass:
.my-wide-modal {
--flare-modal-min-width: 32rem;
--flare-modal-width: 40rem;
--flare-modal-max-width: 90vw;
}
Typeahead
A single-value autocomplete control that searches items as the user types.
@* Client-side filtering *@
<FlareTypeahead TItem="string"
Items="_roles"
TextSelector="r => r"
@bind-Value="SelectedRole"
Placeholder="Search roles…"
MinLength="0" />
@* Async search *@
<FlareTypeahead TItem="User"
SearchFunc="SearchUsers"
TextSelector="u => u.Name"
@bind-Value="SelectedUser"
Placeholder="Search users…" />
@* Free-text creation *@
<FlareTypeahead TItem="string"
Items="_tags"
TextSelector="t => t"
CreateItem="t => t"
@bind-Value="Tag"
Placeholder="Type or pick a tag…" />
| Parameter | Default | Description |
|---|---|---|
Items |
null |
Static collection to filter client-side (IEnumerable<TItem>) |
SearchFunc |
null |
Async search (string query, CancellationToken ct) → IEnumerable<TItem> |
TextSelector |
(required) | Extracts display text from an item |
Value / ValueChanged |
Two-way binding for the selected item | |
ValueExpression |
null |
Expression for EditForm integration (validation + field notifications) |
ItemTemplate |
null |
Custom render template for dropdown items |
CreateItem |
null |
Factory to create a new item from free text |
Placeholder |
null |
Input placeholder |
Class |
null |
CSS class(es) on the root container |
DebounceMs |
300 |
Debounce delay before searching |
MinLength |
1 |
Minimum characters to trigger search |
LoadingText |
"Searching…" |
Text shown while loading |
NotFoundText |
"No results found" |
Text shown when empty |
Disabled |
false |
Disables the control |
Headless |
false |
Strips all built-in CSS |
Keyboard: Arrow keys navigate, Enter selects, Escape/Tab closes.
Tag Box
A multi-select tagging control with typeahead search. Selected items appear as removable tags.
@* Client-side with free-text creation *@
<FlareTagBox TItem="string"
Items="_knownSkills"
TextSelector="s => s"
CreateItem="s => s"
@bind-Values="Skills"
Placeholder="Add skills…"
MaxTags="5" />
@* Async search with custom templates *@
<FlareTagBox TItem="User"
SearchFunc="SearchUsers"
TextSelector="u => u.Name"
@bind-Values="TeamMembers"
Placeholder="Add members…">
<ItemTemplate>@context.Name — @context.Role</ItemTemplate>
<TagTemplate>@context.Name</TagTemplate>
</FlareTagBox>
| Parameter | Default | Description |
|---|---|---|
Items |
null |
Static collection to filter client-side (IEnumerable<TItem>) |
SearchFunc |
null |
Async search (string query, CancellationToken ct) → IEnumerable<TItem> |
TextSelector |
(required) | Extracts display text from an item |
Values / ValuesChanged |
Two-way binding for selected items | |
ValuesExpression |
null |
Expression for EditForm integration (validation + field notifications) |
Comparer |
Default |
Equality comparer for duplicate prevention |
ItemTemplate |
null |
Custom render template for dropdown items |
TagTemplate |
null |
Custom render template for tags |
CreateItem |
null |
Factory to create a new item from free text |
Placeholder |
null |
Input placeholder (hidden when tags exist) |
Class |
null |
CSS class(es) on the root container |
DebounceMs |
300 |
Debounce delay before searching |
MinLength |
1 |
Minimum characters to trigger search |
MaxTags |
0 |
Max selectable items (0 = unlimited) |
LoadingText |
"Searching…" |
Text shown while loading |
NotFoundText |
"No results found" |
Text shown when empty |
Disabled |
false |
Disables the control |
Headless |
false |
Strips all built-in CSS |
Keyboard: Arrow keys navigate, Enter/Comma selects, Backspace removes last tag, Escape closes.
Check List
A searchable, scrollable multi-select list with virtualized rendering. Uses Blazor's Virtualize component — only visible rows are rendered, so it handles 100k+ items with no DOM pressure. Three data modes: static Items, async SearchFunc, or server-paged ProviderFunc.
@* Client-side with fixed height *@
<FlareCheckList TItem="string"
Items="_services"
TextSelector="s => s"
@bind-Values="SelectedServices"
Placeholder="Filter services…"
MaxHeight="16rem"
ShowCount />
@* Async remote search (loads full result set) *@
<FlareCheckList TItem="UserGroup"
SearchFunc="SearchGroups"
TextSelector="g => g.Name"
@bind-Values="AssignedGroups"
Placeholder="Search groups…"
MaxHeight="20rem"
ShowCount>
<ItemTemplate>
<div>
<strong>@context.Name</strong>
<div style="font-size: 0.75rem; color: #6b7280;">@context.Description</div>
</div>
</ItemTemplate>
</FlareCheckList>
@* Server-side paging — only the visible page is fetched *@
<FlareCheckList TItem="string"
ProviderFunc="LoadServices"
TextSelector="s => s"
@bind-Values="SelectedServices"
Placeholder="Search services…"
MaxHeight="16rem"
ShowCount />
@code {
private async Task<CheckListResult<string>> LoadServices(
string filter, int skip, int take, CancellationToken ct)
{
var url = $"/api/services?filter={Uri.EscapeDataString(filter)}&skip={skip}&take={take}";
var page = await Http.GetFromJsonAsync<ServicePage>(url, ct);
return new CheckListResult<string>(page!.Items, page.TotalCount);
}
}
| Parameter | Default | Description |
|---|---|---|
Items |
null |
Static collection to filter client-side (IEnumerable<TItem>) |
SearchFunc |
null |
Async search (string query, CancellationToken ct) → IEnumerable<TItem> |
ProviderFunc |
null |
Server-paged provider (filter, skip, take, ct) → CheckListResult<TItem> |
TextSelector |
(required) | Extracts display text from an item |
Values / ValuesChanged |
Two-way binding for selected items | |
ValuesExpression |
null |
Expression for EditForm integration |
Comparer |
Default |
Equality comparer for selection state |
KeySelector |
null |
Extracts a unique key for stable virtual scroll tracking (falls back to TextSelector) |
ItemTemplate |
null |
Custom render template for each row |
Placeholder |
null |
Search input placeholder |
MaxHeight |
null |
CSS max-height for scroll area (null = auto-expand) |
ItemSize |
40 |
Row height in px for virtual scroll |
DebounceMs |
300 |
Debounce delay before remote search |
ShowSearch |
true |
Show/hide the filter input |
ShowCount |
false |
Show "N selected" footer |
SelectedFirst |
false |
Sort checked items to top |
MaxItems |
0 |
Max selectable items (0 = unlimited) |
LoadingText |
"Loading…" |
Text shown while loading |
NotFoundText |
"No items found" |
Text shown when empty |
Disabled |
false |
Disables the control |
Headless |
false |
Strips all built-in CSS |
Keyboard: Escape clears filter. Click row to toggle.
EditForm Integration
FlareTypeahead, FlareTagBox, and FlareCheckList integrate with Blazor's EditForm. When used inside an EditForm, @bind-Value / @bind-Values automatically generates the expression parameter. The component picks up the cascading EditContext, notifies field changes on selection, and applies validation CSS classes (modified, valid, invalid).
<EditForm Model="_model" OnValidSubmit="Save">
<DataAnnotationsValidator />
<FlareTypeahead TItem="string"
Items="_roles"
TextSelector="r => r"
@bind-Value="_model.Role"
Placeholder="Pick a role…" />
<ValidationMessage For="() => _model.Role" />
<FlareTagBox TItem="string"
Items="_skills"
TextSelector="s => s"
@bind-Values="_model.Skills"
Placeholder="Add skills…" />
<ValidationMessage For="() => _model.Skills" />
</EditForm>
No InputBase<T> inheritance — the existing API stays intact.
Loading Bar
Declarative:
<FlareLoadingBar Active="_loading" Fixed />
<FlareLoadingBar Active="_loading" Progress="_percent" />
Imperative:
using var _ = Flare.StartLoadingBar(); // shows after 1500ms delay
await SomeWork(); // bar auto-hides on dispose
using var _ = Flare.StartLoadingBar(delayMs: 0); // shows immediately
Loading Toast
// Indeterminate
using var _ = Flare.StartLoadingToast("Processing...");
await SomeWork();
// With progress
var toast = Flare.StartLoadingToast("Uploading...", delayMs: 0);
for (var i = 0; i <= 100; i += 10)
{
toast.Update(progress: i);
await Task.Delay(100);
}
toast.Dispose();
Confirm Button
A two-stage confirmation button that prevents accidental destructive actions. Supports timed mode (arm → confirm) and modal mode (opens a Flare confirm dialog).
@* Timed mode — first click arms, second click confirms *@
<FlareConfirmButton class="btn btn-danger" ArmedClass="btn-warning"
OnConfirmed="HandleDelete">
<Standby>Delete record</Standby>
<Armed>Confirm delete</Armed>
</FlareConfirmButton>
@* Modal mode — opens a Flare confirm dialog *@
<FlareConfirmButton class="btn btn-danger" UseModal
ModalHeading="Purge Cache"
ModalMessage="This will invalidate all cached entries. Continue?"
OnConfirmed="HandlePurge">
<Standby>Purge cache</Standby>
</FlareConfirmButton>
By default the button permanently disables after confirmation. Set DisableOnConfirm="false" for repeatable actions:
<FlareConfirmButton class="btn btn-outline-warning" ArmedClass="btn-warning"
DisableOnConfirm="false" OnConfirmed="Rollback">
<Standby>Rollback</Standby>
<Armed>Confirm rollback</Armed>
</FlareConfirmButton>
| Parameter | Default | Description |
|---|---|---|
Standby |
(required) | Content in default state |
Armed |
"Confirm" |
Content in armed state |
OnConfirmed |
Fires on confirmed action | |
UseModal |
false |
Use confirm dialog instead of timed mode |
ModalHeading |
"Confirm" |
Dialog title (modal mode) |
ModalMessage |
null |
Dialog body (modal mode) |
ArmedClass |
null |
CSS class merged when armed |
ArmDelayMs |
2000 |
Disabled wait before arming |
ArmedWindowMs |
8000 |
Time window to confirm before reset |
DisableOnConfirm |
true |
Permanently disable after confirmation |
Debounced Button
Prevents double-click and rapid-fire submits by disabling the button for a cooldown period after each click.
<FlareDebouncedButton class="btn btn-primary" OnAction="Save">
Save changes
</FlareDebouncedButton>
<FlareDebouncedButton class="btn btn-success" Timeout="TimeSpan.FromSeconds(3)" OnAction="Submit">
Submit
</FlareDebouncedButton>
| Parameter | Default | Description |
|---|---|---|
ChildContent |
(required) | Button content |
OnAction |
(required) | Fires on click |
Timeout |
1s |
Cooldown period |
Clipboard Button
Copies a string to the system clipboard and shows success/error feedback via Flare toast.
<FlareClipboardButton class="btn btn-outline-secondary" Value="@SomeText" />
<FlareClipboardButton class="btn btn-sm btn-outline-primary" Value="@ApiKey">
Copy API key
</FlareClipboardButton>
| Parameter | Default | Description |
|---|---|---|
Value |
null |
Text to copy |
ChildContent |
"Copy to clipboard" |
Custom button content |
OnCopied |
Fires after copy attempt (bool success) |
Clipboard Inline
Renders inline content that copies its text to the clipboard on click. Shows a "Copy" tooltip on hover with a pointer cursor. No default styling — bring your own classes.
<FlareClipboard Class="text-monospace">@user.ID</FlareClipboard>
<FlareClipboard>@user.FirstName <b>@user.LastName</b></FlareClipboard>
When no Value is set, the component reads the rendered text content from the DOM — so mixed markup (like bold text) is copied as plain text automatically.
| Parameter | Default | Description |
|---|---|---|
ChildContent |
Content to display (also the copied text) | |
Value |
null |
Explicit text to copy (overrides text extraction) |
Class |
null |
CSS class(es) on the wrapping <span> |
Tooltip colors are customizable via CSS variables:
--flare-clipboard-tooltip-bg: #333;
--flare-clipboard-tooltip-color: #fff;
Configuration
builder.Services.AddFlare(o =>
{
o.ToastPosition = ToastPosition.BottomRight;
o.MaxToasts = 3;
o.Headless = true; // strip all default styles
o.Locale = "de-de"; // BCP 47 tag (default: "en-us")
o.Debug = builder.Environment.IsDevelopment(); // verbose JS logging
// Toast defaults
o.Toast.DurationMs = 4000;
o.Toast.ShowProgress = false;
// Modal defaults
o.Modal.CloseOnBackdropClick = false;
// Confirm defaults
o.Confirm.Intent = ConfirmIntent.Primary;
o.Confirm.ConfirmText = "OK";
o.Confirm.CancelText = "Cancel";
});
WASM note: In a Blazor WebAssembly project, use
builder.HostEnvironment.IsDevelopment()instead.
Per-call options override global defaults. Unset properties fall back to the configured defaults.
Relative Time
Displays a UTC timestamp as a live-updating relative time string. Formatting runs entirely in the browser via JS — zero SignalR overhead. Shows the absolute timestamp as a tooltip.
<FlareRelativeTime Value="@item.CreatedUtc" />
Renders output like "just now", "5 minutes ago", "in 2 hours", "3 days ago".
Updates automatically — 1-second ticks while any element is in seconds range, 10-second ticks otherwise. Pauses when the tab is hidden.
Relative Day
Displays a UTC timestamp relative to the current day, focused on day granularity with an optional night indicator (23:00–05:59).
<FlareRelativeDay Value="@item.ScheduledUtc" />
Renders output like "earlier today", "tonight", "tomorrow night", "last night", "in 3 days".
Night phrasing is human-oriented rather than calendar-oriented: from daytime, the upcoming night is labeled "tonight", including times after midnight such as 01:00 or 03:00 on the next calendar day.
Expectation model
- Daytime is
06:00–22:59 - Nighttime is
23:00–05:59 - Daytime labels are calendar-based:
earlier today,today,tomorrow,yesterday - Night labels are night-period-based:
earlier tonight,tonight,last night,tomorrow night
| Now | Target | Expected |
|---|---|---|
| day | later same day, daytime | today |
| day | later same day, night | tonight |
| day | next calendar day, 00:00–05:59 |
tonight |
| day | next calendar day, daytime | tomorrow |
| day | next distinct night period | tomorrow night |
| day | previous night period | last night |
| night | earlier in same continuous night | earlier tonight |
| night | later in same continuous night | tonight |
| night | next daytime | today or tomorrow, depending on calendar day |
| night | previous distinct night period | last night |
Examples:
| Now | Target | Expected |
|---|---|---|
2026-06-15 14:00 |
2026-06-16 00:30 |
tonight |
2026-06-15 14:00 |
2026-06-16 03:00 |
tonight |
2026-06-15 14:00 |
2026-06-16 23:30 |
tomorrow night |
2026-06-15 14:00 |
2026-06-15 03:00 |
last night |
2026-06-16 03:00 |
2026-06-15 23:00 |
earlier tonight |
2026-06-16 03:00 |
2026-06-16 12:00 |
today |
Timezone
Detects the client's IANA timezone and converts UTC timestamps to client-local time. Useful when you need formatted dates rather than relative strings.
@inject IFlareTimezoneService Tz
@if (Tz.IsInitialized)
{
<span>@Tz.ToClientTime(item.CreatedUtc).ToString("yyyy-MM-dd HH:mm")</span>
<span>Timezone: @Tz.IanaTimezone</span>
}
The service initializes automatically when <FlareProvider> renders on the client.
Localization
Flare ships 25 locale files using BCP 47 tags. Set the locale at startup:
builder.Services.AddFlare(o => o.Locale = "ja-jp");
Included locales: en-us, en-gb, de-de, de-at, de-ch, fr-fr, es-es, it-it, pt-br, nl-nl, pl-pl, ja-jp, ko-kr, zh-cn, tr-tr, ru-ru, sv-se, nb-no, da-dk, fi-fi, cs-cz, uk-ua, ar-sa, hi-in, th-th.
Fallback resolution: exact tag → base language (e.g. de → de-de) → en-us.
Locale files are JSON in wwwroot/locales/. During server prerender, strings are read from embedded resources. On the client, the matching JSON file is fetched at runtime.
The relative-day locale contract includes dedicated keys for person-friendly night phrasing such as earlierTonight, tonight, tomorrowNight, and lastNight, with nightFormat used only for longer ranges like "in 3 days at night".
License
Built with Claude Code using Claude Opus 4.6 by Anthropic
| 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.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.7.5 | 60 | 4/9/2026 |
| 1.7.4 | 160 | 4/1/2026 |
| 1.7.3 | 97 | 4/1/2026 |
| 1.7.2 | 86 | 4/1/2026 |
| 1.7.1 | 87 | 4/1/2026 |
| 1.7.0 | 84 | 3/31/2026 |
| 1.6.1 | 87 | 3/31/2026 |
| 1.6.0 | 84 | 3/30/2026 |
| 1.5.0 | 82 | 3/30/2026 |
| 1.4.2 | 86 | 3/27/2026 |
| 1.4.1 | 95 | 3/26/2026 |
| 1.4.0 | 100 | 3/25/2026 |
| 1.3.0 | 86 | 3/24/2026 |
| 1.2.1 | 83 | 3/24/2026 |
| 1.2.0 | 100 | 3/24/2026 |
| 1.1.1 | 85 | 3/23/2026 |
| 1.1.0 | 79 | 3/23/2026 |
| 1.0.1 | 82 | 3/23/2026 |
| 1.0.0 | 83 | 3/20/2026 |
| 0.4.1 | 205 | 3/11/2026 |