diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a56a10..1423c14 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,9 @@ Additions
- Added consuming variants of IsPressed methods to InputHandler
### MLEM.Ui
+Additions
+- Added Element.AutoNavGroup which allows forming groups for auto-navigation
+
Fixes
- Fixed auto-nav tooltip displaying on the selected element even when not in auto-nav mode
- Fixed radio buttons not unchecking all other radio buttons with the same root element
diff --git a/MLEM.Ui/Elements/Element.cs b/MLEM.Ui/Elements/Element.cs
index db48ed3..378be87 100644
--- a/MLEM.Ui/Elements/Element.cs
+++ b/MLEM.Ui/Elements/Element.cs
@@ -249,6 +249,12 @@ namespace MLEM.Ui.Elements {
/// Returns whether this element's method has been recently called and its area has not been updated since then using or .
///
public bool AreaDirty { get; private set; }
+ ///
+ /// An optional string that represents a group of elements for automatic (keyboard and gamepad) navigation.
+ /// All elements that share the same auto-nav group will be able to be navigated between, and all other elements will not be reachable from elements of other groups.
+ /// Note that, if no element is previously selected and auto-navigation is invoked, this element can always be navigated to if it is the first one chosen by auto-navigation.
+ ///
+ public virtual string AutoNavGroup { get; set; }
///
/// This Element's current .
diff --git a/MLEM.Ui/UiControls.cs b/MLEM.Ui/UiControls.cs
index 5f5818d..5389702 100644
--- a/MLEM.Ui/UiControls.cs
+++ b/MLEM.Ui/UiControls.cs
@@ -353,15 +353,15 @@ namespace MLEM.Ui {
protected virtual Element GetTabNextElement(bool backward) {
if (this.ActiveRoot == null)
return null;
- var children = this.ActiveRoot.Element.GetChildren(c => !c.IsHidden, true, true).Append(this.ActiveRoot.Element);
+ var children = this.ActiveRoot.Element.GetChildren(c => !c.IsHidden, true, true).Append(this.ActiveRoot.Element)
+ // we can't add these checks to GetChildren because it ignores false grandchildren
+ .Where(c => c.CanBeSelected && c.AutoNavGroup == this.SelectedElement?.AutoNavGroup);
if (this.SelectedElement?.Root != this.ActiveRoot) {
- return backward ? children.LastOrDefault(c => c.CanBeSelected) : children.FirstOrDefault(c => c.CanBeSelected);
+ return backward ? children.LastOrDefault() : children.FirstOrDefault();
} else {
var foundCurr = false;
Element lastFound = null;
foreach (var child in children) {
- if (!child.CanBeSelected)
- continue;
if (child == this.SelectedElement) {
// when going backwards, return the last element found before the current one
if (backward)