Novatech.RCL
1.2.0
See the version list below for details.
dotnet add package Novatech.RCL --version 1.2.0
NuGet\Install-Package Novatech.RCL -Version 1.2.0
<PackageReference Include="Novatech.RCL" Version="1.2.0" />
<PackageVersion Include="Novatech.RCL" Version="1.2.0" />
<PackageReference Include="Novatech.RCL" />
paket add Novatech.RCL --version 1.2.0
#r "nuget: Novatech.RCL, 1.2.0"
#:package Novatech.RCL@1.2.0
#addin nuget:?package=Novatech.RCL&version=1.2.0
#tool nuget:?package=Novatech.RCL&version=1.2.0
Novatech.RCL
Razor Class Library Blazor con componenti UI enterprise riutilizzabili. Supporta Blazor Server e Blazor WebAssembly.
- Design system coerente · CSS isolato per componente · accessibilità curata
- API imperativa per i dialog · composizione dichiarativa per tab, grid, breadcrumb
- Localizzazione runtime · multi-tenancy · storage applicativo su
localStorage
Requisiti
| Requisito | Note |
|---|---|
| .NET 10.0 | <TargetFramework>net10.0</TargetFramework> |
| Blazor Server o WebAssembly | Include <SupportedPlatform Include="browser" /> |
| FontAwesome 6 | Richiesto a runtime per le icone |
| Bootstrap 5 | Non richiesto: la libreria usa CSS proprio |
Includere FontAwesome nell'host:
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
Installazione
dotnet add package Novatech.RCL
Setup
1. Servizi (Program.cs)
using Novatech.RCL.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents(); // o WebAssembly
builder.Services.AddComponentLibrary(); // provider + toast + coordinator
builder.Services.AddTenantServices(); // opzionale
AddComponentLibrary() registra con TryAddScoped / TryAddSingleton:
| Servizio | Default |
|---|---|
IStringProvider |
StringProvider (italiano) |
IIconProvider |
IconProvider (FontAwesome) |
IToastService |
ToastService |
DropDownWidgetCoordinator |
— |
LibraryOptions |
— |
Ogni registrazione è sovrascrivibile dal consumer.
2. Layout (MainLayout.razor)
@inherits LayoutComponentBase
<main>@Body</main>
<ToastContainer Position="ToastEnum.Position.TopRight" Timeout="5" MaxStack="5" />
Montare una sola istanza di
ToastContainer.
Esempio
@page "/customers"
<ScreenShell>
<ScreenShellHeader>
<HeaderLeft><h2>Clienti</h2></HeaderLeft>
<HeaderRight>
<ActionButton Semantics="ActionButtonEnum.Semantics.SaveNew"
Icon="fas fa-plus"
OnClick="OpenCreateDialogAsync" />
</HeaderRight>
</ScreenShellHeader>
<ScreenShellContent>
<ScreenShellGrid OnSearch="SearchAsync" OnReset="ResetAsync">
<GridContent>
<Grid TItem="Customer" Items="_customers">
<GridHeader>
<GridHeaderItem HeaderText="Nome"
Field="@(r => ((Customer)r).Name)" />
</GridHeader>
<GridRow>
<GridRowItem Value="@context.Name" />
</GridRow>
</Grid>
</GridContent>
</ScreenShellGrid>
</ScreenShellContent>
</ScreenShell>
<FormDialog TModel="CustomerEditModel"
@ref="_formRef"
Title="Nuovo cliente"
OnSubmit="SaveAsync">
<FormFields>
<InputText @bind-Value="context.Model.Name"
class="form-control"
disabled="@context.State.ReadOnly" />
<ValidationMessage For="@(() => context.Model.Name)" />
</FormFields>
</FormDialog>
@code {
[Inject] private IToastService Toast { get; set; } = default!;
private FormDialog<CustomerEditModel>? _formRef;
private List<Customer> _customers = new();
private async Task OpenCreateDialogAsync(MouseEventArgs _)
{
var result = await _formRef!.ShowAsync(new CustomerEditModel());
if (result.Saved)
Toast.ShowSuccess("Cliente creato");
}
private Task<bool> SaveAsync(CustomerEditModel model) => Task.FromResult(true);
private Task SearchAsync() => Task.CompletedTask;
private Task ResetAsync() => Task.CompletedTask;
}
Componenti
| Categoria | Componenti |
|---|---|
| Azioni | ActionButton · RichButton |
| Dati | UsageCard |
| Layout | Collapsable |
| Dialog | Dialog · ConfirmDialog · InfoDialog · UploadDialog · LoaderDialog · FormDialog<TModel> · GridSelectionDialog<TItem> |
| Griglia | Grid<TItem> · GridDynamic · GridHeaderItem · GridRowItem · GridFooter · GridPagination |
| Feedback | Loader · Toast · ToastContainer |
| Navigazione | DropDownWidget · DropDownWidgetGroup · DropDownWidgetItem |
| Layout pagina | ScreenShell · ScreenShellHeader · ScreenShellContent · ScreenShellSection · ScreenShellToolbar · ScreenShellActions · ScreenShellTabs · ScreenShellTab · ScreenShellGrid · ScreenShellEmpty · ScreenShellError · ScreenShellBadge · ScreenShellBreadcrumb · ScreenShellBreadcrumbItem |
Dialog — API comune
Tutti i dialog espongono lo stesso contratto:
Task<Result?> ShowAsync(Args? args = null);
Task Hide();
bool IsOpen { get; }
Esempio:
var ok = await _confirmRef!.ShowAsync(new ConfirmDialogArgs
{
Title = "Elimina elemento",
Message = "L'operazione non è reversibile.",
ConfirmText = "ELIMINA",
ConfirmButtonClass = "btn-danger"
});
if (ok == true) { /* ... */ }
Toast
[Inject] private IToastService Toast { get; set; } = default!;
Toast.ShowSuccess("Elemento salvato");
Toast.ShowError("Impossibile contattare il server");
Design system
| Categoria | Valori chiave |
|---|---|
| Primary | #1a5cff · hover #0d47c7 · soft #eff6ff |
| Danger | #dc2626 · soft #fee2e2 |
| Success | #16a34a · soft #dcfce7 |
| Warning | #d97706 · soft #fef3c7 |
| Info | #0284c7 · soft #e0f2fe |
| Testo heading / body | #0b2b4c / #1e293b |
| Bordo tenue / medio / forte | #eef2f7 / #e2e8f0 / #cbd5e1 |
| Focus ring | outline: 2px solid #1a5cff; outline-offset: 2px |
| Raggio card / bottone | 16px / 10px |
Tutti i componenti rispettano @media (prefers-reduced-motion: reduce).
Localizzazione runtime
Sicura in Blazor Server multi-circuito: la cultura viene applicata al thread corrente solo per la durata della chiamata.
// 1) Implementazione
public sealed class LocalizationState : ICultureProvider
{
public string CurrentCulture { get; set; } = "it-IT";
}
// 2) Registrazione
builder.Services.AddSingleton<LocalizationState>();
builder.Services.AddSingleton<ICultureProvider>(sp =>
sp.GetRequiredService<LocalizationState>());
builder.Services.AddComponentLibrary();
builder.Services.AddLanguageAwareLocalization();
Cambio lingua a runtime:
@inject LocalizationState Localization
<select value="@Localization.CurrentCulture" @onchange="OnLanguageChanged">
<option value="it-IT">🇮🇹 Italiano</option>
<option value="en-US">🇬🇧 English</option>
</select>
Override dei provider
public sealed class MyEnglish : StringProvider
{
public override string ActionConfirm => "CONFIRM";
public override string ActionCancel => "CANCEL";
}
builder.Services.AddScoped<IStringProvider, MyEnglish>();
Analogamente per le icone: ereditare da IconProvider e registrare IIconProvider.
Multi-tenancy
builder.Services.AddTenantServices();
| Modalità | Risoluzione | Config |
|---|---|---|
| Subdomain | acme.example.com → acme |
"TenantResolution": "0" |
| QueryString | example.com?tenant=acme |
"TenantResolution": "1" |
| Auto (default) | localhost → query string; altrimenti subdomain |
(config assente) |
@inject ITenantNavigationService TenantNav
<ActionButton Text="VAI"
OnClick="@(() => TenantNav.NavigateTo("/dashboard"))" />
NavigateTo inietta automaticamente ?tenant=... quando la modalità è QueryString.
Storage applicativo
builder.Services.AddScoped<IAppStorageService, AppStorageService>();
Wrapper di localStorage con serializzazione JSON, chiavi con prefisso app- e gestione automatica di JSException (nessun crash se l'interop non è disponibile).
await _storage.SetUserAsync(user);
var user = await _storage.GetUserAsync();
var all = await _storage.GetLocalStorageAsync();
await _storage.ClearLocalStorageAsync();
Modelli inclusi: TokenLocalStorageModel, UserLocalStorageModel, ApplicationTenantOrganizationLocalStorageModel, TenantOrganizationFunctionLocalStorageModel, ConfigLocalStorageModel, LicenceLocalStorageModel, AppSettingLocalStorageModel, UserAuthorizationLocalStorageModel.
Accessibilità
- Focus visibile su ogni elemento interattivo (
:focus-visible). roleearia-*applicati:dialog,tablist,progressbar,alert,status,menu,checkbox.- Navigazione da tastiera: ESC su dialog e dropdown, frecce su tab, Enter/Space su collapsable.
- Contrasto WCAG AA garantito sui colori del design system.
prefers-reduced-motionrispettato su tutte le animazioni.
| 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.Authorization (>= 10.0.12)
- Microsoft.AspNetCore.Components.Web (>= 10.0.12)
- Microsoft.Extensions.Localization (>= 10.0.12)
- Microsoft.Extensions.Localization.Abstractions (>= 10.0.12)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.