diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
index 19a770feef..3d08fa5b1b 100644
--- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
+++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
@@ -55,6 +55,15 @@
Gets or sets a callback when a accordion item is changed.
+
+
+
+
+
+
+
+
+
Gets or sets the owning FluentTreeView.
@@ -74,6 +83,11 @@
If both are set, this parameter will not be used.
+
+
+ Gets or sets the tooltip for the heading of the accordion item.
+
+
Gets or sets a value indicating whether the item is expanded or collapsed.
diff --git a/examples/Demo/Shared/Pages/Accordion/Examples/AccordionDefault.razor b/examples/Demo/Shared/Pages/Accordion/Examples/AccordionDefault.razor
index 1eb5c0be29..a29209dbc4 100644
--- a/examples/Demo/Shared/Pages/Accordion/Examples/AccordionDefault.razor
+++ b/examples/Demo/Shared/Pages/Accordion/Examples/AccordionDefault.razor
@@ -10,10 +10,10 @@
Panel two content, using the 'end' slot for extra header content
-
+
Panel three content
-
+
Panel Four
diff --git a/src/Core/Components/Accordion/FluentAccordionItem.razor.cs b/src/Core/Components/Accordion/FluentAccordionItem.razor.cs
index ba3a603d71..9e16762560 100644
--- a/src/Core/Components/Accordion/FluentAccordionItem.razor.cs
+++ b/src/Core/Components/Accordion/FluentAccordionItem.razor.cs
@@ -3,11 +3,26 @@
// ------------------------------------------------------------------------
using Microsoft.AspNetCore.Components;
+using Microsoft.FluentUI.AspNetCore.Components.Extensions;
+using Microsoft.JSInterop;
namespace Microsoft.FluentUI.AspNetCore.Components;
public partial class FluentAccordionItem : FluentComponentBase, IDisposable
{
+ private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/Accordion/FluentAccordionItem.razor.js";
+
+ ///
+ [Inject]
+ private LibraryConfiguration LibraryConfiguration { get; set; } = default!;
+
+ ///
+ [Inject]
+ private IJSRuntime JSRuntime { get; set; } = default!;
+
+ ///
+ private IJSObjectReference? Module { get; set; }
+
///
/// Gets or sets the owning FluentTreeView.
///
@@ -30,6 +45,12 @@ public partial class FluentAccordionItem : FluentComponentBase, IDisposable
[Parameter]
public RenderFragment? HeadingTemplate { get; set; }
+ ///
+ /// Gets or sets the tooltip for the heading of the accordion item.
+ ///
+ [Parameter]
+ public string? HeadingTooltip { get; set; }
+
///
/// Gets or sets a value indicating whether the item is expanded or collapsed.
///
@@ -65,6 +86,18 @@ protected override void OnInitialized()
Owner?.Register(this);
}
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender)
+ {
+ if (HeadingTooltip != null && !string.IsNullOrEmpty(Id))
+ {
+ Module ??= await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration));
+ await Module.InvokeVoidAsync("setControlAttribute", Id, "title", HeadingTooltip);
+ }
+ }
+ }
+
private async Task HandleOnAccordionItemChangedAsync(AccordionChangeEventArgs args)
{
if (args is not null)
diff --git a/src/Core/Components/Accordion/FluentAccordionItem.razor.js b/src/Core/Components/Accordion/FluentAccordionItem.razor.js
new file mode 100644
index 0000000000..aa32ffb2cf
--- /dev/null
+++ b/src/Core/Components/Accordion/FluentAccordionItem.razor.js
@@ -0,0 +1,7 @@
+export function setControlAttribute(id, attrName, value) {
+ const fieldElement = document.querySelector("#" + id)?.shadowRoot?.querySelector("[part='button']");
+
+ if (!!fieldElement) {
+ fieldElement?.setAttribute(attrName, value);
+ }
+}
diff --git a/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingAndTooltip.verified.html b/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingAndTooltip.verified.html
new file mode 100644
index 0000000000..8bd07513d5
--- /dev/null
+++ b/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingAndTooltip.verified.html
@@ -0,0 +1,4 @@
+
+
+ custom heading value
+
\ No newline at end of file
diff --git a/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingTemplateAndTooltip.verified.html b/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingTemplateAndTooltip.verified.html
new file mode 100644
index 0000000000..cf16a7fb55
--- /dev/null
+++ b/tests/Core/Accordion/FluentAccordionItemTests.FluentAccordionItem_WithHeadingTemplateAndTooltip.verified.html
@@ -0,0 +1,4 @@
+
+
+ custom heading content
+
\ No newline at end of file
diff --git a/tests/Core/Accordion/FluentAccordionItemTests.cs b/tests/Core/Accordion/FluentAccordionItemTests.cs
index cc8c934efe..082e8711bf 100644
--- a/tests/Core/Accordion/FluentAccordionItemTests.cs
+++ b/tests/Core/Accordion/FluentAccordionItemTests.cs
@@ -3,17 +3,32 @@
// ------------------------------------------------------------------------
using Bunit;
+using Microsoft.AspNetCore.Components;
+using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Microsoft.FluentUI.AspNetCore.Components.Tests.Accordion;
-public class FluentAccordionItemTests : TestBase
+public class FluentAccordionItemTests : TestContext
{
+ private const string FluentAccordionItemRazorJs = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/Accordion/FluentAccordionItem.razor.js";
+
+ [Inject]
+ private LibraryConfiguration LibraryConfiguration { get; set; } = new LibraryConfiguration();
+
+ public FluentAccordionItemTests()
+ {
+ var script = JSInterop.SetupModule(FluentAccordionItemRazorJs);
+ script.SetupVoid("setControlAttribute", _ => true);
+
+ Services.AddSingleton(LibraryConfiguration.ForUnitTests);
+ }
+
[Fact]
public void FluentAccordionItem_WithChildContent_IsNull()
{
// Arrange & Act
- var cut = TestContext.RenderComponent();
+ var cut = RenderComponent();
// Assert
cut.Verify();
@@ -23,7 +38,7 @@ public void FluentAccordionItem_WithChildContent_IsNull()
public void FluentAccordionItem_WithProvided_Content()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.AddChildContent("child content");
});
@@ -35,8 +50,9 @@ public void FluentAccordionItem_WithProvided_Content()
[Fact]
public void FluentAccordionItem_WithCustomHeaderValue()
{
+
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Heading, "custom heading value");
});
@@ -49,7 +65,7 @@ public void FluentAccordionItem_WithCustomHeaderValue()
public void FluentAccordionItem_WithHeadingTemplateAndHeading_IsProvidedBoth()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.HeadingTemplate, context =>
{
@@ -63,13 +79,45 @@ public void FluentAccordionItem_WithHeadingTemplateAndHeading_IsProvidedBoth()
cut.Verify();
}
+ [Fact]
+ public void FluentAccordionItem_WithHeadingAndTooltip()
+ {
+ // Arrange & Act
+ var cut = RenderComponent(parameters =>
+ {
+ parameters.Add(p => p.Heading, "custom heading value");
+ parameters.Add(p => p.HeadingTooltip, "my tooltip");
+ });
+
+ // Assert
+ cut.Verify();
+ }
+
+ [Fact]
+ public void FluentAccordionItem_WithHeadingTemplateAndTooltip()
+ {
+ // Arrange & Act
+ var cut = RenderComponent(parameters =>
+ {
+ parameters.Add(p => p.HeadingTemplate, context =>
+ {
+ context.AddContent(0, "custom heading content");
+ });
+
+ parameters.Add(p => p.HeadingTooltip, "my tooltip");
+ });
+
+ // Assert
+ cut.Verify();
+ }
+
[Theory]
[InlineData(true)]
[InlineData(false)]
public void FluentAccordionItem_WithProvidedExpanded_Parameter(bool expanded)
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Expanded, expanded);
});
@@ -82,7 +130,7 @@ public void FluentAccordionItem_WithProvidedExpanded_Parameter(bool expanded)
public void FluentAccordionItem_WithAnAdditionalAttribute()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.AddUnmatched("unknown", "unknowns-value");
});
@@ -95,7 +143,7 @@ public void FluentAccordionItem_WithAnAdditionalAttribute()
public void FluentAccordionItem_WithMultipleAdditionalAttributes()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.AddUnmatched("unknown1", "unknown1s-value");
parameters.AddUnmatched("unknown2", "unknown2s-value");
@@ -109,7 +157,7 @@ public void FluentAccordionItem_WithMultipleAdditionalAttributes()
public void FluentAccordionItem_WhenAllParamsAdded_AndAdditionalAttributes_AndContent()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Expanded, true);
parameters.Add(p => p.Heading, "custom heading value");
@@ -126,7 +174,7 @@ public void FluentAccordionItem_WhenAllParamsAdded_AndAdditionalAttributes_AndCo
public void FluentAccordionItem_WhenAdditionalCSSClass_IsProvided()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Class, "additional-class");
});
@@ -139,7 +187,7 @@ public void FluentAccordionItem_WhenAdditionalCSSClass_IsProvided()
public void FluentAccordionItem_WhenAdditionalStyle_IsProvided()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Style, "background-color: grey");
});
@@ -152,7 +200,7 @@ public void FluentAccordionItem_WhenAdditionalStyle_IsProvided()
public void FluentAccordionItem_WithHeadingTemplate_IsNull()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.HeadingTemplate, context => { });
});
@@ -165,7 +213,7 @@ public void FluentAccordionItem_WithHeadingTemplate_IsNull()
public void FluentAccordionItem_WithHeadingTemplate_IsProvided()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.HeadingTemplate, context =>
{
diff --git a/tests/Core/Accordion/FluentAccordionTests.cs b/tests/Core/Accordion/FluentAccordionTests.cs
index 55eb87cf7a..013c5b7a53 100644
--- a/tests/Core/Accordion/FluentAccordionTests.cs
+++ b/tests/Core/Accordion/FluentAccordionTests.cs
@@ -3,17 +3,23 @@
// ------------------------------------------------------------------------
using Bunit;
+using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Microsoft.FluentUI.AspNetCore.Components.Tests.Accordion;
-public class FluentAccordionTests : TestBase
+public class FluentAccordionTests : TestContext
{
+ public FluentAccordionTests()
+ {
+ Services.AddSingleton(LibraryConfiguration.ForUnitTests);
+ }
+
[Fact]
public void FluentAccordion_When_ChildContent_IsNull()
{
// Arrange & Act
- var cut = TestContext.RenderComponent();
+ var cut = RenderComponent();
// Assert
cut.Verify();
@@ -23,7 +29,7 @@ public void FluentAccordion_When_ChildContent_IsNull()
public void FluentAccordion_TheDefaultExpandMode_WhenExpandMode_IsNotSpecified()
{
// Arrange & Act
- var cut = TestContext.RenderComponent();
+ var cut = RenderComponent();
// Assert
cut.Verify();
@@ -35,7 +41,7 @@ public void FluentAccordion_TheDefaultExpandMode_WhenExpandMode_IsNotSpecified()
public void FluentAccordion_WhenExpandMode_IsSpecified(AccordionExpandMode accordionExpandMode)
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.ExpandMode, accordionExpandMode);
});
@@ -48,7 +54,7 @@ public void FluentAccordion_WhenExpandMode_IsSpecified(AccordionExpandMode accor
public void FluentAccordion_WhenAdditionalCSSClass_IsProvided()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Class, "additional-class");
});
@@ -61,7 +67,7 @@ public void FluentAccordion_WhenAdditionalCSSClass_IsProvided()
public void FluentAccordion_WhenAdditionalStyle_IsProvided()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.Style, "background-color: grey");
});
@@ -74,7 +80,7 @@ public void FluentAccordion_WhenAdditionalStyle_IsProvided()
public void FluentAccordion_WhenAdditionalParameters_AreAdded()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.AddUnmatched("unmatched1", "unmatched1-value");
parameters.AddUnmatched("unmatched2", "unmatched2-value");
@@ -88,7 +94,7 @@ public void FluentAccordion_WhenAdditionalParameters_AreAdded()
public void FluentAccordion_WhenExpandedModeIsSingle_AndMultipleItemAreExpanded_ByDefault()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.ExpandMode, AccordionExpandMode.Single);
parameters.AddChildContent(itemParams => itemParams.Add(p => p.Expanded, true));
@@ -103,14 +109,14 @@ public void FluentAccordion_WhenExpandedModeIsSingle_AndMultipleItemAreExpanded_
public void FluentAccordion_Dispose()
{
// Arrange & Act
- var cut = TestContext.RenderComponent(parameters =>
+ var cut = RenderComponent(parameters =>
{
parameters.Add(p => p.ExpandMode, AccordionExpandMode.Single);
parameters.AddChildContent(itemParams => itemParams.Add(p => p.Expanded, true));
parameters.AddChildContent(itemParams => itemParams.Add(p => p.Expanded, true));
});
- TestContext.DisposeComponents();
+ DisposeComponents();
// Assert
Assert.True(cut.IsDisposed);