diff --git a/src/MudBlazor.Docs/Pages/Components/Stack/Examples/StackBreakpointExample.razor b/src/MudBlazor.Docs/Pages/Components/Stack/Examples/StackBreakpointExample.razor
new file mode 100644
index 000000000000..be144f686927
--- /dev/null
+++ b/src/MudBlazor.Docs/Pages/Components/Stack/Examples/StackBreakpointExample.razor
@@ -0,0 +1,28 @@
+@namespace MudBlazor.Docs.Examples
+
+
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+
+
+
+
+
+ @foreach (var value in Enum.GetValues(typeof(Breakpoint)).Cast()){
+ @value
+ }
+
+
+
+
+
+@code {
+ private Breakpoint _breakpoint = Breakpoint.None;
+ private bool _row = false;
+ private bool _reverse = false;
+}
\ No newline at end of file
diff --git a/src/MudBlazor.Docs/Pages/Components/Stack/StackPage.razor b/src/MudBlazor.Docs/Pages/Components/Stack/StackPage.razor
index 1abee50448c2..7dfc33fa9e26 100644
--- a/src/MudBlazor.Docs/Pages/Components/Stack/StackPage.razor
+++ b/src/MudBlazor.Docs/Pages/Components/Stack/StackPage.razor
@@ -24,6 +24,15 @@
+
+
+ With the @nameof(MudStack.Breakpoint) property set, the state of the @nameof(MudStack.Row) property will be reversed based on the defined screen size breakpoint. For example, when set to a specific breakpoint such as @nameof(Breakpoint.Md), the row state is reversed at that screen size. If set to a range like @nameof(Breakpoint.MdAndUp), the row state will be reversed for all screen sizes greater than or equal to the specified breakpoint.
+
+
+
+
+
+
The default spacing can be changed by setting any number between 0 and 16 with the @nameof(MudStack.Spacing) property.
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseRowTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseRowTest.razor
new file mode 100644
index 000000000000..aa9ce80914ab
--- /dev/null
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseRowTest.razor
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseTest.razor
new file mode 100644
index 000000000000..e4331ed246bd
--- /dev/null
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointReverseTest.razor
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointRowTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointRowTest.razor
new file mode 100644
index 000000000000..73731a283b2d
--- /dev/null
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointRowTest.razor
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointTest.razor
new file mode 100644
index 000000000000..d6bd541241d5
--- /dev/null
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/Stack/BreakpointTest.razor
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MudBlazor.UnitTests/Components/StackTests.cs b/src/MudBlazor.UnitTests/Components/StackTests.cs
index b39a422f3a18..d8ce2594e5e8 100644
--- a/src/MudBlazor.UnitTests/Components/StackTests.cs
+++ b/src/MudBlazor.UnitTests/Components/StackTests.cs
@@ -82,6 +82,124 @@ public void CheckSpacingClass(int spacing)
stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", "flex-column", $"gap-{spacing}" });
}
+ [Test]
+ [TestCase(Breakpoint.None)]
+ [TestCase(Breakpoint.Always)]
+ [TestCase(Breakpoint.Xs)]
+ [TestCase(Breakpoint.Sm)]
+ [TestCase(Breakpoint.Md)]
+ [TestCase(Breakpoint.Lg)]
+ [TestCase(Breakpoint.Xl)]
+ [TestCase(Breakpoint.Xxl)]
+ [TestCase(Breakpoint.SmAndDown)]
+ [TestCase(Breakpoint.MdAndDown)]
+ [TestCase(Breakpoint.LgAndDown)]
+ [TestCase(Breakpoint.XlAndDown)]
+ [TestCase(Breakpoint.SmAndUp)]
+ [TestCase(Breakpoint.MdAndUp)]
+ [TestCase(Breakpoint.LgAndUp)]
+ [TestCase(Breakpoint.XlAndUp)]
+ [TestCase(Breakpoint.None, true)]
+ [TestCase(Breakpoint.Always, true)]
+ [TestCase(Breakpoint.Xs, true)]
+ [TestCase(Breakpoint.Sm, true)]
+ [TestCase(Breakpoint.Md, true)]
+ [TestCase(Breakpoint.Lg, true)]
+ [TestCase(Breakpoint.Xl, true)]
+ [TestCase(Breakpoint.Xxl, true)]
+ [TestCase(Breakpoint.SmAndDown, true)]
+ [TestCase(Breakpoint.MdAndDown, true)]
+ [TestCase(Breakpoint.LgAndDown, true)]
+ [TestCase(Breakpoint.XlAndDown, true)]
+ [TestCase(Breakpoint.SmAndUp, true)]
+ [TestCase(Breakpoint.MdAndUp, true)]
+ [TestCase(Breakpoint.LgAndUp, true)]
+ [TestCase(Breakpoint.XlAndUp, true)]
+ [TestCase(Breakpoint.None, true, true)]
+ [TestCase(Breakpoint.Always, true, true)]
+ [TestCase(Breakpoint.Xs, true, true)]
+ [TestCase(Breakpoint.Sm, true, true)]
+ [TestCase(Breakpoint.Md, true, true)]
+ [TestCase(Breakpoint.Lg, true, true)]
+ [TestCase(Breakpoint.Xl, true, true)]
+ [TestCase(Breakpoint.Xxl, true, true)]
+ [TestCase(Breakpoint.SmAndDown, true, true)]
+ [TestCase(Breakpoint.MdAndDown, true, true)]
+ [TestCase(Breakpoint.LgAndDown, true, true)]
+ [TestCase(Breakpoint.XlAndDown, true, true)]
+ [TestCase(Breakpoint.SmAndUp, true, true)]
+ [TestCase(Breakpoint.MdAndUp, true, true)]
+ [TestCase(Breakpoint.LgAndUp, true, true)]
+ [TestCase(Breakpoint.XlAndUp, true, true)]
+ public void CheckBreakpointClass(Breakpoint breakpoint, bool row = false, bool reverse = false)
+ {
+ var stack = Context.RenderComponent(x => x.Add(c => c.Breakpoint, breakpoint).Add(c => c.Row, row).Add(c => c.Reverse, reverse));
+
+ // Get the Default and Reverse States
+ string defaultState = (row ? "row" : "column") + (reverse ? "-reverse" : string.Empty);
+ string reverseState = (row ? "column" : "row") + (reverse ? "-reverse" : string.Empty);
+
+ // Get the Stack Class
+ var stackClass = stack.Find(".d-flex");
+
+ // Handle Special Cases
+ switch (breakpoint)
+ {
+ // If the Breakpoint is None or Always, return the default direction
+ case Breakpoint.None: // If breakpoint is None, return the default direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Always: // If breakpoint is Always, return the reverse direction, honestly the user should just use the Row Property
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", "gap-3" });
+ break;
+ case Breakpoint.Xs: // Xs is Reverse Direction, Sm and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", $"flex-sm-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Sm: // Xs is Default Direction, Sm is Reverse Direction, Md and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-sm-{reverseState}", $"flex-md-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Md: // Xs to Sm is Default Direction, Md is Reverse Direction, Lg and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-md-{reverseState}", $"flex-lg-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Lg: // Xs to Md is Default Direction, Lg is Reverse Direction, Xl and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-lg-{reverseState}", $"flex-xl-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Xl: // Xs to Lg is Default Direction, Xl is Reverse Direction, Xxl is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-xl-{reverseState}", $"flex-xxl-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.Xxl: // Xs to Xl is Default Direction, Xxl is Reverse Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-xxl-{reverseState}", "gap-3" });
+ break;
+ case Breakpoint.SmAndDown: // Sm and Down is Reverse Direction, Md and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", $"flex-md-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.MdAndDown: // Md and Down is Reverse Direction, Lg and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", $"flex-lg-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.LgAndDown: // Lg and Down is Reverse Direction, Xl and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", $"flex-xl-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.XlAndDown: // Xl and Down is Reverse Direction, Xxl and Up is Default Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{reverseState}", $"flex-xxl-{defaultState}", "gap-3" });
+ break;
+ case Breakpoint.SmAndUp: // Xs is Default Direction, Sm and Up is Reverse Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-sm-{reverseState}", "gap-3" });
+ break;
+ case Breakpoint.MdAndUp: // Xs to Sm is Default Direction, Md and Up is Reverse Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-md-{reverseState}", "gap-3" });
+ break;
+ case Breakpoint.LgAndUp: // Xs to Md is Default Direction, Lg and Up is Reverse Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-lg-{reverseState}", "gap-3" });
+ break;
+ case Breakpoint.XlAndUp: // Xs to Lg is Default Direction, Xl and Up is Reverse Direction
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", $"flex-xl-{reverseState}", "gap-3" });
+ break;
+ default: // Return the default direction if no Breakpoint is Matched
+ stackClass.ClassList.Should().ContainInOrder(new[] { "d-flex", $"flex-{defaultState}", "gap-3" });
+ break;
+ }
+ }
+
[Test]
[TestCase(Justify.FlexStart, "start")]
[TestCase(Justify.Center, "center")]
diff --git a/src/MudBlazor/Components/Stack/MudStack.razor.cs b/src/MudBlazor/Components/Stack/MudStack.razor.cs
index 32157b89f4f4..20dd1c9961b4 100644
--- a/src/MudBlazor/Components/Stack/MudStack.razor.cs
+++ b/src/MudBlazor/Components/Stack/MudStack.razor.cs
@@ -16,7 +16,7 @@ public partial class MudStack : MudComponentBase
{
protected string Classname =>
new CssBuilder("d-flex")
- .AddClass($"flex-{(Row ? "row" : "column")}{(Reverse ? "-reverse" : string.Empty)}")
+ .AddClass(getFlexDirection())
.AddClass($"justify-{Justify?.ToDescriptionString()}", Justify is not null)
.AddClass($"align-{AlignItems?.ToDescriptionString()}", AlignItems is not null)
.AddClass($"flex-{Wrap?.ToDescriptionString()}", Wrap is not null)
@@ -25,6 +25,67 @@ public partial class MudStack : MudComponentBase
.AddClass(Class)
.Build();
+ ///
+ /// Gets the CSS flex direction based on the current breakpoint and row settings.
+ ///
+ ///
+ /// This property generates a CSS flex direction string based on the following conditions:
+ /// - If the breakpoint is not set or is "none" or "always", it returns the default direction based on the Row and Reverse properties.
+ /// - If the breakpoint is one of the predefined sizes ("xs", "sm", "md", "lg", "xl", "xxl"), it generates a flex direction string that changes at the specified breakpoint.
+ /// - If the breakpoint ends with "anddown", it generates a flex direction string that applies up to and including the specified breakpoint.
+ /// - If the breakpoint ends with "andup", it generates a flex direction string that applies from the specified breakpoint and up.
+ ///
+ ///
+ /// A string representing the CSS flex direction based on the current breakpoint and row settings.
+ ///
+ private string getFlexDirection()
+ {
+ // Sets the inital direction based on the Row Parameter and Appends the reverse if needed
+ string defaultState = (Row ? "row" : "column") + (Reverse ? "-reverse" : string.Empty);
+ // Sets the reverse direction based on the Row Parameter and Appends the reverse if needed
+ string reverseState = (Row ? "column" : "row") + (Reverse ? "-reverse" : string.Empty);
+
+ // Switch statement to determine the breakpoint and return the appropriate flex direction
+ switch (Breakpoint)
+ {
+ // If the Breakpoint is None or Always, return the default direction
+ case Breakpoint.None: // If breakpoint is None, return the default direction
+ return $"flex-{defaultState}";
+ case Breakpoint.Always: // If breakpoint is Always, return the reverse direction, honestly the user should just use the Row Property
+ return $"flex-{reverseState}";
+ case Breakpoint.Xs: // Xs is Reverse Direction, Sm and Up is Default Direction
+ return $"flex-{reverseState} flex-sm-{defaultState}";
+ case Breakpoint.Sm: // Xs is Default Direction, Sm is Reverse Direction, Md and Up is Default Direction
+ return $"flex-{defaultState} flex-sm-{reverseState} flex-md-{defaultState}";
+ case Breakpoint.Md: // Xs to Sm is Default Direction, Md is Reverse Direction, Lg and Up is Default Direction
+ return $"flex-{defaultState} flex-md-{reverseState} flex-lg-{defaultState}";
+ case Breakpoint.Lg: // Xs to Md is Default Direction, Lg is Reverse Direction, Xl and Up is Default Direction
+ return $"flex-{defaultState} flex-lg-{reverseState} flex-xl-{defaultState}";
+ case Breakpoint.Xl: // Xs to Lg is Default Direction, Xl is Reverse Direction, Xxl is Default Direction
+ return $"flex-{defaultState} flex-xl-{reverseState} flex-xxl-{defaultState}";
+ case Breakpoint.Xxl: // Xs to Xl is Default Direction, Xxl is Reverse Direction
+ return $"flex-{defaultState} flex-xxl-{reverseState}";
+ case Breakpoint.SmAndDown: // Sm and Down is Reverse Direction, Md and Up is Default Direction
+ return $"flex-{reverseState} flex-md-{defaultState}";
+ case Breakpoint.MdAndDown: // Md and Down is Reverse Direction, Lg and Up is Default Direction
+ return $"flex-{reverseState} flex-lg-{defaultState}";
+ case Breakpoint.LgAndDown: // Lg and Down is Reverse Direction, Xl and Up is Default Direction
+ return $"flex-{reverseState} flex-xl-{defaultState}";
+ case Breakpoint.XlAndDown: // Xl and Down is Reverse Direction, Xxl and Up is Default Direction
+ return $"flex-{reverseState} flex-xxl-{defaultState}";
+ case Breakpoint.SmAndUp: // Xs is Default Direction, Sm and Up is Reverse Direction
+ return $"flex-{defaultState} flex-sm-{reverseState}";
+ case Breakpoint.MdAndUp: // Xs to Sm is Default Direction, Md and Up is Reverse Direction
+ return $"flex-{defaultState} flex-md-{reverseState}";
+ case Breakpoint.LgAndUp: // Xs to Md is Default Direction, Lg and Up is Reverse Direction
+ return $"flex-{defaultState} flex-lg-{reverseState}";
+ case Breakpoint.XlAndUp: // Xs to Lg is Default Direction, Xl and Up is Reverse Direction
+ return $"flex-{defaultState} flex-xl-{reverseState}";
+ default: // Return the default direction if no Breakpoint is Matched
+ return $"flex-{defaultState}";
+ }
+ }
+
///
/// Displays items horizontally.
///
@@ -98,6 +159,13 @@ public partial class MudStack : MudComponentBase
[Category(CategoryTypes.Stack.Behavior)]
public Wrap? Wrap { get; set; }
+ ///
+ /// The breakpoint at which the Stack should switch to a row or column layout.
+ ///
+ [Parameter]
+ [Category(CategoryTypes.Stack.Behavior)]
+ public Breakpoint Breakpoint { get; set; } = Breakpoint.None;
+
///
/// The content within this component.
///
diff --git a/src/MudBlazor/Styles/utilities/flexbox/_flex-direction.scss b/src/MudBlazor/Styles/utilities/flexbox/_flex-direction.scss
index c106f76b9126..ad63c087ce8f 100644
--- a/src/MudBlazor/Styles/utilities/flexbox/_flex-direction.scss
+++ b/src/MudBlazor/Styles/utilities/flexbox/_flex-direction.scss
@@ -18,4 +18,4 @@
}
}
-@include flex-direction("");
+@include flex-direction("");
\ No newline at end of file