Overlay
Documentație pentru componenta FodOverlay
1. Descriere Generală
FodOverlay
este componenta pentru afișarea unui strat suprapus peste conținutul paginii, utilizată pentru a crea efecte de fundal, loading states, modals sau pentru a bloca interacțiunea cu interfața. Componenta oferă control complet asupra vizibilității, culorii fundalului și blocării scroll-ului.
Caracteristici principale: - Fundal semi-transparent personalizabil - Blocare automată a scroll-ului - Suport pentru poziționare absolută sau fixă - Auto-închidere la click - Control z-index - Integrare cu sistemul de comenzi - Lifecycle management pentru scroll - Suport pentru conținut personalizat
2. Ghid de Utilizare API
Overlay simplu
<FodButton Variant="FodVariant.Filled"
Color="FodColor.Primary"
OnClick="@(() => showOverlay = true)">
Afișează Overlay
</FodButton>
<FodOverlay @bind-Visible="showOverlay"
DarkBackground="true"
AutoClose="true" />
@code {
private bool showOverlay = false;
}
Overlay cu conținut personalizat
<FodOverlay @bind-Visible="isLoading" DarkBackground="true">
<div class="d-flex flex-column align-items-center">
<FodProgressCircular Color="FodColor.Secondary"
Indeterminate="true"
Size="FodSize.Large" />
<FodText Typo="Typo.h6" Color="FodColor.White" Class="mt-4">
Se încarcă datele...
</FodText>
</div>
</FodOverlay>
@code {
private bool isLoading = false;
private async Task LoadData()
{
isLoading = true;
await DataService.LoadAsync();
isLoading = false;
}
}
Overlay absolut pentru containere
<FodCard Style="position: relative; height: 300px;">
<FodCardContent>
<FodText Typo="Typo.h5">Card cu loading overlay</FodText>
<FodText Typo="Typo.body2">
Acest card are un overlay absolut care acoperă doar cardul.
</FodText>
</FodCardContent>
@if (isCardLoading)
{
<FodOverlay Visible="true"
DarkBackground="true"
Absolute="true">
<FodProgressCircular Color="FodColor.Primary"
Indeterminate="true" />
</FodOverlay>
}
</FodCard>
Overlay cu fundal light
<FodOverlay @bind-Visible="showLightOverlay"
LightBackground="true"
AutoClose="true">
<FodPaper Elevation="8" Class="pa-4">
<FodText Typo="Typo.h6" GutterBottom="true">
Notificare
</FodText>
<FodText Typo="Typo.body2" GutterBottom="true">
Aceasta este o notificare importantă cu fundal light.
</FodText>
<FodButton Color="FodColor.Primary"
OnClick="@(() => showLightOverlay = false)">
Închide
</FodButton>
</FodPaper>
</FodOverlay>
Overlay cu z-index personalizat
<!-- Overlay de bază -->
<FodOverlay @bind-Visible="baseOverlay"
DarkBackground="true"
ZIndex="1000">
<FodText Color="FodColor.White">Overlay de bază (z-index: 1000)</FodText>
</FodOverlay>
<!-- Overlay deasupra -->
<FodOverlay @bind-Visible="topOverlay"
DarkBackground="true"
ZIndex="1100">
<FodText Color="FodColor.White">Overlay deasupra (z-index: 1100)</FodText>
</FodOverlay>
Loading state pentru întreaga pagină
@if (pageLoading)
{
<FodOverlay Visible="true" DarkBackground="true">
<div class="d-flex flex-column align-items-center">
<FodProgressCircular Color="FodColor.Secondary"
Indeterminate="true"
Size="FodSize.Large" />
<FodText Typo="Typo.h6" Color="FodColor.White" Class="mt-4">
Procesăm cererea dumneavoastră...
</FodText>
<FodText Typo="Typo.body2" Color="FodColor.White" Class="mt-2">
Vă rugăm așteptați
</FodText>
</div>
</FodOverlay>
}
@code {
private bool pageLoading = false;
private async Task ProcessRequest()
{
pageLoading = true;
StateHasChanged();
try
{
await ProcessService.ExecuteAsync();
}
finally
{
pageLoading = false;
StateHasChanged();
}
}
}
Overlay fără blocare scroll
<FodOverlay @bind-Visible="showOverlay"
DarkBackground="true"
LockScroll="false">
<FodAlert Severity="Severity.Warning" Class="ma-4">
<FodAlertTitle>Atenție</FodAlertTitle>
Puteți continua să navigați în timp ce acest mesaj este afișat.
</FodAlert>
</FodOverlay>
Overlay cu handler onClick
<FodOverlay Visible="showMenu"
AutoClose="false"
OnClick="HandleOverlayClick">
<FodList Class="bg-white" Style="width: 200px;">
<FodListItem Button="true" OnClick="@(() => SelectOption(1))">
<FodListItemText Primary="Opțiunea 1" />
</FodListItem>
<FodListItem Button="true" OnClick="@(() => SelectOption(2))">
<FodListItemText Primary="Opțiunea 2" />
</FodListItem>
<FodListItem Button="true" OnClick="@(() => SelectOption(3))">
<FodListItemText Primary="Opțiunea 3" />
</FodListItem>
</FodList>
</FodOverlay>
@code {
private bool showMenu = false;
private void HandleOverlayClick(MouseEventArgs e)
{
// Click pe overlay (nu pe conținut)
showMenu = false;
}
private void SelectOption(int option)
{
Console.WriteLine($"Selected option: {option}");
showMenu = false;
}
}
Loading overlay pentru formular
<FodForm @ref="form" Model="@model" Style="position: relative;">
<FodCardContent>
<FodGrid Container="true" Spacing="2">
<FodGrid Item="true" xs="12">
<FodTextField @bind-Value="model.Name"
Label="Nume"
Required="true" />
</FodGrid>
<FodGrid Item="true" xs="12">
<FodTextField @bind-Value="model.Email"
Label="Email"
Required="true" />
</FodGrid>
</FodGrid>
</FodCardContent>
<FodCardActions>
<FodButton Variant="FodVariant.Text">Anulează</FodButton>
<FodButton Variant="FodVariant.Filled"
Color="FodColor.Primary"
OnClick="Submit">
Salvează
</FodButton>
</FodCardActions>
@if (isSubmitting)
{
<FodOverlay Visible="true"
DarkBackground="true"
Absolute="true">
<FodProgressCircular Color="FodColor.Primary"
Indeterminate="true" />
</FodOverlay>
}
</FodForm>
@code {
private FodForm form;
private UserModel model = new();
private bool isSubmitting = false;
private async Task Submit()
{
if (await form.ValidateAsync())
{
isSubmitting = true;
await UserService.SaveAsync(model);
isSubmitting = false;
}
}
}
Overlay pentru imagini (lightbox simplu)
<FodGrid Container="true" Spacing="2">
@foreach (var image in images)
{
<FodGrid Item="true" xs="12" sm="6" md="4">
<FodImage Src="@image.Thumbnail"
Alt="@image.Title"
Style="cursor: pointer;"
OnClick="@(() => ShowFullImage(image))" />
</FodGrid>
}
</FodGrid>
<FodOverlay @bind-Visible="showFullImage"
DarkBackground="true"
AutoClose="true">
@if (selectedImage != null)
{
<div class="d-flex flex-column align-items-center">
<FodImage Src="@selectedImage.FullSize"
Alt="@selectedImage.Title"
Style="max-width: 90vw; max-height: 90vh;" />
<FodText Typo="Typo.h6" Color="FodColor.White" Class="mt-3">
@selectedImage.Title
</FodText>
</div>
}
</FodOverlay>
@code {
private List<ImageModel> images = new();
private bool showFullImage = false;
private ImageModel selectedImage;
private void ShowFullImage(ImageModel image)
{
selectedImage = image;
showFullImage = true;
}
}
3. Atribute disponibile
Proprietate | Tip | Descriere | Valoare Implicită |
---|---|---|---|
Visible |
bool |
Controlează vizibilitatea overlay-ului | false |
VisibleChanged |
EventCallback<bool> |
Callback pentru schimbarea vizibilității | - |
AutoClose |
bool |
Închide overlay la click | false |
LockScroll |
bool |
Blochează scroll-ul paginii | true |
LockScrollClass |
string |
Clasa CSS pentru blocare scroll | "scroll-locked" |
DarkBackground |
bool |
Aplică fundal întunecat | false |
LightBackground |
bool |
Aplică fundal deschis | false |
Absolute |
bool |
Poziționare absolută în container | false |
ZIndex |
int |
Valoarea z-index | 5 |
OnClick |
EventCallback<MouseEventArgs> |
Handler pentru click pe overlay | - |
Command |
ICommand |
Comandă executată la click | null |
CommandParameter |
object |
Parametru pentru comandă | null |
ChildContent |
RenderFragment |
Conținutul overlay-ului | null |
Class |
string |
Clase CSS adiționale | null |
Style |
string |
Stiluri inline | null |
4. Evenimente
Eveniment | Tip | Descriere |
---|---|---|
VisibleChanged |
EventCallback<bool> |
Se declanșează când se schimbă vizibilitatea |
OnClick |
EventCallback<MouseEventArgs> |
Se declanșează la click pe overlay |
5. Metode publice
Componenta nu expune metode publice, fiind controlată prin proprietăți.
6. Stilizare și personalizare
/* Overlay cu gradient */
.gradient-overlay .fod-overlay-scrim {
background: linear-gradient(45deg,
rgba(63, 81, 181, 0.8),
rgba(233, 30, 99, 0.8));
}
/* Overlay cu blur */
.blur-overlay {
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
/* Animație fade-in */
.animated-overlay {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Overlay cu pattern */
.pattern-overlay .fod-overlay-scrim {
background-image:
repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(0, 0, 0, 0.1) 10px,
rgba(0, 0, 0, 0.1) 20px
);
}
/* Content centrat cu animație */
.fod-overlay-content {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
7. Integrare cu alte componente
Cu Dialog
<FodOverlay @bind-Visible="showDialogOverlay"
DarkBackground="true"
ZIndex="1290">
<FodDialog Open="true" MaxWidth="MaxWidth.Small" FullWidth="true">
<FodDialogTitle>
Confirmare
</FodDialogTitle>
<FodDialogContent>
<FodText>Sunteți sigur că doriți să continuați?</FodText>
</FodDialogContent>
<FodDialogActions>
<FodButton OnClick="@(() => showDialogOverlay = false)">
Anulează
</FodButton>
<FodButton Color="FodColor.Primary" Variant="FodVariant.Filled">
Confirmă
</FodButton>
</FodDialogActions>
</FodDialog>
</FodOverlay>
Cu Drawer
<!-- Overlay pentru drawer -->
<FodOverlay Visible="@drawerOpen"
DarkBackground="true"
OnClick="@(() => drawerOpen = false)"
ZIndex="1200" />
<FodDrawer @bind-Open="drawerOpen"
Anchor="Anchor.Left"
Variant="DrawerVariant.Temporary"
Style="z-index: 1201;">
<!-- Drawer content -->
</FodDrawer>
Cu Loading states
<FodDataTable Items="@items"
Loading="@loading"
Style="position: relative;">
<HeaderContent>
<!-- Table headers -->
</HeaderContent>
<RowTemplate>
<!-- Row template -->
</RowTemplate>
@if (loading)
{
<FodOverlay Visible="true"
LightBackground="true"
Absolute="true">
<FodProgressLinear Color="FodColor.Primary"
Indeterminate="true" />
</FodOverlay>
}
</FodDataTable>
8. Patterns comune
Loading service global
public interface ILoadingService
{
event Action OnChange;
bool IsLoading { get; }
void Show(string message = null);
void Hide();
}
public class LoadingService : ILoadingService
{
public event Action OnChange;
public bool IsLoading { get; private set; }
public string Message { get; private set; }
public void Show(string message = null)
{
IsLoading = true;
Message = message;
OnChange?.Invoke();
}
public void Hide()
{
IsLoading = false;
Message = null;
OnChange?.Invoke();
}
}
// În MainLayout.razor
@implements IDisposable
@inject ILoadingService LoadingService
<FodOverlay Visible="@LoadingService.IsLoading"
DarkBackground="true">
<div class="d-flex flex-column align-items-center">
<FodProgressCircular Color="FodColor.Secondary"
Indeterminate="true" />
@if (!string.IsNullOrEmpty(LoadingService.Message))
{
<FodText Typo="Typo.body1" Color="FodColor.White" Class="mt-3">
@LoadingService.Message
</FodText>
}
</div>
</FodOverlay>
@code {
protected override void OnInitialized()
{
LoadingService.OnChange += StateHasChanged;
}
public void Dispose()
{
LoadingService.OnChange -= StateHasChanged;
}
}
Overlay cu timeout
<FodOverlay @bind-Visible="showTemporaryOverlay"
DarkBackground="true">
<FodAlert Severity="Severity.Success" Class="ma-4">
<FodAlertTitle>Succes!</FodAlertTitle>
Operațiunea a fost finalizată cu succes.
</FodAlert>
</FodOverlay>
@code {
private bool showTemporaryOverlay = false;
private CancellationTokenSource cts;
private async Task ShowSuccessMessage()
{
showTemporaryOverlay = true;
cts?.Cancel();
cts = new CancellationTokenSource();
try
{
await Task.Delay(3000, cts.Token);
showTemporaryOverlay = false;
}
catch (TaskCanceledException)
{
// Anulat - un nou mesaj a fost afișat
}
}
}
9. Considerații de performanță
- Scroll Lock Management - Componenta gestionează automat blocarea/deblocarea scroll-ului
- Dispose Pattern - Implementează IDisposable pentru cleanup corect
- Event Propagation - Folosește
@onclick:stopPropagation
pentru a preveni bubble-up - Conditional Rendering - Overlay-ul este randat doar când este vizibil
10. Accesibilitate
- Overlay-ul blochează interacțiunea cu conținutul de dedesubt
- Pentru overlay-uri modale, considerați adăugarea de atribute ARIA
- Asigurați contrast suficient pentru conținutul afișat peste overlay
- Oferiți modalități de închidere pentru utilizatorii de tastatură
11. Bune practici
- Loading States - Folosiți overlay pentru loading states consistente
- Z-Index Management - Gestionați z-index pentru overlay-uri multiple
- Scroll Lock - Activați doar când este necesar (modal-uri, meniuri)
- Auto Close - Activați pentru overlay-uri dismissible
- Absolute vs Fixed - Folosiți Absolute pentru containere specifice
- Cleanup - Asigurați-vă că overlay-ul este închis la navigare
12. Troubleshooting
Overlay-ul nu acoperă întreaga pagină
- Verificați că nu folosiți
Absolute="true"
- Verificați că părintele nu are
position: relative
- Verificați z-index-ul
Scroll-ul nu este blocat
- Verificați că
LockScroll="true"
- Verificați că nu folosiți
Absolute="true"
- Verificați că clasa CSS există
Conținutul nu este centrat
- Overlay-ul centrează automat conținutul
- Verificați CSS-ul personalizat
13. Exemple avansate
Overlay cu tranziții personalizate
@if (showAnimatedOverlay)
{
<FodOverlay Visible="true"
DarkBackground="true"
Class="@($"animated-overlay {(closing ? "closing" : "")}")"
OnClick="CloseWithAnimation">
<div class="content-scale">
<FodPaper Elevation="8" Class="pa-4">
<FodText Typo="Typo.h5">Conținut animat</FodText>
</FodPaper>
</div>
</FodOverlay>
}
<style>
.animated-overlay {
animation: fadeIn 0.3s ease-out;
}
.animated-overlay.closing {
animation: fadeOut 0.3s ease-out;
}
.content-scale {
animation: scaleIn 0.3s ease-out;
}
.closing .content-scale {
animation: scaleOut 0.3s ease-out;
}
@keyframes scaleIn {
from { transform: scale(0.8); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
@keyframes scaleOut {
from { transform: scale(1); opacity: 1; }
to { transform: scale(0.8); opacity: 0; }
}
</style>
@code {
private bool showAnimatedOverlay = false;
private bool closing = false;
private async Task CloseWithAnimation()
{
closing = true;
await Task.Delay(300);
showAnimatedOverlay = false;
closing = false;
}
}
Overlay stack management
@foreach (var overlay in overlayStack)
{
<FodOverlay @key="overlay.Id"
Visible="true"
DarkBackground="@(overlay == overlayStack.Last())"
ZIndex="@(1000 + overlayStack.IndexOf(overlay) * 100)"
OnClick="@(() => CloseOverlay(overlay.Id))">
@overlay.Content
</FodOverlay>
}
@code {
private List<OverlayItem> overlayStack = new();
private class OverlayItem
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public RenderFragment Content { get; set; }
}
private void ShowOverlay(RenderFragment content)
{
overlayStack.Add(new OverlayItem { Content = content });
}
private void CloseOverlay(string id)
{
overlayStack.RemoveAll(o => o.Id == id);
}
}
14. Concluzie
FodOverlay
oferă o soluție flexibilă pentru crearea de overlay-uri în aplicații Blazor, cu suport pentru multiple scenarii de utilizare: loading states, backdrop-uri pentru modals, protecție pentru click-uri nedorite și efecte vizuale. Componenta gestionează automat aspectele tehnice precum blocarea scroll-ului și oferă control complet asupra comportamentului și stilizării.