diff --git a/src/BlazorUI/Bit.BlazorUI/Components/BitIconInfo.cs b/src/BlazorUI/Bit.BlazorUI/Components/BitIconInfo.cs new file mode 100644 index 0000000000..7558101df7 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI/Components/BitIconInfo.cs @@ -0,0 +1,202 @@ +namespace Bit.BlazorUI; + +/// +/// Represents icon information for rendering icons in Bit BlazorUI components. +/// Supports both built-in Fluent UI icons and custom/external icon libraries. +/// +public class BitIconInfo +{ + /// + /// Creates a new instance of . + /// + public BitIconInfo() { } + + /// + /// Creates a new instance of with the specified icon name. + /// + /// + /// The name of the icon. + /// + public BitIconInfo(string name) + { + Name = name; + } + + /// + /// Creates a new instance of with full customization. + /// + /// + /// The name of the icon or the CSS class for external icons. + /// + /// + /// The base CSS class for the icon. + /// Set to null or empty string for external icon libraries that don't need a base class. + /// + /// + /// The CSS class prefix used before the icon name. + /// Set to null or empty string for external icons that don't use a prefix. + /// + public BitIconInfo(string name, string? baseClass, string? prefix = null) + { + Name = name; + BaseClass = baseClass; + Prefix = prefix; + } + + /// + /// Gets or sets the name of the icon. + /// For external icons, this can be the full CSS class name if and are empty. + /// + public string? Name { get; set; } + + /// + /// Gets or sets the base CSS class for the icon. + /// For external icon libraries like FontAwesome, you might set this to "fa" or leave empty. + /// + public string? BaseClass { get; set; } + + /// + /// Gets or sets the CSS class prefix used before the icon name. + /// For external icon libraries, you might set this to "fa-" or leave empty. + /// + public string? Prefix { get; set; } + + + + /// + /// Gets the CSS classes to render the icon. + /// + /// The complete CSS class string for the icon. + public string GetCssClasses() + { + if (Name.HasNoValue()) return string.Empty; + + if (BaseClass.HasNoValue() && Prefix.HasNoValue()) + { + return Name!; + } + + if (BaseClass.HasNoValue()) + { + return $"{Prefix}{Name}"; + } + + if (Prefix.HasNoValue()) + { + return $"{BaseClass} {Name}"; + } + + return $"{BaseClass} {Prefix}{Name}"; + } + + /// + /// Implicit conversion from string to . + /// This maintains backward compatibility with the existing string-based IconName parameter. + /// + /// + /// The icon name string. + /// + public static implicit operator BitIconInfo?(string? iconName) + { + if (iconName is null) return null; + + return new BitIconInfo(iconName); + } + + /// + /// Implicit conversion from to string. + /// Returns the icon name for simple scenarios. + /// + /// + /// The icon info instance. + /// + public static implicit operator string?(BitIconInfo? iconInfo) + { + return iconInfo?.Name; + } + + /// + /// Creates a for an external/custom icon using the provided CSS classes directly. + /// + /// + /// The complete CSS class(es) to render the icon (e.g., "fa-solid fa-house" for FontAwesome). + /// + /// + /// A new instance configured for external icons. + /// + public static BitIconInfo Css(string cssClasses) + { + return new BitIconInfo(cssClasses, baseClass: "", prefix: ""); + } + + /// + /// Creates a for a built-in bit BlazorUI icon. + /// + /// + /// The bit BlazorUI icon name (e.g., "add"). + /// + /// + /// A new instance configured for bit BlazorUI icons. + /// + public static BitIconInfo Bit(string name) + { + return new BitIconInfo(name, baseClass: "bit-icon", prefix: "bit-icon--"); + } + + /// + /// Creates a for a FontAwesome icon. + /// + /// + /// The FontAwesome icon classes (e.g., "fa-solid fa-house", "solid house", or just "house" with style parameter). + /// + /// + /// A new instance configured for FontAwesome icons. + /// + public static BitIconInfo Fa(string icons) + { + var cssClasses = string.Join(' ', icons.Split(' ', StringSplitOptions.RemoveEmptyEntries) + .Select(i => i.StartsWith("fa-") ? i : $"fa-{i}")); + + return new BitIconInfo(cssClasses, baseClass: "", prefix: ""); + } + + /// + /// Creates a for a Bootstrap Icons icon. + /// + /// + /// The Bootstrap Icon name without the "bi-" prefix (e.g., "house", "search"). + /// + /// + /// A new instance configured for Bootstrap Icons. + /// + public static BitIconInfo Bi(string iconName) + { + return new BitIconInfo(iconName, baseClass: "bi", prefix: "bi-"); + } + + /// + /// Resolves the effective icon from either a or an icon name string. + /// The parameter takes precedence when both are provided. + /// + /// + /// The icon info instance, if provided. + /// + /// + /// The icon name string for built-in icons, if provided. + /// + /// + /// A instance if either parameter has a value; otherwise, null. + /// + /// + /// This method is useful for components to unify the handling of + /// the Icon and IconName parameters. + /// + public static BitIconInfo? From(BitIconInfo? icon, string? iconName) + { + if (icon is not null) return icon; + + if (iconName.HasNoValue()) return null; + + return Bit(iconName!); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.razor.cs index 9d9d7846d5..bc2a2064eb 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.razor.cs @@ -1,30 +1,46 @@ namespace Bit.BlazorUI; /// -/// An icon represents concept or meaning for the user. It's used to make better user experience (UX) and user-friendly applications. +/// A component for displaying icons that enhance visual communication and user experience. +/// Supports both built-in Fluent UI icons and external icon libraries. /// public partial class BitIcon : BitComponentBase { /// - /// The general color of the icon. + /// Specifies the color theme of the icon. + /// Default value is . /// [Parameter, ResetClassBuilder] public BitColor? Color { get; set; } /// - /// The icon name for the icon shown. + /// Specifies the icon configuration for rendering icons from external icon libraries using custom CSS classes. + /// Takes precedence over when both are set. + /// + /// + /// Use this property for external icon libraries such as FontAwesome, or Bootstrap Icons. + /// For built-in Fluent UI icons, use the property instead. + /// + [Parameter, ResetClassBuilder] + public BitIconInfo? Icon { get; set; } + + /// + /// Specifies the name of the icon from the built-in Fluent UI icon library. + /// This property is ignored when is set. /// [Parameter, ResetClassBuilder] public string? IconName { get; set; } /// - /// The size of the icon. + /// Specifies the size of the icon. + /// Default value is . /// [Parameter, ResetClassBuilder] public BitSize? Size { get; set; } /// - /// The visual variant of the icon. + /// Specifies the visual styling variant of the icon. + /// Default value is . /// [Parameter, ResetClassBuilder] public BitVariant? Variant { get; set; } @@ -57,7 +73,7 @@ protected override void RegisterCssClasses() _ => "bit-ico-pri" }); - ClassBuilder.Register(() => IconName.HasValue() ? $"bit-icon bit-icon--{IconName}" : string.Empty); + ClassBuilder.Register(() => BitIconInfo.From(Icon, IconName)?.GetCssClasses()); ClassBuilder.Register(() => Size switch { diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor index f4829557b9..f834edbba0 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor @@ -1,4 +1,4 @@ -@page "/components/icon" +@page "/components/icon" @@ -16,8 +17,11 @@   +



-
Disabled

+ +
Disabled
+
  @@ -26,92 +30,100 @@ -
Fill

+
Fill
+
+



-
Outline

+ +
Outline
+
-



-
Text (default)

- -
- -
Small

- -   - -   - -



-
Medium

- -   - -   -



-
Large

- -   - -   - + +
Text (default)
+
+
- +
Offering a range of specialized color variants, providing visual cues for specific actions or states within your application.
+


-
Primary

+ +
Primary
+
    +



-
Secondary

+ +
Secondary
+
    +



-
Tertiary

+ +
Tertiary
+
    +



-
Info

+ +
Info
+
    +



-
Success

+ +
Success
+
    +



-
Warning

+ +
Warning
+
    +



-
SevereWarning

+ +
SevereWarning
+
    +



-
Error

+ +
Error
+
  @@ -119,11 +131,76 @@
- + +
Use icons from external libraries like FontAwesome, Material Icons, and Bootstrap Icons with the Icon parameter.
+ +

+ + + +
FontAwesome
+
+ +   + +   + +   + + +



+ + + +
Bootstrap Icons
+
+ +   + +   + +   + +
+ + +
Small
+
+ +   + +   + + +



+ +
Medium
+
+ +   + +   + + +



+ +
Large
+
+ +   + +   + +
+ +
- - + +
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs index 28f1cedbab..fa28a82786 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs @@ -9,16 +9,25 @@ public partial class BitIconDemo Name = "Color", Type = "BitColor?", DefaultValue = "null", - Description = "The general color of the icon.", + Description = "Specifies the color theme of the icon. Default value is BitColor.Primary.", LinkType = LinkType.Link, Href = "#color-enum", }, new() + { + Name = "Icon", + Type = "BitIconInfo?", + DefaultValue = "null", + Description = "Specifies the icon configuration for rendering icons from external icon libraries using custom CSS classes. Takes precedence over IconName when both are set.", + LinkType = LinkType.Link, + Href = "#bit-icon-info", + }, + new() { Name = "IconName", Type = "string", DefaultValue = "", - Description = "The icon name for the icon shown", + Description = "Specifies the name of the icon from the built-in Fluent UI icon library. This property is ignored when Icon is set.", LinkType = LinkType.Link, Href = "/iconography", }, @@ -27,7 +36,7 @@ public partial class BitIconDemo Name = "Size", Type = "BitSize?", DefaultValue = "null", - Description = "The size of the icon.", + Description = "Specifies the size of the icon. Default value is BitSize.Medium.", LinkType = LinkType.Link, Href = "#icon-size-enum", }, @@ -36,12 +45,45 @@ public partial class BitIconDemo Name = "Variant", Type = "BitVariant?", DefaultValue = "null", - Description = "The visual variant of the icon.", + Description = "Specifies the visual styling variant of the icon. Default value is BitVariant.Text.", LinkType = LinkType.Link, Href = "#variant-enum", }, ]; + private readonly List componentSubClasses = + [ + new() + { + Id = "bit-icon-info", + Title = "BitIconInfo", + Parameters = + [ + new() + { + Name = "Name", + Type = "string?", + DefaultValue = "null", + Description = "Gets or sets the name of the icon." + }, + new() + { + Name = "BaseClass", + Type = "string?", + DefaultValue = "null", + Description = "Gets or sets the base CSS class for the icon. For built-in Fluent UI icons, this defaults to \"bit-icon\". For external icon libraries like FontAwesome, you might set this to \"fa\" or leave empty." + }, + new() + { + Name = "Prefix", + Type = "string?", + DefaultValue = "null", + Description = "Gets or sets the CSS class prefix used before the icon name. For built-in Fluent UI icons, this defaults to \"bit-icon--\". For external icon libraries, you might set this to \"fa-\" or leave empty." + }, + ] + }, + ]; + private readonly List componentSubEnums = [ new() @@ -230,19 +272,6 @@ public partial class BitIconDemo "; private readonly string example3RazorCode = @" - - - - - - - - - - -"; - - private readonly string example4RazorCode = @" @@ -275,7 +304,36 @@ public partial class BitIconDemo "; + private readonly string example4RazorCode = @" + + + + + + + + + + + + + +"; + private readonly string example5RazorCode = @" + + + + + + + + + + +"; + + private readonly string example6RazorCode = @" - -"; + +"; } diff --git a/src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Utilities/Icon/BitIconInfoTests.cs b/src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Utilities/Icon/BitIconInfoTests.cs new file mode 100644 index 0000000000..d391926a64 --- /dev/null +++ b/src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Utilities/Icon/BitIconInfoTests.cs @@ -0,0 +1,426 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Bit.BlazorUI.Tests.Components.Utilities.Icon; + +[TestClass] +public class BitIconInfoTests +{ + [TestMethod] + public void ConstructorShouldSetAllProperties() + { + var iconInfo = new BitIconInfo("home", "fa", "fa-"); + + Assert.AreEqual("home", iconInfo.Name); + Assert.AreEqual("fa", iconInfo.BaseClass); + Assert.AreEqual("fa-", iconInfo.Prefix); + } + + [TestMethod] + public void ConstructorWithOnlyNameShouldSetNameOnly() + { + var iconInfo = new BitIconInfo("home"); + + Assert.AreEqual("home", iconInfo.Name); + Assert.IsNull(iconInfo.BaseClass); + Assert.IsNull(iconInfo.Prefix); + } + + [TestMethod] + public void GetCssClassesWithBaseClassAndPrefixShouldReturnCorrectClasses() + { + var iconInfo = new BitIconInfo("home", "fa", "fa-"); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("fa fa-home", result); + } + + [TestMethod] + public void GetCssClassesWithBaseClassOnlyShouldReturnBaseClassAndName() + { + var iconInfo = new BitIconInfo("home", "material-icons", ""); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("material-icons home", result); + } + + [TestMethod] + public void GetCssClassesWithPrefixOnlyShouldReturnPrefixedName() + { + var iconInfo = new BitIconInfo("home", "", "icon-"); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("icon-home", result); + } + + [TestMethod] + public void GetCssClassesWithEmptyBaseClassAndPrefixShouldReturnNameOnly() + { + var iconInfo = new BitIconInfo("home", "", ""); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("home", result); + } + + // Factory Method Tests + + [TestMethod] + public void CssShouldCreateIconInfoWithEmptyBaseClassAndPrefix() + { + var iconInfo = BitIconInfo.Css("fa-solid fa-home"); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("", iconInfo.BaseClass); + Assert.AreEqual("", iconInfo.Prefix); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void FontAwesomeShouldCreateIconInfoForFontAwesome6() + { + var iconInfo = BitIconInfo.Fa("fa-solid fa-home"); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("", iconInfo.BaseClass); + Assert.AreEqual("", iconInfo.Prefix); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void FontAwesomeShouldHandleBrandIcons() + { + var iconInfo = BitIconInfo.Fa("fa-brands fa-github"); + + Assert.AreEqual("fa-brands fa-github", iconInfo.Name); + Assert.AreEqual("fa-brands fa-github", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void BootstrapShouldCreateBootstrapIconInfo() + { + var iconInfo = BitIconInfo.Bi("check-circle"); + + Assert.AreEqual("check-circle", iconInfo.Name); + Assert.AreEqual("bi", iconInfo.BaseClass); + Assert.AreEqual("bi-", iconInfo.Prefix); + Assert.AreEqual("bi bi-check-circle", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void BootstrapShouldHandleVariousIconNames() + { + var iconInfo = BitIconInfo.Bi("house"); + + Assert.AreEqual("house", iconInfo.Name); + Assert.AreEqual("bi", iconInfo.BaseClass); + Assert.AreEqual("bi-", iconInfo.Prefix); + Assert.AreEqual("bi bi-house", iconInfo.GetCssClasses()); + } + + // Implicit Conversion Tests + + [TestMethod] + public void ImplicitConversionFromStringShouldCreateIconInfo() + { + BitIconInfo iconInfo = "home"; + + Assert.AreEqual("home", iconInfo.Name); + Assert.IsNull(iconInfo.BaseClass); + Assert.IsNull(iconInfo.Prefix); + } + + [TestMethod] + public void ImplicitConversionFromNullStringShouldReturnNull() + { + string? nullString = null; + BitIconInfo? iconInfo = nullString; + + Assert.IsNull(iconInfo); + } + + [TestMethod] + public void ImplicitConversionToStringShouldReturnName() + { + var iconInfo = new BitIconInfo("home", "fa", "fa-"); + + string? result = iconInfo; + + Assert.AreEqual("home", result); + } + + [TestMethod] + public void ImplicitConversionFromNullIconInfoShouldReturnNull() + { + BitIconInfo? iconInfo = null; + + string? result = iconInfo; + + Assert.IsNull(result); + } + + // CSS class generation tests + + [TestMethod] + public void GetCssClassesFontAwesome6SolidIconShouldGenerateCorrectClasses() + { + var iconInfo = BitIconInfo.Fa("fa-solid fa-user"); + + Assert.AreEqual("fa-solid fa-user", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesFontAwesome6RegularIconShouldGenerateCorrectClasses() + { + var iconInfo = BitIconInfo.Fa("fa-regular fa-heart"); + + Assert.AreEqual("fa-regular fa-heart", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesFontAwesome6BrandIconShouldGenerateCorrectClasses() + { + var iconInfo = BitIconInfo.Fa("fa-brands fa-github"); + + Assert.AreEqual("fa-brands fa-github", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesBootstrapShouldGenerateCorrectClasses() + { + var iconInfo = BitIconInfo.Bi("arrow-right"); + + Assert.AreEqual("bi bi-arrow-right", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesCustomCssShouldGenerateCorrectClasses() + { + var iconInfo = BitIconInfo.Css("my-custom-icon-class"); + + Assert.AreEqual("my-custom-icon-class", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesCustomIconWithConstructorShouldGenerateCorrectClasses() + { + var iconInfo = new BitIconInfo("custom-icon", "my-icons", "ico-"); + + Assert.AreEqual("my-icons ico-custom-icon", iconInfo.GetCssClasses()); + } + + // Edge Cases + + [TestMethod] + public void GetCssClassesWithEmptyBaseClassShouldHandleCorrectly() + { + var iconInfo = new BitIconInfo("home", "", "icon-"); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("icon-home", result); + } + + [TestMethod] + public void GetCssClassesWithEmptyPrefixShouldHandleCorrectly() + { + var iconInfo = new BitIconInfo("home", "icons", ""); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("icons home", result); + } + + [TestMethod] + public void GetCssClassesWithAllEmptyStringsShouldReturnEmptyString() + { + var iconInfo = new BitIconInfo("", "", ""); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("", result); + } + + [TestMethod] + public void GetCssClassesWithSpecialCharactersInNameShouldHandleCorrectly() + { + var iconInfo = BitIconInfo.Fa("fa-solid fa-arrow-circle-right"); + + Assert.AreEqual("fa-solid fa-arrow-circle-right", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void GetCssClassesBootstrapWithHyphenatedNameShouldHandleCorrectly() + { + var iconInfo = BitIconInfo.Bi("check-circle-fill"); + + Assert.AreEqual("bi bi-check-circle-fill", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void DefaultConstructorShouldCreateEmptyIconInfo() + { + var iconInfo = new BitIconInfo(); + + Assert.IsNull(iconInfo.Name); + Assert.IsNull(iconInfo.BaseClass); + Assert.IsNull(iconInfo.Prefix); + } + + [TestMethod] + public void GetCssClassesWithNullNameShouldReturnEmptyString() + { + var iconInfo = new BitIconInfo(); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("", result); + } + + // Bit Factory Method Tests + + [TestMethod] + public void BitShouldCreateIconInfoForBitBlazorUIIcons() + { + var iconInfo = BitIconInfo.Bit("Add"); + + Assert.AreEqual("Add", iconInfo.Name); + Assert.AreEqual("bit-icon", iconInfo.BaseClass); + Assert.AreEqual("bit-icon--", iconInfo.Prefix); + Assert.AreEqual("bit-icon bit-icon--Add", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void BitShouldHandleVariousIconNames() + { + var iconInfo = BitIconInfo.Bit("ChevronDown"); + + Assert.AreEqual("ChevronDown", iconInfo.Name); + Assert.AreEqual("bit-icon", iconInfo.BaseClass); + Assert.AreEqual("bit-icon--", iconInfo.Prefix); + Assert.AreEqual("bit-icon bit-icon--ChevronDown", iconInfo.GetCssClasses()); + } + + // From Method Tests + + [TestMethod] + public void FromShouldReturnIconWhenIconIsProvided() + { + var icon = BitIconInfo.Fa("fa-solid fa-home"); + + var result = BitIconInfo.From(icon, "Add"); + + Assert.AreSame(icon, result); + } + + [TestMethod] + public void FromShouldCreateBitIconWhenOnlyIconNameIsProvided() + { + var result = BitIconInfo.From(null, "Add"); + + Assert.IsNotNull(result); + Assert.AreEqual("Add", result.Name); + Assert.AreEqual("bit-icon", result.BaseClass); + Assert.AreEqual("bit-icon--", result.Prefix); + Assert.AreEqual("bit-icon bit-icon--Add", result.GetCssClasses()); + } + + [TestMethod] + public void FromShouldReturnNullWhenBothParametersAreNull() + { + var result = BitIconInfo.From(null, null); + + Assert.IsNull(result); + } + + [TestMethod] + public void FromShouldReturnNullWhenIconNameIsEmpty() + { + var result = BitIconInfo.From(null, ""); + + Assert.IsNull(result); + } + + [TestMethod] + public void FromShouldPrioritizeIconOverIconName() + { + var icon = BitIconInfo.Bi("house"); + + var result = BitIconInfo.From(icon, "Add"); + + Assert.AreSame(icon, result); + Assert.AreEqual("bi bi-house", result?.GetCssClasses()); + } + + // Null BaseClass and Prefix Tests + + [TestMethod] + public void GetCssClassesWithNullBaseClassAndNullPrefixShouldReturnNameOnly() + { + var iconInfo = new BitIconInfo("home"); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("home", result); + } + + [TestMethod] + public void GetCssClassesWithNullBaseClassAndPrefixShouldReturnPrefixedName() + { + var iconInfo = new BitIconInfo("home", null, "icon-"); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("icon-home", result); + } + + [TestMethod] + public void GetCssClassesWithBaseClassAndNullPrefixShouldReturnBaseClassAndName() + { + var iconInfo = new BitIconInfo("home", "material-icons", null); + + var result = iconInfo.GetCssClasses(); + + Assert.AreEqual("material-icons home", result); + } + + // FontAwesome Shorthand Tests + + [TestMethod] + public void FontAwesomeShouldAddFaPrefixWhenMissing() + { + var iconInfo = BitIconInfo.Fa("solid home"); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void FontAwesomeShouldNotAddFaPrefixWhenAlreadyPresent() + { + var iconInfo = BitIconInfo.Fa("fa-solid fa-home"); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void FontAwesomeShouldHandleMixedPrefixes() + { + var iconInfo = BitIconInfo.Fa("fa-solid home"); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } + + [TestMethod] + public void FontAwesomeShouldHandleExtraSpaces() + { + var iconInfo = BitIconInfo.Fa(" solid home "); + + Assert.AreEqual("fa-solid fa-home", iconInfo.Name); + Assert.AreEqual("fa-solid fa-home", iconInfo.GetCssClasses()); + } +}