Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@namespace Bit.BlazorUI
@namespace Bit.BlazorUI
@inherits BitComponentBase

<div @ref="RootElement" @attributes="HtmlAttributes"
Expand All @@ -19,7 +19,10 @@
type="button"
style="@Styles?.DismissButton"
class="bit-snb-cbt @Classes?.DismissButton">
<i style="@Styles?.DismissIcon" class="bit-icon bit-icon--@(DismissIconName ?? "Cancel") @Classes?.DismissIcon" />
@{
var dismissIcon = BitIconInfo.From(DismissIcon, DismissIconName ?? "Cancel");
}
<i style="@Styles?.DismissIcon" class="@dismissIcon?.GetCssClasses() @Classes?.DismissIcon" />
</button>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public partial class BitSnackBar : BitComponentBase
/// </summary>
[Parameter] public BitSnackBarClassStyles? Classes { get; set; }

/// <summary>
/// The icon of the dismiss button.
/// </summary>
[Parameter] public BitIconInfo? DismissIcon { get; set; }

/// <summary>
/// The icon name of the dismiss button.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/components/snackbar"
@page "/components/snackbar"

<PageOutlet Url="components/snackbar"
Title="Snackbar"
Expand Down Expand Up @@ -114,7 +114,36 @@
<BitButton OnClick="OpenBodyTemplate">Body Template</BitButton>
</DemoExample>

<DemoExample Title="Style & Class" RazorCode="@example5RazorCode" CsharpCode="@example5CsharpCode" Id="example5">
<DemoExample Title="External Icons" RazorCode="@example5RazorCode" CsharpCode="@example5CsharpCode" Id="example5">
<div>
Use icons from external libraries like FontAwesome and Bootstrap Icons with the <b>DismissIcon</b> parameter.
</div>

<br /><br />

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" />

<div>FontAwesome:</div>
<br />
<BitSnackBar @ref="dismissIconFaRef" DismissIcon="@BitIconInfo.Fa("solid xmark")" />
<BitButton OnClick="OpenDismissIconFa">FontAwesome dismiss icon</BitButton>
<br /><br />
<BitSnackBar @ref="dismissIconCssRef" DismissIcon="@BitIconInfo.Css("fa-solid fa-x")" />
<BitButton OnClick="OpenDismissIconCss">CSS classes dismiss icon</BitButton>
<br /><br /><br /><br />

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" />

<div>Bootstrap:</div>
<br />
<BitSnackBar @ref="dismissIconBiRef" DismissIcon="@BitIconInfo.Bi("x-lg")" />
<BitButton OnClick="OpenDismissIconBi">Bootstrap dismiss icon</BitButton>
<br /><br />
<BitSnackBar @ref="dismissIconImplicitRef" DismissIcon="@("bi bi-x-circle")" />
<BitButton OnClick="OpenDismissIconImplicit">Implicit CSS dismiss icon</BitButton>
</DemoExample>

<DemoExample Title="Style & Class" RazorCode="@example6RazorCode" CsharpCode="@example6CsharpCode" Id="example6">
<div>
<div>Item's Style & Class:</div><br />
<BitSnackBar @ref="snackBarStyleRef" />
Expand All @@ -126,13 +155,13 @@
<div>Styles & Classes:</div><br />
<BitSnackBar @ref="snackBarStylesRef"
Styles="@(new() { Container = "width: 16rem; background-color: purple;",
Header = "background-color: rebeccapurple; padding: 0.2rem;" })" />
<BitButton OnClick="OpenSnackBarStyles">Custom styles</BitButton>
<br /><br />
Header = "background-color: rebeccapurple; padding: 0.2rem;" })" />
<BitButton OnClick="OpenSnackBarStyles">Custom styles</BitButton>
<br /><br />
<BitSnackBar @ref="snackBarClassesRef" AutoDismiss
Classes="@(new() { Container = "custom-container",
ProgressBar = "custom-progress" })" />
ProgressBar = "custom-progress" })" />
<BitButton OnClick="OpenSnackBarClasses">Custom classes</BitButton>
</div>
</DemoExample>
</DemoPage>
</div>
</DemoExample>
</DemoPage>
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ public partial class BitSnackBarDemo
Href = "#class-styles",
},
new()
{
Name = "DismissIcon",
Type = "BitIconInfo?",
DefaultValue = "null",
Description = "Gets or sets the icon of the dismiss button using custom CSS classes for external icon libraries. Takes precedence over DismissIconName when both are set.",
LinkType = LinkType.Link,
Href = "#bit-icon-info",
},
new()
{
Name = "DismissIconName",
Type = "string?",
DefaultValue = "null",
Description = "The icon name of the dismiss button.",
Description = "The icon name of the dismiss button from the built-in Fluent UI icons.",
},
new()
{
Expand Down Expand Up @@ -243,6 +252,35 @@ public partial class BitSnackBarDemo

private readonly List<ComponentSubClass> 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."
},
]
},
new()
{
Id = "class-styles",
Expand Down Expand Up @@ -501,6 +539,32 @@ private async Task OpenCustomizationSnackBar()
}


