diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
index 005c8155b7..917e69feaf 100644
--- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
+++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
@@ -13011,12 +13011,17 @@
- FluentUI System Icon font size 10x10
+ Filled variant of FluentUI System Icons
- FluentUI System Icon font size 12x12
+ Regular variant of FluentUI System Icons
+
+
+
+
+ Light variant of FluentUI System Icons
@@ -14291,6 +14296,13 @@
By default, the tooltip closes if the cursor leaves the anchor, but not the tooltip itself.
+
+
+ Gets or sets the value indicating whether the library should validate CSS class names.
+ respecting the following regex: "^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$".
+ Default is true.
+
+
A strongly-typed resource class, for looking up localized strings, etc.
@@ -14367,11 +14379,22 @@
Looks up a localized string similar to {0} years ago.
+
+
+ Validate CSS class, which must respect the following regex: "^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$".
+ Default is true.
+
+
Initializes a new instance of the class.
+
+
+ Initializes a new instance of the class.
+
+
Initializes a new instance of the class.
diff --git a/examples/Demo/Shared/wwwroot/docs/CodeSetup.md b/examples/Demo/Shared/wwwroot/docs/CodeSetup.md
index c16bb729ad..cfcb405869 100644
--- a/examples/Demo/Shared/wwwroot/docs/CodeSetup.md
+++ b/examples/Demo/Shared/wwwroot/docs/CodeSetup.md
@@ -49,6 +49,23 @@ When using **SSR (Static Server Rendering)**, you will need to include the web c
```
If you would later add interactivity, the Blazor script will kick in and try to load the web component script again but JavaScript will handle that gracefully by design.
+### Styles
+
+The styles used by FluentUI are included in the package.
+You don't need to do anything to include them in your project.
+
+You can always add your own styles, using the `class` or `style` attribute on the components.
+By default, the classes are organised and checked by the component itself (in particular by checking that the class names are valid).
+Some frameworks, such as **Tailwind CSS**, add exceptions to class names (e.g. `min-h-[16px]` or `bg-[#ff0000]`).
+In this case, you need to disable class name validation by adding this code to your `Program.cs` file:
+
+```csharp
+builder.Services.AddFluentUIComponents(options =>
+{
+ options.ValidateClassNames = false;
+});
+```
+
### Reboot (optional)
**Reboot** is a collection of element-specific CSS changes in a single file to help kick-start building a site with the **Fluent UI Blazor** components for Blazor. It provides an elegant, consistent, and simple baseline to build upon.
diff --git a/src/Core/Infrastructure/LibraryConfiguration.cs b/src/Core/Infrastructure/LibraryConfiguration.cs
index 00d375a65a..6547a2b168 100644
--- a/src/Core/Infrastructure/LibraryConfiguration.cs
+++ b/src/Core/Infrastructure/LibraryConfiguration.cs
@@ -29,6 +29,17 @@ public class LibraryConfiguration
///
public bool HideTooltipOnCursorLeave { get; set; } = false;
+ ///
+ /// Gets or sets the value indicating whether the library should validate CSS class names.
+ /// respecting the following regex: "^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$".
+ /// Default is true.
+ ///
+ public bool ValidateClassNames
+ {
+ get => Utilities.CssBuilder.ValidateClassNames;
+ set => Utilities.CssBuilder.ValidateClassNames = value;
+ }
+
public LibraryConfiguration()
{
}
diff --git a/src/Core/Utilities/CssBuilder.cs b/src/Core/Utilities/CssBuilder.cs
index 775d24bb97..5e116e9a9b 100644
--- a/src/Core/Utilities/CssBuilder.cs
+++ b/src/Core/Utilities/CssBuilder.cs
@@ -8,6 +8,14 @@ public readonly partial struct CssBuilder
private readonly string[]? _userClasses;
private static readonly Regex ValidClassNameRegex = GenerateValidClassNameRegex();
+ ///
+ /// Validate CSS class, which must respect the following regex: "^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$".
+ /// Default is true.
+ ///
+ public static bool ValidateClassNames = true;
+
+ private readonly bool _validateClassNames = ValidateClassNames;
+
///
/// Initializes a new instance of the class.
///
@@ -17,6 +25,14 @@ public CssBuilder()
_userClasses = null;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal CssBuilder(bool validateClassNames, string? userClasses) : this(userClasses)
+ {
+ _validateClassNames = validateClassNames;
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -84,9 +100,9 @@ public CssBuilder AddClass(string? values)
///
/// CSS class name to validate
/// True if valid, otherwise false
- private static bool IsValidClassName(string className)
+ private bool IsValidClassName(string className)
{
- return ValidClassNameRegex.IsMatch(className);
+ return _validateClassNames ? ValidClassNameRegex.IsMatch(className) : true;
}
///
@@ -94,7 +110,7 @@ private static bool IsValidClassName(string className)
///
/// Space-separated CSS Classes
/// Enumerable of valid class names
- private static IEnumerable SplitAndValidate(string input)
+ private IEnumerable SplitAndValidate(string input)
{
return input.Split(' ', StringSplitOptions.RemoveEmptyEntries).Where(IsValidClassName);
}
diff --git a/tests/Core/Utilities/CssBuilderTests.cs b/tests/Core/Utilities/CssBuilderTests.cs
index 7c87845195..3f38b8359c 100644
--- a/tests/Core/Utilities/CssBuilderTests.cs
+++ b/tests/Core/Utilities/CssBuilderTests.cs
@@ -179,4 +179,25 @@ public void CssBuilder_CombinesValidUserAndAddedClasses()
// Assert
Assert.Equal("added-class user-class", cssBuilder.Build());
}
+
+ [Theory]
+ [InlineData("min-h-[16px] user-class", "min-h-[16px] ")]
+ [InlineData("bg-red-500/50 user-class", " bg-red-500/50")]
+ [InlineData("bg-[#ff0000] user-class", " bg-[#ff0000] ")]
+ [InlineData("a:hover user-class", "a:hover")]
+ [InlineData("min-h-[16px] a:hover user-class", "min-h-[16px]", "a:hover")]
+ public void CssBuilder_ValidateClassNames_AcceptInvalid(string expected, params string[] value)
+ {
+ // Arrange
+ var cssBuilder = new CssBuilder(validateClassNames: false, userClasses: "user-class");
+
+ // Act
+ foreach (var item in value)
+ {
+ cssBuilder.AddClass(item);
+ }
+
+ // Assert
+ Assert.Equal(expected, cssBuilder.Build());
+ }
}