Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/BuildingBlocks/Blazor.UI/Blazor.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,27 @@
<AssemblyName>FSH.Framework.Blazor.UI</AssemblyName>
<PackageId>FullStackHero.Framework.Blazor.UI</PackageId>
<!-- MUD0002: MudBlazor analyzer false positives for valid component parameter usage in RenderFragment/component contexts -->
<NoWarn>$(NoWarn);MUD0002</NoWarn>
<NoWarn>$(NoWarn);MUD0002;NU1507</NoWarn>

<!-- Disable CSS isolation to prevent unused preload warnings -->
<!-- Components can still use regular CSS files -->
<GenerateScopedCssFiles>false</GenerateScopedCssFiles>
</PropertyGroup>


<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" />
<PackageReference Include="MudBlazor" />
<PackageReference Include="MudBlazor.ThemeManager" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" />
<PackageReference Include="MudBlazor" />
<PackageReference Include="MudBlazor.ThemeManager" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Components;
using FSH.Framework.Shared.Localization;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;

namespace FSH.Framework.Blazor.UI.Components.Base;

Expand All @@ -7,4 +9,5 @@ public abstract class FshComponentBase : ComponentBase
[Inject] protected ISnackbar Snackbar { get; set; } = default!;
[Inject] protected IDialogService DialogService { get; set; } = default!;
[Inject] protected NavigationManager Navigation { get; set; } = default!;
[Inject] protected IStringLocalizer<SharedResource> L { get; set; } = default!;
}
Empty file.
40 changes: 28 additions & 12 deletions src/BuildingBlocks/Blazor.UI/Components/Dialogs/FshDialogService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using MudBlazor;
using FSH.Framework.Shared.Localization;
using Microsoft.Extensions.Localization;
using System.Globalization;

namespace FSH.Framework.Blazor.UI.Components.Dialogs;

Expand Down Expand Up @@ -45,25 +46,40 @@ public static async Task<bool> ShowConfirmAsync(

public static Task<bool> ShowDeleteConfirmAsync(
this IDialogService dialogService,
string itemName = "this item")
string itemName,
IStringLocalizer<SharedResource>? localizer = null)
{
string title = localizer?["DeleteConfirmation"] ?? "Delete Confirmation";
string message = localizer != null
? string.Format(CultureInfo.InvariantCulture, localizer["ConfirmDelete"], itemName)
: $"Are you sure you want to delete {itemName}? This action cannot be undone.";
string confirmText = localizer?["Delete"] ?? "Delete";
string cancelText = localizer?["Cancel"] ?? "Cancel";

return dialogService.ShowConfirmAsync(
title: "Delete Confirmation",
message: $"Are you sure you want to delete {itemName}? This action cannot be undone.",
confirmText: "Delete",
cancelText: "Cancel",
title: title,
message: message,
confirmText: confirmText,
cancelText: cancelText,
confirmColor: Color.Error,
icon: Icons.Material.Outlined.DeleteForever,
iconColor: Color.Error);
}