private BitSnackBar dismissIconFaRef = default!;
private BitSnackBar dismissIconCssRef = default!;
private BitSnackBar dismissIconBiRef = default!;
private BitSnackBar dismissIconImplicitRef = default!;

private async Task OpenDismissIconFa()
{
await dismissIconFaRef.Info("Notification", "Click the FontAwesome dismiss icon to close.");
}

private async Task OpenDismissIconCss()
{
await dismissIconCssRef.Info("Notification", "Click the CSS class dismiss icon to close.");
}

private async Task OpenDismissIconBi()
{
await dismissIconBiRef.Info("Notification", "Click the Bootstrap dismiss icon to close.");
}

private async Task OpenDismissIconImplicit()
{
await dismissIconImplicitRef.Info("Notification", "Click the implicit CSS dismiss icon to close.");
}


private BitSnackBar snackBarStyleRef = default!;
private BitSnackBar snackBarClassRef = default!;
private BitSnackBar snackBarStylesRef = default!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,49 @@ private async Task OpenBodyTemplate()
}";

private readonly string example5RazorCode = @"
<link rel=""stylesheet"" href=""https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css"" />

<BitSnackBar @ref=""dismissIconFaRef"" DismissIcon=""@BitIconInfo.Fa(""solid xmark"")""/>
<BitButton OnClick=""OpenDismissIconFa"">FontAwesome dismiss icon</BitButton>

<BitSnackBar @ref=""dismissIconCssRef"" DismissIcon=""@BitIconInfo.Css(""fa-solid fa-x"")""/>
<BitButton OnClick=""OpenDismissIconCss"">CSS classes dismiss icon</BitButton>


<link rel=""stylesheet"" href=""https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"" />

<BitSnackBar @ref=""dismissIconBiRef"" DismissIcon=""@BitIconInfo.Bi(""x-lg"")""/>
<BitButton OnClick=""OpenDismissIconBi"">Bootstrap dismiss icon</BitButton>

<BitSnackBar @ref=""dismissIconImplicitRef"" DismissIcon=""@(""bi bi-x-circle"")""/>
<BitButton OnClick=""OpenDismissIconImplicit"">Implicit CSS dismiss icon</BitButton>";
private readonly string example5CsharpCode = @"
private BitSnackBar dismissIconFaRef = default!;
private BitSnackBar dismissIconCssRef = default!;
private BitSnackBar dismissIconBiRef = default!;
private BitSnackBar dismissIconImplicitRef = default!;

private async Task OpenDismissIconFa()
{
await dismissIconFaRef.Info(""Notification"", ""Click the FontAwesome dismiss icon to close."");
}

private async Task OpenDismissIconCss()
{
await dismissIconCssRef.Info(""Notification"", ""Click the CSS class dismiss icon to close."");
}

private async Task OpenDismissIconBi()
{
await dismissIconBiRef.Info(""Notification"", ""Click the Bootstrap dismiss icon to close."");
}

private async Task OpenDismissIconImplicit()
{
await dismissIconImplicitRef.Info(""Notification"", ""Click the implicit CSS dismiss icon to close."");
}";

