diff --git a/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/BrandBar.razor b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/BrandBar.razor
new file mode 100644
index 0000000..bc8cbd1
--- /dev/null
+++ b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/BrandBar.razor
@@ -0,0 +1,11 @@
+@* Components/BrandBar.razor *@
+
+ @if (Logo is not null) { @Logo }
+ else { ▮ }
+ @Product
+
+
+@code {
+ [Parameter, EditorRequired] public string Product { get; set; } = string.Empty;
+ [Parameter] public RenderFragment? Logo { get; set; }
+}
diff --git a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/BrandBarTests.cs b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/BrandBarTests.cs
new file mode 100644
index 0000000..40b6774
--- /dev/null
+++ b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/BrandBarTests.cs
@@ -0,0 +1,22 @@
+namespace ZB.MOM.WW.Theme.Tests;
+
+public class BrandBarTests : TestContext
+{
+ [Fact]
+ public void Renders_product_with_default_mark()
+ {
+ var cut = RenderComponent(p => p.Add(x => x.Product, "OtOpcUa"));
+ Assert.Contains("OtOpcUa", cut.Markup);
+ Assert.NotNull(cut.Find(".brand .mark")); // default glyph when no Logo
+ }
+
+ [Fact]
+ public void Custom_logo_replaces_default_mark()
+ {
+ var cut = RenderComponent(p => p
+ .Add(x => x.Product, "ScadaBridge")
+ .Add(x => x.Logo, (RenderFragment)(b => b.AddMarkupContent(0, "
"))));
+ Assert.NotNull(cut.Find(".brand .logo"));
+ Assert.Empty(cut.FindAll(".brand .mark"));
+ }
+}
diff --git a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/_Imports.cs b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/_Imports.cs
index 0dedb18..e196a6c 100644
--- a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/_Imports.cs
+++ b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/_Imports.cs
@@ -1,4 +1,5 @@
global using Bunit;
global using Xunit;
+global using Microsoft.AspNetCore.Components;
global using ZB.MOM.WW.Theme;
global using ZB.MOM.WW.Theme.Components;