From 30d2e6d9a9fcb0c6e818a3a4484cfb00d06f7c77 Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 16:42:14 +0200 Subject: [PATCH 1/6] Add safe variants to `JustifyItems` --- crates/bevy_ui/src/layout/convert.rs | 3 ++ crates/bevy_ui/src/ui_node.rs | 41 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index a45bb5ab0a11d..1af04ff79f297 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -172,8 +172,11 @@ impl From for Option { match value { JustifyItems::Default => None, JustifyItems::Start => taffy::style::JustifyItems::START.into(), + JustifyItems::StartSafe => taffy::style::JustifyItems::SAFE_START.into(), JustifyItems::End => taffy::style::JustifyItems::END.into(), + JustifyItems::EndSafe => taffy::style::JustifyItems::SAFE_END.into(), JustifyItems::Center => taffy::style::JustifyItems::CENTER.into(), + JustifyItems::CenterSafe => taffy::style::JustifyItems::SAFE_CENTER.into(), JustifyItems::Baseline => taffy::style::JustifyItems::BASELINE.into(), JustifyItems::Stretch => taffy::style::JustifyItems::STRETCH.into(), } diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 322b49fd8d106..fecd8679e5c47 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -927,6 +927,11 @@ impl Default for AlignItems { /// - For Flexbox containers, this property has no effect. See `justify_content` for main axis alignment of flex items. /// - For CSS Grid containers, sets default inline (horizontal) axis alignment of child items within their grid areas. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -940,10 +945,16 @@ pub enum JustifyItems { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed along the center of the axis Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are packed such that their baselines align. Baseline, /// The items are stretched to fill the space they're given. @@ -952,6 +963,36 @@ pub enum JustifyItems { impl JustifyItems { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifyItems::StartSafe | JustifyItems::CenterSafe | JustifyItems::EndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifyItems::Default + | JustifyItems::Start + | JustifyItems::Center + | JustifyItems::End + | JustifyItems::Baseline + | JustifyItems::Stretch => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifyItems::Start => JustifyItems::StartSafe, + JustifyItems::Center => JustifyItems::CenterSafe, + JustifyItems::End => JustifyItems::EndSafe, + JustifyItems::Default + | JustifyItems::StartSafe + | JustifyItems::EndSafe + | JustifyItems::CenterSafe + | JustifyItems::Baseline + | JustifyItems::Stretch => self, + } + } } impl Default for JustifyItems { From 5f1353a97ab0b170dcaf22c4ee9b75897bc17406 Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 16:42:14 +0200 Subject: [PATCH 2/6] Add safe variants to `AlignItems` --- crates/bevy_ui/src/layout/convert.rs | 5 +++ crates/bevy_ui/src/ui_node.rs | 55 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index 1af04ff79f297..6ffabd934bce0 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -157,10 +157,15 @@ impl From for Option { match value { AlignItems::Default => None, AlignItems::Start => taffy::style::AlignItems::START.into(), + AlignItems::StartSafe => taffy::style::AlignItems::SAFE_START.into(), AlignItems::End => taffy::style::AlignItems::END.into(), + AlignItems::EndSafe => taffy::style::AlignItems::SAFE_END.into(), AlignItems::FlexStart => taffy::style::AlignItems::FLEX_START.into(), + AlignItems::FlexStartSafe => taffy::style::AlignItems::SAFE_FLEX_START.into(), AlignItems::FlexEnd => taffy::style::AlignItems::FLEX_END.into(), + AlignItems::FlexEndSafe => taffy::style::AlignItems::SAFE_FLEX_END.into(), AlignItems::Center => taffy::style::AlignItems::CENTER.into(), + AlignItems::CenterSafe => taffy::style::AlignItems::SAFE_CENTER.into(), AlignItems::Baseline => taffy::style::AlignItems::BASELINE.into(), AlignItems::Stretch => taffy::style::AlignItems::STRETCH.into(), } diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index fecd8679e5c47..b711a78364947 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -884,6 +884,11 @@ pub enum InlineDirection { /// - For Flexbox containers, sets default cross axis alignment of the child items. /// - For CSS Grid containers, controls block (vertical) axis alignment of children of this grid container within their grid areas. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -897,16 +902,26 @@ pub enum AlignItems { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then they are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then they are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are packed such that their baselines align. Baseline, /// The items are stretched to fill the space they're given. @@ -915,6 +930,46 @@ pub enum AlignItems { impl AlignItems { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignItems::StartSafe + | AlignItems::CenterSafe + | AlignItems::EndSafe + | AlignItems::FlexStartSafe + | AlignItems::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignItems::Default + | AlignItems::Start + | AlignItems::Center + | AlignItems::End + | AlignItems::FlexStart + | AlignItems::FlexEnd + | AlignItems::Baseline + | AlignItems::Stretch => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignItems::Start => AlignItems::StartSafe, + AlignItems::Center => AlignItems::CenterSafe, + AlignItems::End => AlignItems::EndSafe, + AlignItems::FlexStart => AlignItems::FlexStartSafe, + AlignItems::FlexEnd => AlignItems::FlexEndSafe, + AlignItems::Default + | AlignItems::StartSafe + | AlignItems::EndSafe + | AlignItems::CenterSafe + | AlignItems::FlexStartSafe + | AlignItems::FlexEndSafe + | AlignItems::Baseline + | AlignItems::Stretch => self, + } + } } impl Default for AlignItems { From 65101568c47e1c3cd78819db48d39632e28f574f Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 17:44:04 +0200 Subject: [PATCH 3/6] Add safe variants to `JustifyContent` --- crates/bevy_ui/src/layout/convert.rs | 5 +++ crates/bevy_ui/src/ui_node.rs | 59 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index 6ffabd934bce0..ae5c6a0bd4f1c 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -238,10 +238,15 @@ impl From for Option { match value { JustifyContent::Default => None, JustifyContent::Start => taffy::style::JustifyContent::START.into(), + JustifyContent::StartSafe => taffy::style::JustifyContent::SAFE_START.into(), JustifyContent::End => taffy::style::JustifyContent::END.into(), + JustifyContent::EndSafe => taffy::style::JustifyContent::SAFE_END.into(), JustifyContent::FlexStart => taffy::style::JustifyContent::FLEX_START.into(), + JustifyContent::FlexStartSafe => taffy::style::JustifyContent::SAFE_FLEX_START.into(), JustifyContent::FlexEnd => taffy::style::JustifyContent::FLEX_END.into(), + JustifyContent::FlexEndSafe => taffy::style::JustifyContent::SAFE_FLEX_END.into(), JustifyContent::Center => taffy::style::JustifyContent::CENTER.into(), + JustifyContent::CenterSafe => taffy::style::JustifyContent::SAFE_CENTER.into(), JustifyContent::Stretch => taffy::style::JustifyContent::STRETCH.into(), JustifyContent::SpaceBetween => taffy::style::JustifyContent::SPACE_BETWEEN.into(), JustifyContent::SpaceAround => taffy::style::JustifyContent::SPACE_AROUND.into(), diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index b711a78364947..949f905c6e5d1 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1187,6 +1187,11 @@ impl Default for AlignContent { /// - For Flexbox containers, controls alignment of items in the main axis. /// - For CSS Grid containers, controls alignment of grid columns. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1200,16 +1205,26 @@ pub enum JustifyContent { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then the items are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then the items are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are stretched to fill the container along the axis. Stretch, /// The items are distributed such that the gap between any two items is equal. @@ -1222,6 +1237,50 @@ pub enum JustifyContent { impl JustifyContent { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifyContent::StartSafe + | JustifyContent::CenterSafe + | JustifyContent::EndSafe + | JustifyContent::FlexStartSafe + | JustifyContent::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifyContent::Default + | JustifyContent::Start + | JustifyContent::Center + | JustifyContent::End + | JustifyContent::FlexStart + | JustifyContent::FlexEnd + | JustifyContent::Stretch + | JustifyContent::SpaceBetween + | JustifyContent::SpaceEvenly + | JustifyContent::SpaceAround => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifyContent::Start => JustifyContent::StartSafe, + JustifyContent::Center => JustifyContent::CenterSafe, + JustifyContent::End => JustifyContent::EndSafe, + JustifyContent::FlexStart => JustifyContent::FlexStartSafe, + JustifyContent::FlexEnd => JustifyContent::FlexEndSafe, + JustifyContent::Default + | JustifyContent::StartSafe + | JustifyContent::EndSafe + | JustifyContent::CenterSafe + | JustifyContent::FlexStartSafe + | JustifyContent::FlexEndSafe + | JustifyContent::Stretch + | JustifyContent::SpaceBetween + | JustifyContent::SpaceEvenly + | JustifyContent::SpaceAround => self, + } + } } impl Default for JustifyContent { From ad949c65704380025b68179e73126451a308ea0e Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 18:02:38 +0200 Subject: [PATCH 4/6] Add safe variants to `AlignContent` --- crates/bevy_ui/src/layout/convert.rs | 5 +++ crates/bevy_ui/src/ui_node.rs | 59 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index ae5c6a0bd4f1c..5a3f9c01071ec 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -221,10 +221,15 @@ impl From for Option { match value { AlignContent::Default => None, AlignContent::Start => taffy::style::AlignContent::START.into(), + AlignContent::StartSafe => taffy::style::AlignContent::SAFE_START.into(), AlignContent::End => taffy::style::AlignContent::END.into(), + AlignContent::EndSafe => taffy::style::AlignContent::SAFE_END.into(), AlignContent::FlexStart => taffy::style::AlignContent::FLEX_START.into(), + AlignContent::FlexStartSafe => taffy::style::AlignContent::SAFE_FLEX_START.into(), AlignContent::FlexEnd => taffy::style::AlignContent::FLEX_END.into(), + AlignContent::FlexEndSafe => taffy::style::AlignContent::SAFE_FLEX_END.into(), AlignContent::Center => taffy::style::AlignContent::CENTER.into(), + AlignContent::CenterSafe => taffy::style::AlignContent::SAFE_CENTER.into(), AlignContent::Stretch => taffy::style::AlignContent::STRETCH.into(), AlignContent::SpaceBetween => taffy::style::AlignContent::SPACE_BETWEEN.into(), AlignContent::SpaceAround => taffy::style::AlignContent::SPACE_AROUND.into(), diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 949f905c6e5d1..abfaef9f80fc3 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1140,6 +1140,11 @@ impl Default for JustifySelf { /// - For Flexbox containers, controls alignment of lines if `flex_wrap` is set to [`FlexWrap::Wrap`] and there are multiple lines of items. /// - For CSS Grid containers, controls alignment of grid rows. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1153,16 +1158,26 @@ pub enum AlignContent { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then the items are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then the items are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are stretched to fill the container along the axis. Stretch, /// The items are distributed such that the gap between any two items is equal. @@ -1175,6 +1190,50 @@ pub enum AlignContent { impl AlignContent { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignContent::StartSafe + | AlignContent::CenterSafe + | AlignContent::EndSafe + | AlignContent::FlexStartSafe + | AlignContent::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignContent::Default + | AlignContent::Start + | AlignContent::Center + | AlignContent::End + | AlignContent::FlexStart + | AlignContent::FlexEnd + | AlignContent::Stretch + | AlignContent::SpaceBetween + | AlignContent::SpaceEvenly + | AlignContent::SpaceAround => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignContent::Start => AlignContent::StartSafe, + AlignContent::Center => AlignContent::CenterSafe, + AlignContent::End => AlignContent::EndSafe, + AlignContent::FlexStart => AlignContent::FlexStartSafe, + AlignContent::FlexEnd => AlignContent::FlexEndSafe, + AlignContent::Default + | AlignContent::StartSafe + | AlignContent::EndSafe + | AlignContent::CenterSafe + | AlignContent::FlexStartSafe + | AlignContent::FlexEndSafe + | AlignContent::Stretch + | AlignContent::SpaceBetween + | AlignContent::SpaceEvenly + | AlignContent::SpaceAround => self, + } + } } impl Default for AlignContent { From 4e1a37f78b6aa087340aefc6476d4cbb8c415f3c Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 18:02:38 +0200 Subject: [PATCH 5/6] Add safe variants to `JustifySelf` --- crates/bevy_ui/src/layout/convert.rs | 3 ++ crates/bevy_ui/src/ui_node.rs | 41 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index 5a3f9c01071ec..ab5a06f79a8de 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -208,8 +208,11 @@ impl From for Option { match value { JustifySelf::Auto => None, JustifySelf::Start => taffy::style::JustifySelf::START.into(), + JustifySelf::StartSafe => taffy::style::JustifySelf::SAFE_START.into(), JustifySelf::End => taffy::style::JustifySelf::END.into(), + JustifySelf::EndSafe => taffy::style::JustifySelf::SAFE_END.into(), JustifySelf::Center => taffy::style::JustifySelf::CENTER.into(), + JustifySelf::CenterSafe => taffy::style::JustifySelf::SAFE_CENTER.into(), JustifySelf::Baseline => taffy::style::JustifySelf::BASELINE.into(), JustifySelf::Stretch => taffy::style::JustifySelf::STRETCH.into(), } diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index abfaef9f80fc3..dcd10375da1a1 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1103,6 +1103,11 @@ impl Default for AlignSelf { /// - For children of flex nodes, this property has no effect. See `justify_content` for main axis alignment of flex items. /// - For CSS Grid items, controls inline (horizontal) axis alignment of a grid item within its grid area. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1116,10 +1121,16 @@ pub enum JustifySelf { Auto, /// This item will be aligned with the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// This item will be aligned with the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// This item will be aligned along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// This item will be aligned at the baseline. Baseline, /// This item will be stretched to fill the space it's given. @@ -1128,6 +1139,36 @@ pub enum JustifySelf { impl JustifySelf { pub const DEFAULT: Self = Self::Auto; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifySelf::StartSafe | JustifySelf::CenterSafe | JustifySelf::EndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifySelf::Start + | JustifySelf::Center + | JustifySelf::End + | JustifySelf::Auto + | JustifySelf::Stretch + | JustifySelf::Baseline => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifySelf::Start => JustifySelf::StartSafe, + JustifySelf::Center => JustifySelf::CenterSafe, + JustifySelf::End => JustifySelf::EndSafe, + JustifySelf::StartSafe + | JustifySelf::EndSafe + | JustifySelf::CenterSafe + | JustifySelf::Auto + | JustifySelf::Stretch + | JustifySelf::Baseline => self, + } + } } impl Default for JustifySelf { From 68b18fbf2590f0b9d2b4feb8d1066b9d7e20309d Mon Sep 17 00:00:00 2001 From: Loreball Date: Mon, 31 Aug 2026 18:23:20 +0200 Subject: [PATCH 6/6] Add safe variants to `AlignSelf` --- crates/bevy_ui/src/layout/convert.rs | 5 +++ crates/bevy_ui/src/ui_node.rs | 55 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index ab5a06f79a8de..91a34a796df9e 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -193,10 +193,15 @@ impl From for Option { match value { AlignSelf::Auto => None, AlignSelf::Start => taffy::style::AlignSelf::START.into(), + AlignSelf::StartSafe => taffy::style::AlignSelf::SAFE_START.into(), AlignSelf::End => taffy::style::AlignSelf::END.into(), + AlignSelf::EndSafe => taffy::style::AlignSelf::SAFE_END.into(), AlignSelf::FlexStart => taffy::style::AlignSelf::FLEX_START.into(), + AlignSelf::FlexStartSafe => taffy::style::AlignSelf::SAFE_FLEX_START.into(), AlignSelf::FlexEnd => taffy::style::AlignSelf::FLEX_END.into(), + AlignSelf::FlexEndSafe => taffy::style::AlignSelf::SAFE_FLEX_END.into(), AlignSelf::Center => taffy::style::AlignSelf::CENTER.into(), + AlignSelf::CenterSafe => taffy::style::AlignSelf::SAFE_CENTER.into(), AlignSelf::Baseline => taffy::style::AlignSelf::BASELINE.into(), AlignSelf::Stretch => taffy::style::AlignSelf::STRETCH.into(), } diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index dcd10375da1a1..27ebc2c820fbb 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1060,6 +1060,11 @@ impl Default for JustifyItems { /// - For Flexbox items, controls cross axis alignment of the item. /// - For CSS Grid items, controls block (vertical) axis alignment of a grid item within its grid area. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1073,16 +1078,26 @@ pub enum AlignSelf { Auto, /// This item will be aligned with the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// This item will be aligned with the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// This item will be aligned with the start of the axis, unless the flex direction is reversed; /// then it will be aligned with the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// This item will be aligned with the end of the axis, unless the flex direction is reversed; /// then it will be aligned with the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// This item will be aligned along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// This item will be aligned at the baseline. Baseline, /// This item will be stretched to fill the container. @@ -1091,6 +1106,46 @@ pub enum AlignSelf { impl AlignSelf { pub const DEFAULT: Self = Self::Auto; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignSelf::StartSafe + | AlignSelf::CenterSafe + | AlignSelf::EndSafe + | AlignSelf::FlexStartSafe + | AlignSelf::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignSelf::Start + | AlignSelf::Center + | AlignSelf::End + | AlignSelf::FlexStart + | AlignSelf::FlexEnd + | AlignSelf::Stretch + | AlignSelf::Auto + | AlignSelf::Baseline => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignSelf::Start => AlignSelf::StartSafe, + AlignSelf::Center => AlignSelf::CenterSafe, + AlignSelf::End => AlignSelf::EndSafe, + AlignSelf::FlexStart => AlignSelf::FlexStartSafe, + AlignSelf::FlexEnd => AlignSelf::FlexEndSafe, + AlignSelf::StartSafe + | AlignSelf::EndSafe + | AlignSelf::CenterSafe + | AlignSelf::FlexStartSafe + | AlignSelf::FlexEndSafe + | AlignSelf::Stretch + | AlignSelf::Auto + | AlignSelf::Baseline => self, + } + } } impl Default for AlignSelf {