public static Task<bool> ShowSignOutConfirmAsync(this IDialogService dialogService)
public static Task<bool> ShowSignOutConfirmAsync(
this IDialogService dialogService,
IStringLocalizer<SharedResource>? localizer = null)
{
string title = localizer?["SignOut"] ?? "Sign Out";
string message = localizer?["ConfirmSignOut"] ?? "Are you sure you want to sign out of your account?";
string confirmText = localizer?["SignOut"] ?? "Sign Out";
string cancelText = localizer?["Cancel"] ?? "Cancel";

return dialogService.ShowConfirmAsync(
title: "Sign Out",
message: "Are you sure you want to sign out of your account?",
confirmText: "Sign Out",
cancelText: "Cancel",
title: title,
message: message,
confirmText: confirmText,
cancelText: cancelText,
confirmColor: Color.Error,
icon: Icons.Material.Outlined.Logout,
iconColor: Color.Warning);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,15 @@ namespace FSH.Framework.Blazor.UI.Components.Feedback.Snackbar;
/// <summary>
/// Convenience wrapper for snackbar calls with consistent styling.
/// </summary>
public sealed class FshSnackbar
public sealed class FshSnackbar(ISnackbar snackbar)
{
private readonly ISnackbar _snackbar;

public FshSnackbar(ISnackbar snackbar)
{
_snackbar = snackbar;
}

public void Success(string message) => Add(message, Severity.Success);
public void Info(string message) => Add(message, Severity.Info);
public void Warning(string message) => Add(message, Severity.Warning);
public void Error(string message) => Add(message, Severity.Error);

private void Add(string message, Severity severity)
{
_snackbar.Add(message, severity);
snackbar.Add(message, severity);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
@using FSH.Framework.Blazor.UI.Theme
@using FSH.Framework.Shared.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<SharedResource> L

<MudPaper Class="pa-4" Elevation="0" Outlined="true">
<MudText Typo="Typo.h6" Class="mb-4">Brand Assets</MudText>
<MudText Typo="Typo.h6" Class="mb-4">@L["BrandAssets"]</MudText>

<MudGrid>
@* Light Mode Logo *@
<MudItem xs="12" sm="6" md="4">
<MudPaper Class="pa-4" Elevation="0" Outlined="true">
<MudText Typo="Typo.subtitle2" Class="mb-2">Logo (Light Mode)</MudText>
<MudText Typo="Typo.subtitle2" Class="mb-2">@L["LogoLightMode"]</MudText>
@if (!string.IsNullOrEmpty(BrandAssets.LogoUrl))
{
<div class="d-flex flex-column align-center gap-2">
Expand All @@ -21,7 +24,7 @@
Size="Size.Small"
StartIcon="@Icons.Material.Filled.Delete"
OnClick="@(() => ClearLogo())">
Remove
@L["Remove"]
</MudButton>
</div>
}
Expand All @@ -31,15 +34,16 @@
Accept=".png,.jpg,.jpeg,.svg,.webp"
FilesChanged="@OnLogoUpload"
MaximumFileCount="1">
<ActivatorContent>
<CustomContent Context="upload">
<MudPaper Class="pa-4 d-flex flex-column align-center justify-center cursor-pointer"
Style="border: 2px dashed; border-color: var(--mud-palette-lines-default); min-height: 100px;"
Elevation="0">
Elevation="0"
@onclick="@(async (e) => await upload.OpenFilePickerAsync())">
<MudIcon Icon="@Icons.Material.Outlined.CloudUpload" Size="Size.Large" Color="Color.Default" />
<MudText Typo="Typo.caption" Class="mt-2">Click to upload logo</MudText>
<MudText Typo="Typo.caption" Class="mt-2">@L["ClickToUpload"]</MudText>
<MudText Typo="Typo.caption" Color="Color.Secondary">PNG, JPG, SVG, WebP</MudText>
</MudPaper>
</ActivatorContent>
</CustomContent>
</MudFileUpload>
}
</MudPaper>
Expand All @@ -48,7 +52,7 @@
@* Dark Mode Logo *@
<MudItem xs="12" sm="6" md="4">
<MudPaper Class="pa-4" Elevation="0" Outlined="true" Style="background-color: #1a1a2e;">
<MudText Typo="Typo.subtitle2" Class="mb-2" Style="color: white;">Logo (Dark Mode)</MudText>
<MudText Typo="Typo.subtitle2" Class="mb-2" Style="color: white;">@L["LogoDarkMode"]</MudText>
@if (!string.IsNullOrEmpty(BrandAssets.LogoDarkUrl))
{
<div class="d-flex flex-column align-center gap-2">
Expand All @@ -62,7 +66,7 @@
Size="Size.Small"
StartIcon="@Icons.Material.Filled.Delete"
OnClick="@(() => ClearLogoDark())">
Remove
@L["Remove"]
</MudButton>
</div>
}
Expand All @@ -72,15 +76,16 @@
Accept=".png,.jpg,.jpeg,.svg,.webp"
FilesChanged="@OnLogoDarkUpload"
MaximumFileCount="1">
<ActivatorContent>
<CustomContent Context="upload">
<MudPaper Class="pa-4 d-flex flex-column align-center justify-center cursor-pointer"
Style="border: 2px dashed; border-color: rgba(255,255,255,0.3); min-height: 100px; background-color: transparent;"
Elevation="0">
Elevation="0"
@onclick="@(async (e) => await upload.OpenFilePickerAsync())">
<MudIcon Icon="@Icons.Material.Outlined.CloudUpload" Size="Size.Large" Style="color: rgba(255,255,255,0.7);" />
<MudText Typo="Typo.caption" Class="mt-2" Style="color: rgba(255,255,255,0.7);">Click to upload logo</MudText>
<MudText Typo="Typo.caption" Class="mt-2" Style="color: rgba(255,255,255,0.7);">@L["ClickToUpload"]</MudText>
<MudText Typo="Typo.caption" Style="color: rgba(255,255,255,0.5);">PNG, JPG, SVG, WebP</MudText>
</MudPaper>
</ActivatorContent>
</CustomContent>
</MudFileUpload>
}
</MudPaper>
Expand All @@ -89,7 +94,7 @@
@* Favicon *@
<MudItem xs="12" sm="6" md="4">
<MudPaper Class="pa-4" Elevation="0" Outlined="true">
<MudText Typo="Typo.subtitle2" Class="mb-2">Favicon</MudText>
<MudText Typo="Typo.subtitle2" Class="mb-2">@L["Favicon"]</MudText>
@if (!string.IsNullOrEmpty(BrandAssets.FaviconUrl))
{
<div class="d-flex flex-column align-center gap-2">
Expand All @@ -104,7 +109,7 @@
Size="Size.Small"
StartIcon="@Icons.Material.Filled.Delete"
OnClick="@(() => ClearFavicon())">
Remove
@L["Remove"]
</MudButton>
</div>
}
Expand All @@ -114,15 +119,16 @@
Accept=".png,.ico,.svg"
FilesChanged="@OnFaviconUpload"
MaximumFileCount="1">
<ActivatorContent>
<CustomContent Context="upload">
<MudPaper Class="pa-4 d-flex flex-column align-center justify-center cursor-pointer"
Style="border: 2px dashed; border-color: var(--mud-palette-lines-default); min-height: 100px;"
Elevation="0">
Elevation="0"
@onclick="@(async (e) => await upload.OpenFilePickerAsync())">
<MudIcon Icon="@Icons.Material.Outlined.Image" Size="Size.Large" Color="Color.Default" />
<MudText Typo="Typo.caption" Class="mt-2">Click to upload favicon</MudText>
<MudText Typo="Typo.caption" Class="mt-2">@L["ClickToUpload"]</MudText>
<MudText Typo="Typo.caption" Color="Color.Secondary">16x16 or 32x32 PNG, ICO</MudText>
</MudPaper>
</ActivatorContent>
</CustomContent>
</MudFileUpload>
}
</MudPaper>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
@using FSH.Framework.Blazor.UI.Theme
@using FSH.Framework.Shared.Localization
@using Microsoft.Extensions.Localization
@using MudBlazor.Utilities
@inject IStringLocalizer<SharedResource> L

