From 9654bf57b3e21cefb144f356f14b1871eef1cbbf Mon Sep 17 00:00:00 2001 From: Alice I Cecile Date: Wed, 8 Apr 2026 15:23:28 -0700 Subject: [PATCH 1/2] Add advice on best practices for event propagation --- crates/bevy_ecs/src/event/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/bevy_ecs/src/event/mod.rs b/crates/bevy_ecs/src/event/mod.rs index 5abbe9d747d5f..b80d54e6e8dc7 100644 --- a/crates/bevy_ecs/src/event/mod.rs +++ b/crates/bevy_ecs/src/event/mod.rs @@ -272,6 +272,22 @@ pub trait Event: Send + Sync + Sized + 'static { /// }); /// ``` /// +/// ## Best practices for event propagation +/// +/// Propagation is useful for events that should be handled by multiple entities in a hierarchy, such as UI events. +/// In these cases, it is common for the event to be triggered on a "leaf" entity, and then propagate up to "root" entities. +/// In this pattern, it is generally recommended to trigger the event on the most specific entity possible (the leaf), and then use propagation to have it handled by more general entities (the roots). +/// +/// Once an event is handled by a given entity, you should stop propagation. +/// This ensures that only a single "behavior" resolves per event sent, +/// avoiding unexpected behavior from entities higher up the hierarchy. +/// +/// This advice has one notable wrinkle: +/// if an entity is "disabled" (e.g. if a UI node is grayed out), +/// the event should still be considered "handled" by that entity, +/// even though the observer logic should not be run. +/// This ensures consistent behavior regardless of the enabled/disabled state of entities. +/// /// ## Naming and Usage Conventions /// /// In most cases, it is recommended to use a named struct field for the "event target" entity, and to use From eeeff35db49caa4a6c786ecda736440ea043f74a Mon Sep 17 00:00:00 2001 From: Alice I Cecile Date: Wed, 8 Apr 2026 15:26:41 -0700 Subject: [PATCH 2/2] Add cross-links from bevy_ui_widgets and bevy_feathers --- crates/bevy_feathers/src/lib.rs | 8 ++++++++ crates/bevy_ui_widgets/src/lib.rs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/crates/bevy_feathers/src/lib.rs b/crates/bevy_feathers/src/lib.rs index 3bb3e1b76e5c9..2eae6919218b6 100644 --- a/crates/bevy_feathers/src/lib.rs +++ b/crates/bevy_feathers/src/lib.rs @@ -11,6 +11,14 @@ //! Consider copying this code into your own project, //! and refining the styles and abstractions provided to meet your needs. //! +//! ## Best practices for event propagation +//! +//! Generally, when a widget handles an event, +//! propagation of that event to parent entities should be stopped. +//! This is important when writing your custom widgets, and understanding the behavior of existing widgets. +//! +//! For more guidance on this, see the documentation for [`EntityEvent`](bevy_ecs::event::EntityEvent). +//! //! ## Warning: Experimental! //! All that said, this crate is still experimental and unfinished! //! It will change in breaking ways, and there will be both bugs and limitations. diff --git a/crates/bevy_ui_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 027ebbf85951c..f7abf98cc8c9b 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -17,6 +17,14 @@ //! state (as well as any other related game state) in response to a change event emitted by the //! widget. The primary motivation for this is to avoid two-way data binding in scenarios where the //! user interface is showing a live view of dynamic data coming from deeper within the game engine. +//! +//! ## Best practices for event propagation +//! +//! Generally, when a widget handles an event, +//! propagation of that event to parent entities should be stopped. +//! This is important when writing your custom widgets, and understanding the behavior of existing widgets. +//! +//! For more guidance on this, see the documentation for [`EntityEvent`]. mod button; mod checkbox;