diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor new file mode 100644 index 0000000000..972b59d00d --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor @@ -0,0 +1,20 @@ + + + @Label + + + @Value + + + diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor.cs new file mode 100644 index 0000000000..bc854ec69e --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconDetailRow.razor.cs @@ -0,0 +1,22 @@ +namespace Bit.BlazorUI.Demo.Client.Core.Pages.Iconography; + +public partial class IconDetailRow +{ + [Parameter] public string Label { get; set; } = default!; + + [Parameter] public string Value { get; set; } = default!; + + [Parameter] public string CopyKey { get; set; } = default!; + + [Parameter] public string? CopyFeedbackKey { get; set; } + + [Parameter] public EventCallback<(string Text, string Key)> OnCopy { get; set; } + + + + private bool IsCopied => CopyFeedbackKey == CopyKey; + + + + private Task HandleCopy() => OnCopy.InvokeAsync((Value, CopyKey)); +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor new file mode 100644 index 0000000000..408a118b9b --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor @@ -0,0 +1,237 @@ +@page "/iconography" + +@code { + private IEnumerable _cascadingParams = new List + { + new BitCardParams { Background = BitColorKind.Primary, FullWidth = true, Style = "padding: 1.5rem" }, + new BitTextParams { Typography = BitTypography.Body1 }, + new BitTagParams { Color = BitColor.TertiaryBackground }, + }; +} + + + +
+ + Iconography + +
+ + + bit BlazorUI is using a custom font for icons of its components. + This font is part of the MDL2 design system (Office UI fabric icons) and contains glyphs that you can scale, color, and style in any way. + + +

+ + + + Note: To use these Icons, you need to add the Bit.BlazorUI.Icons nuget package to your project + as described in the Optional steps of the Getting started page. + + + +
+ + + Icon list + +
+ + + Note: click an icon to open its details. Use the panel to preview sizes, colors, and copy usage snippets. + + + + +
+ + + + @if (filteredIcons.Count == 0) + { + No result + } + else + { + foreach (var icon in filteredIcons) + { + + + + + + @icon.Value + + + + } + } + + +
+ +
+ + +
+
+ +
+ + + @if (selectedIcon is not null) + { + var glyphCode = GetGlyphCode(selectedIcon); + + + + + + + @selectedIcon.Value + + + + @selectedIcon.ConstantReference + + + + @(copyFeedbackKey == COPY_KEY_NAME ? "Copied" : "Copy name") + + + + +
+ + Preview + + + + + + + + Small + + + + + + Medium + + + + + + Large + + + + + + + + @foreach (var color in previewColors) + { + + + + @color.Label + + + } + + + +
+ +
+ + Properties + + + + +
+ +
+ + @if (string.IsNullOrEmpty(glyphCode) is false) + { +
+ + } +
+
+
+ +
+ + Usage + + + + + + IconName parameter + + + + @($"") + + + + + + BitIconInfo + + + + @($"") + + + +
+
+ } + +
+
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.cs new file mode 100644 index 0000000000..b482c5e341 --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.cs @@ -0,0 +1,156 @@ +using System.Reflection; +using System.Text.RegularExpressions; +using System.Globalization; +using Microsoft.AspNetCore.Components.Web; + +namespace Bit.BlazorUI.Demo.Client.Core.Pages.Iconography; + +public partial class IconographyPage +{ + private sealed record IconInfo(string FieldName, string Value) + { + public string ConstantReference => $"BitIconName.{FieldName}"; + + public string CssClass => $"bit-icon bit-icon--{Value}"; + + public string RazorIconName => $"IconName=\"@BitIconName.{FieldName}\""; + + public string RazorIconInfo => $"Icon=\"@BitIconInfo.Bit(\"{Value}\")\""; + } + + + + private const double IconPanelSize = 400; + + private const string COPY_KEY_NAME = "name"; + + private static readonly (string Label, BitColor Value)[] previewColors = + [ + ("Primary", BitColor.Primary), + ("Secondary", BitColor.Secondary), + ("Tertiary", BitColor.Tertiary), + ("Info", BitColor.Info), + ("Success", BitColor.Success), + ("Warning", BitColor.Warning), + ("Error", BitColor.Error), + ]; + + private List allIcons = default!; + private List filteredIcons = default!; + private IconInfo? selectedIcon; + private bool isIconPanelOpen; + private Dictionary? iconGlyphs; + private string? copyFeedbackKey; + + + + [AutoInject] private IJSRuntime _js = default!; + + [AutoInject] private HttpClient _http = default!; + + + + protected override void OnInitialized() + { + allIcons = [.. typeof(BitIconName).GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(m => new IconInfo(m.Name, m.GetValue(null)?.ToString() ?? string.Empty)) + .Where(i => string.IsNullOrEmpty(i.Value) is false) + .OrderBy(i => i.Value, StringComparer.OrdinalIgnoreCase)]; + + HandleClear(); + base.OnInitialized(); + } + + + + private void HandleClear() + { + filteredIcons = allIcons; + } + + private void HandleChange(string text) + { + HandleClear(); + if (string.IsNullOrEmpty(text)) return; + + filteredIcons = allIcons.FindAll(icon => + icon.Value.Contains(text, StringComparison.InvariantCultureIgnoreCase) || + icon.FieldName.Contains(text, StringComparison.InvariantCultureIgnoreCase)); + } + + private async Task OpenIconPanel(IconInfo icon) + { + selectedIcon = icon; + isIconPanelOpen = true; + copyFeedbackKey = null; + await EnsureGlyphsLoadedAsync(); + } + + private async Task CloseIconPanel() + { + isIconPanelOpen = false; + StateHasChanged(); + + await Task.Delay(200); + + if (isIconPanelOpen is false) + { + selectedIcon = null; + StateHasChanged(); + } + } + + private Task HandleIconPanelDismissed(MouseEventArgs _) + { + return CloseIconPanel(); + } + + private string? GetGlyphCode(IconInfo icon) + { + if (iconGlyphs is null) return null; + + if (iconGlyphs.TryGetValue(icon.Value, out var glyph) is false || string.IsNullOrEmpty(glyph)) return null; + + if (glyph[0] == '\\' && int.TryParse(glyph[1..], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var escapedCodePoint)) + { + return $"\\{escapedCodePoint:X4}"; + } + + return $"\\{char.ConvertToUtf32(glyph, 0):X4}"; + } + + private async Task EnsureGlyphsLoadedAsync() + { + if (iconGlyphs is not null) return; + + try + { + var css = await _http.GetStringAsync("_content/Bit.BlazorUI.Icons/styles/bit.blazorui.icons.css"); + iconGlyphs = Regex.Matches(css, @"\.bit-icon--([^:{]+)::before\{content:""([^""]+)""\}") + .ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value); + } + catch + { + iconGlyphs = null; + } + } + + private Task CopyIconName() => CopyToClipboard(selectedIcon!.Value, COPY_KEY_NAME); + + private Task HandleDetailCopy((string Text, string Key) args) => CopyToClipboard(args.Text, args.Key); + + private async Task CopyToClipboard(string text, string feedbackKey) + { + await _js.CopyToClipboard(text); + copyFeedbackKey = feedbackKey; + StateHasChanged(); + + await Task.Delay(1500); + + if (copyFeedbackKey == feedbackKey) + { + copyFeedbackKey = null; + StateHasChanged(); + } + } +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.scss new file mode 100644 index 0000000000..2bceac4deb --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Iconography/IconographyPage.razor.scss @@ -0,0 +1,40 @@ +@import '../../Styles/abstracts/_bit-css-variables.scss'; + +::deep { + .iconography-search-box { + max-width: 19rem; + } + + .icon-box { + margin: 1px; + height: auto; + width: 5.125rem; + min-height: unset; + cursor: pointer; + padding: 0.5rem; + border-radius: $bit-shape-border-radius; + transition: background-color 0.15s ease; + + .icon-name { + opacity: 0; + text-align: center; + overflow-wrap: anywhere; + } + + &:hover, + &:focus-visible, + &:active, + &.selected { + color: inherit; + background-color: $bit-color-background-secondary; + + .icon-name { + opacity: 1; + } + } + + &.selected { + outline: 1px solid $bit-color-border-primary; + } + } +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor deleted file mode 100644 index 9e9b9997b7..0000000000 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor +++ /dev/null @@ -1,85 +0,0 @@ -@page "/iconography" - -@code { - private IEnumerable _cascadingParams = new List - { - new BitCardParams { Background = BitColorKind.Primary, FullWidth = true, Style = "padding: 1.5rem" }, - new BitTextParams { Typography = BitTypography.Body1 }, - new BitTagParams { Color = BitColor.TertiaryBackground }, - }; -} - - - -
- - Iconography - -
- - - bit BlazorUI is using a custom font for icons of its components. - This font is part of the MDL2 design system (Office UI fabric icons) and contains glyphs that you can scale, color, and style in any way. - - -

- - - - Note: To use these Icons, you need to add the Bit.BlazorUI.Icons nuget package to your project - as described in the Optional steps of the Getting started page. - - - -
- - - Icon list - -
- - - Note: click on an icon to copy its name to clipboard. - - - - -
- - - - @if (filteredIcons.Count == 0) - { - No result - } - else - { - foreach (var icon in filteredIcons) - { - - - - @icon - - - } - } - - -
- -
- - -
-
\ No newline at end of file diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.cs deleted file mode 100644 index 8f405e07cf..0000000000 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Reflection; - -namespace Bit.BlazorUI.Demo.Client.Core.Pages; - -public partial class IconographyPage -{ - private List allIcons = default!; - private List filteredIcons = default!; - - - - [AutoInject] private IJSRuntime _js = default!; - - - - protected override void OnInitialized() - { - allIcons = typeof(BitIconName).GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(m => m.GetValue(null)?.ToString()!) - .ToList(); - HandleClear(); - base.OnInitialized(); - } - - - - private void HandleClear() - { - filteredIcons = allIcons; - } - - private void HandleChange(string text) - { - HandleClear(); - if (string.IsNullOrEmpty(text)) return; - - filteredIcons = allIcons.FindAll(icon => string.IsNullOrEmpty(icon) is false && icon.Contains(text, StringComparison.InvariantCultureIgnoreCase)); - } - - private async Task CopyToClipboard(string iconName) - { - await _js.CopyToClipboard(iconName); - } -} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.scss deleted file mode 100644 index 01f72983c3..0000000000 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/IconographyPage.razor.scss +++ /dev/null @@ -1,21 +0,0 @@ -::deep { - .iconography-search-box { - max-width: 19rem; - } - - .icon-box { - width: 5rem; - cursor: copy; - padding: 0.5rem; - - .icon-name { - opacity: 0; - } - - &:hover { - .icon-name { - opacity: 1; - } - } - } -} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json index 41efb55017..22110458df 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json @@ -546,8 +546,8 @@ "options": { "sourceMap": false } }, { - "outputFile": "Pages/IconographyPage.razor.css", - "inputFile": "Pages/IconographyPage.razor.scss", + "outputFile": "Pages/Iconography/IconographyPage.razor.css", + "inputFile": "Pages/Iconography/IconographyPage.razor.scss", "minify": { "enabled": false }, "options": { "sourceMap": false } },