diff --git a/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs b/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
index fdd47979cc4b97c650c0d5be41b93f8eda1f8d5d..e6b3961b8233f2bd93a18f5f25ea437aa250ca99 100644
--- a/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
@@ -46,7 +46,6 @@ pub fn extract_nine_patch(
         let image = images.get(image_handle.as_ref().unwrap());
 
         if image.is_none() {
-            dbg!("Uh oh no image! :(");
             continue;
         }
 
diff --git a/examples/full_ui.rs b/examples/full_ui.rs
index ed9b075b7d9ab309ec9cbce1c64d52c74e627ba2..380f548b19ae54be19cd3bdd1ec069a05999745f 100644
--- a/examples/full_ui.rs
+++ b/examples/full_ui.rs
@@ -43,7 +43,6 @@ fn BlueButton(context: KayakContext, children: Children, styles: Option<Style>)
     };
 
     let current_button_handle = *context.create_state::<u16>(blue_button_handle).unwrap();
-    dbg!(current_button_handle);
 
     let button_styles = Style {
         width: StyleProp::Value(Units::Pixels(200.0)),
@@ -57,14 +56,15 @@ fn BlueButton(context: KayakContext, children: Children, styles: Option<Style>)
 
     let button_id = self.get_id();
     let on_event = OnEvent::new(move |context, event| match event.event_type {
-        EventType::Click => {
-            dbg!("Clicked!");
+        EventType::MouseIn => {
             context.set_current_id(button_id);
             context.set_state::<u16>(blue_button_hover_handle);
         }
-        _ => {
+        EventType::MouseOut => {
+            context.set_current_id(button_id);
             context.set_state::<u16>(blue_button_handle);
         }
+        _ => (),
     });
 
     rsx! {
diff --git a/kayak_core/src/context.rs b/kayak_core/src/context.rs
index 59d1d52306c005762e0cd1b2e17ee12983186f25..8e6fb4dde894c91e7767148bd542ac497e3fdb35 100644
--- a/kayak_core/src/context.rs
+++ b/kayak_core/src/context.rs
@@ -5,10 +5,11 @@ use crate::{node::NodeIndex, widget_manager::WidgetManager, Event, EventType, In
 
 pub struct KayakContext {
     component_states: HashMap<crate::Index, resources::Resources>,
-    current_id: crate::Index,
+    current_id: Index,
     pub widget_manager: WidgetManager,
     last_mouse_position: (f32, f32),
     pub global_state: resources::Resources,
+    previous_events: HashMap<Index, Option<EventType>>,
 }
 
 impl std::fmt::Debug for KayakContext {
@@ -27,6 +28,7 @@ impl KayakContext {
             widget_manager: WidgetManager::new(),
             last_mouse_position: (0.0, 0.0),
             global_state: resources::Resources::default(),
+            previous_events: HashMap::new(),
         }
     }
 
@@ -38,7 +40,6 @@ impl KayakContext {
         &mut self,
         initial_state: T,
     ) -> Option<Ref<T>> {
-        dbg!(self.current_id);
         if self.component_states.contains_key(&self.current_id) {
             let states = self.component_states.get_mut(&self.current_id).unwrap();
             if !states.contains::<T>() {
@@ -63,12 +64,10 @@ impl KayakContext {
     }
 
     pub fn set_state<T: resources::Resource + Clone>(&mut self, state: T) {
-        dbg!(self.current_id);
         if self.component_states.contains_key(&self.current_id) {
             let states = self.component_states.get(&self.current_id).unwrap();
             if states.contains::<T>() {
                 let mut mutate_t = states.get_mut::<T>().unwrap();
-                dbg!("Mutating state!");
                 self.widget_manager.dirty_nodes.push(self.current_id);
                 *mutate_t = state;
             } else {
@@ -126,12 +125,51 @@ impl KayakContext {
                         InputEvent::MouseMoved(point) => {
                             // Hover event.
                             if layout.contains(point) {
+                                if Self::get_last_event(&self.previous_events, &index).is_none() {
+                                    let mouse_in_event = Event {
+                                        target: index,
+                                        event_type: EventType::MouseIn,
+                                        ..Event::default()
+                                    };
+                                    events_stream.push(mouse_in_event);
+                                    Self::set_last_event(
+                                        &mut self.previous_events,
+                                        &index,
+                                        Some(EventType::MouseIn),
+                                    );
+                                }
                                 let hover_event = Event {
                                     target: index,
                                     event_type: EventType::Hover,
                                     ..Event::default()
                                 };
                                 events_stream.push(hover_event);
+                                Self::set_last_event(
+                                    &mut self.previous_events,
+                                    &index,
+                                    Some(EventType::Hover),
+                                );
+                            } else {
+                                if let Some(event) =
+                                    Self::get_last_event(&self.previous_events, &index)
+                                {
+                                    if matches!(event, EventType::Hover)
+                                        | matches!(event, EventType::MouseIn)
+                                    {
+                                        let mouse_out_event = Event {
+                                            target: index,
+                                            event_type: EventType::MouseOut,
+                                            ..Event::default()
+                                        };
+                                        events_stream.push(mouse_out_event);
+                                        Self::set_last_event(
+                                            &mut self.previous_events,
+                                            &index,
+                                            Some(EventType::MouseOut),
+                                        );
+                                    }
+                                }
+                                Self::set_last_event(&mut self.previous_events, &index, None);
                             }
                             self.last_mouse_position = *point;
                         }
@@ -170,6 +208,25 @@ impl KayakContext {
         }
     }
 
+    fn get_last_event(
+        previous_events: &HashMap<Index, Option<EventType>>,
+        widget_id: &Index,
+    ) -> Option<EventType> {
+        if previous_events.contains_key(widget_id) {
+            previous_events.get(widget_id).and_then(|e| *e)
+        } else {
+            None
+        }
+    }
+
+    fn set_last_event(
+        previous_events: &mut HashMap<Index, Option<EventType>>,
+        widget_id: &Index,
+        event_type: Option<EventType>,
+    ) {
+        previous_events.insert(*widget_id, event_type);
+    }
+
     fn get_all_parents(&self, current: Index, parents: &mut Vec<Index>) {
         if let Some(parent) = self.widget_manager.tree.parents.get(&current) {
             parents.push(*parent);
diff --git a/kayak_core/src/event.rs b/kayak_core/src/event.rs
index 92d54952fafd7f379164ab9515076708611d2236..1b1f3ecf4ef06cf217794cb54896a133a132e0bf 100644
--- a/kayak_core/src/event.rs
+++ b/kayak_core/src/event.rs
@@ -21,4 +21,6 @@ impl Default for Event {
 pub enum EventType {
     Click,
     Hover,
+    MouseIn,
+    MouseOut,
 }