private readonly string example6RazorCode = @"
<style>
.custom-class {
background-color: tomato;
Expand Down Expand Up @@ -181,7 +224,7 @@ private async Task OpenBodyTemplate()
Classes=""@(new() { Container = ""custom-container"",
ProgressBar = ""custom-progress"" })"" />
<BitButton OnClick=""OpenSnackBarClasses"">Custom classes</BitButton>";
private readonly string example5CsharpCode = @"
private readonly string example6CsharpCode = @"
private BitSnackBar snackBarStyleRef = default!;
private BitSnackBar snackBarClassRef = default!;
private BitSnackBar snackBarStylesRef = default!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,116 @@ public async Task BitSnackBarDismissIconNameTest(string title, string iconName)
Assert.IsTrue(closeButtonIcon.ClassList.Contains($"bit-icon--{iconName}"));
}

[TestMethod,
DataRow("title", "fa-solid fa-xmark"),
DataRow("title", "bi bi-x-lg")
]
public async Task BitSnackBarDismissIconParameterWithCssClassesTest(string title, string cssClasses)
{
var com = RenderComponent<BitSnackBar>(
parameters =>
{
parameters.Add(x => x.DismissIcon, (BitIconInfo)cssClasses!);
}
);

await com.Instance.Show(title);

var closeButtonIcon = com.Find(".bit-snb-cbt > i");

var classes = cssClasses.Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var cls in classes)
{
Assert.IsTrue(closeButtonIcon.ClassList.Contains(cls), $"Dismiss icon should contain class '{cls}'");
}
}

[TestMethod,
DataRow("title")
]
public async Task BitSnackBarDismissIconInfoCssHelperTest(string title)
{
var com = RenderComponent<BitSnackBar>(
parameters =>
{
parameters.Add(x => x.DismissIcon, BitIconInfo.Css("fa-solid fa-xmark"));
}
);

await com.Instance.Show(title);

var closeButtonIcon = com.Find(".bit-snb-cbt > i");

Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-solid"));
Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-xmark"));
}

[TestMethod,
DataRow("title")
]
public async Task BitSnackBarDismissIconInfoFaHelperTest(string title)
{
var com = RenderComponent<BitSnackBar>(
parameters =>
{
parameters.Add(x => x.DismissIcon, BitIconInfo.Fa("solid xmark"));
}
);

await com.Instance.Show(title);

var closeButtonIcon = com.Find(".bit-snb-cbt > i");

Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-solid"));
Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-xmark"));
}

[TestMethod,
DataRow("title")
]
public async Task BitSnackBarDismissIconInfoBiHelperTest(string title)
{
var com = RenderComponent<BitSnackBar>(
parameters =>
{
parameters.Add(x => x.DismissIcon, BitIconInfo.Bi("x-lg"));
}
);

await com.Instance.Show(title);

var closeButtonIcon = com.Find(".bit-snb-cbt > i");

Assert.IsTrue(closeButtonIcon.ClassList.Contains("bi"));
Assert.IsTrue(closeButtonIcon.ClassList.Contains("bi-x-lg"));
}

[TestMethod,
DataRow("title")
]
public async Task BitSnackBarDismissIconTakesPrecedenceOverDismissIconNameTest(string title)
{
var com = RenderComponent<BitSnackBar>(
parameters =>
{
parameters.Add(x => x.DismissIcon, BitIconInfo.Fa("solid xmark"));
parameters.Add(x => x.DismissIconName, "Cancel");
}
);

await com.Instance.Show(title);

var closeButtonIcon = com.Find(".bit-snb-cbt > i");

// DismissIcon should take precedence
Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-solid"));
Assert.IsTrue(closeButtonIcon.ClassList.Contains("fa-xmark"));

// Should not contain DismissIconName classes
Assert.IsFalse(closeButtonIcon.ClassList.Contains("bit-icon"));
Assert.IsFalse(closeButtonIcon.ClassList.Contains("bit-icon--Cancel"));
}

[TestMethod,
DataRow("title")
]
Expand Down
Loading