Flare.UI 1.7.5

dotnet add package Flare.UI --version 1.7.5
                    
NuGet\Install-Package Flare.UI -Version 1.7.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Flare.UI" Version="1.7.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Flare.UI" Version="1.7.5" />
                    
Directory.Packages.props
<PackageReference Include="Flare.UI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Flare.UI --version 1.7.5
                    
#r "nuget: Flare.UI, 1.7.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Flare.UI@1.7.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Flare.UI&version=1.7.5
                    
Install as a Cake Addin
#tool nuget:?package=Flare.UI&version=1.7.5
                    
Install as a Cake Tool

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 confirms
  • ConfirmIntent.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 }

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. dede-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

MIT


Built with Claude Code using Claude Opus 4.6 by Anthropic

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed