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());
+ }
+}