<MudPaper Class="pa-4" Elevation="0" Outlined="true">
<MudText Typo="Typo.h6" Class="mb-4">@Title</MudText>

<MudGrid>
<MudItem xs="12" sm="6" md="4">
<MudText Typo="Typo.caption" Class="mb-1">Primary</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Primary"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Primary)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Primary = v))"
Label="Primary"
Label="@L["Primary"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -20,10 +23,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="4">
<MudText Typo="Typo.caption" Class="mb-1">Secondary</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Secondary"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Secondary)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Secondary = v))"
Label="Secondary"
Label="@L["Secondary"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -33,10 +36,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="4">
<MudText Typo="Typo.caption" Class="mb-1">Tertiary</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Tertiary"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Tertiary)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Tertiary = v))"
Label="Tertiary"
Label="@L["Tertiary"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -46,10 +49,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="4">
<MudText Typo="Typo.caption" Class="mb-1">Background</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Background"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Background)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Background = v))"
Label="Background"
Label="@L["Background"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -59,10 +62,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="4">
<MudText Typo="Typo.caption" Class="mb-1">Surface</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Surface"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Surface)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Surface = v))"
Label="Surface"
Label="@L["Surface"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -72,14 +75,14 @@
</MudItem>

<MudItem xs="12" Class="mt-4">
<MudText Typo="Typo.subtitle2" Class="mb-2">Semantic Colors</MudText>
<MudText Typo="Typo.subtitle2" Class="mb-2">@L["SemanticColors"]</MudText>
</MudItem>

<MudItem xs="12" sm="6" md="3">
<MudText Typo="Typo.caption" Class="mb-1">Success</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Success"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Success)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Success = v))"
Label="Success"
Label="@L["Success"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -89,10 +92,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="3">
<MudText Typo="Typo.caption" Class="mb-1">Info</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Info"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Info)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Info = v))"
Label="Info"
Label="@L["Info"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -102,10 +105,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="3">
<MudText Typo="Typo.caption" Class="mb-1">Warning</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Warning"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Warning)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Warning = v))"
Label="Warning"
Label="@L["Warning"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand All @@ -115,10 +118,10 @@
</MudItem>

<MudItem xs="12" sm="6" md="3">
<MudText Typo="Typo.caption" Class="mb-1">Error</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@L["Error"]</MudText>
<MudColorPicker Value="@GetColor(Palette.Error)"
ValueChanged="@(c => OnColorChanged(c, v => Palette.Error = v))"
Label="Error"
Label="@L["Error"]"
DisableAlpha="true"
DisableModeSwitch="true"
ColorPickerMode="ColorPickerMode.HEX"
Expand Down
Loading
Loading