diff --git a/bevy_kayak_ui/src/bevy_context.rs b/bevy_kayak_ui/src/bevy_context.rs
index 9322b73836bd23de91d7daaa90e3ffd807513802..0c2c974e74e5116e913d90fda7e2ad7c65e681c2 100644
--- a/bevy_kayak_ui/src/bevy_context.rs
+++ b/bevy_kayak_ui/src/bevy_context.rs
@@ -2,6 +2,7 @@ use std::sync::{Arc, RwLock};
 
 use kayak_core::{
     context::KayakContext,
+    render_command::RenderCommand,
     styles::{Style, StyleProp, Units},
 };
 
@@ -12,6 +13,7 @@ pub struct BevyContext {
 impl BevyContext {
     pub fn new<F: Fn(&mut Style, &mut KayakContext)>(width: f32, height: f32, f: F) -> Self {
         let mut app_styles = Style {
+            render_command: StyleProp::Value(RenderCommand::Window),
             width: StyleProp::Value(Units::Pixels(width)),
             height: StyleProp::Value(Units::Pixels(height)),
             ..Style::default()
diff --git a/bevy_kayak_ui/src/lib.rs b/bevy_kayak_ui/src/lib.rs
index c5f8e11b1bfb03c0dce3d49c79410e528b273348..fee1bbc002e4c64ee1a418d83d638763af7f2603 100644
--- a/bevy_kayak_ui/src/lib.rs
+++ b/bevy_kayak_ui/src/lib.rs
@@ -1,4 +1,10 @@
-use bevy::{prelude::{Plugin, ResMut}, render2::color::Color};
+use bevy::{
+    input::{mouse::MouseButtonInput, ElementState},
+    math::Vec2,
+    prelude::{EventReader, MouseButton, Plugin, Res, ResMut},
+    render2::color::Color,
+    window::{CursorMoved, Windows},
+};
 
 mod bevy_context;
 mod camera;
@@ -6,6 +12,7 @@ mod render;
 
 pub use bevy_context::BevyContext;
 pub use camera::*;
+use kayak_core::InputEvent;
 
 #[derive(Default)]
 pub struct BevyKayakUIPlugin;
@@ -22,8 +29,40 @@ pub(crate) fn to_bevy_color(color: &kayak_core::color::Color) -> Color {
     Color::rgba(color.r, color.g, color.b, color.a)
 }
 
-pub fn update(bevy_context: ResMut<BevyContext>) {
+pub fn update(
+    bevy_context: ResMut<BevyContext>,
+    mut cursor_moved_events: EventReader<CursorMoved>,
+    mut mouse_button_input_events: EventReader<MouseButtonInput>,
+    windows: Res<Windows>,
+) {
+    let window_size = if let Some(window) = windows.get_primary() {
+        Vec2::new(window.width(), window.height())
+    } else {
+        panic!("Couldn't find primary window!");
+    };
+
     if let Ok(mut context) = bevy_context.kayak_context.write() {
         context.render();
+
+        let mut input_events = Vec::new();
+        for event in cursor_moved_events.iter() {
+            input_events.push(InputEvent::MouseMoved((
+                event.position.x as f32,
+                window_size.y - event.position.y as f32,
+            )));
+        }
+
+        for event in mouse_button_input_events.iter() {
+            match event.button {
+                MouseButton::Left => {
+                    if event.state == ElementState::Pressed {
+                        input_events.push(InputEvent::MouseLeftClick);
+                    }
+                }
+                _ => {}
+            }
+        }
+
+        context.process_events(input_events);
     }
 }
diff --git a/bevy_kayak_ui/src/render/unified/quad/extract.rs b/bevy_kayak_ui/src/render/unified/quad/extract.rs
index 523ed83e5983a1a9323a1683f601d1504cc0a8ab..fe74d223732f7f5cc512d1272fb6686110c9ae8d 100644
--- a/bevy_kayak_ui/src/render/unified/quad/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/quad/extract.rs
@@ -36,7 +36,7 @@ pub fn extract_quads(mut commands: Commands, context: Res<BevyContext>) {
             extracted_quad: ExtractedQuad {
                 rect: Rect {
                     min: Vec2::new(layout.posx, layout.posy),
-                    max: Vec2::new(layout.width, layout.height),
+                    max: Vec2::new(layout.posx + layout.width, layout.posy + layout.height),
                 },
                 color: to_bevy_color(background_color),
                 vertex_index: 0,
diff --git a/examples/bevy.rs b/examples/bevy.rs
index dedfde9891893b0c6eeb1009784d64ecc66d366c..4895e2ad93c1d6f2513622bd4fc9766ed3ad913c 100644
--- a/examples/bevy.rs
+++ b/examples/bevy.rs
@@ -42,7 +42,12 @@ fn startup(mut commands: Commands, windows: Res<Windows>) {
         let parent_id: Option<Index> = None;
         rsx! {
             <App styles={Some(styles.clone())}>
-                <TestState>{}</TestState>
+                <Window position={(50.0, 50.0)} size={(300.0, 300.0)} title={"Window 1".to_string()}>
+                    {}
+                </Window>
+                <Window position={(800.0, 50.0)} size={(200.0, 200.0)} title={"Window 2".to_string()}>
+                    {}
+                </Window>
             </App>
         }
     });
diff --git a/examples/counter.rs b/examples/counter.rs
new file mode 100644
index 0000000000000000000000000000000000000000..457f5c91f5fc9f0f3d2aaad6a5077c13f7438891
--- /dev/null
+++ b/examples/counter.rs
@@ -0,0 +1,86 @@
+use bevy::{
+    math::Vec2,
+    prelude::{App as BevyApp, Commands, Res},
+    window::{WindowDescriptor, Windows},
+    PipelinedDefaultPlugins,
+};
+use bevy_kayak_ui::{BevyContext, BevyKayakUIPlugin, UICameraBundle};
+use kayak_components::{Button, Text, Window};
+use kayak_core::{
+    styles::{Style, StyleProp, Units},
+    EventType, Index, OnEvent,
+};
+use kayak_ui::components::App;
+use kayak_ui::core::{rsx, widget};
+
+#[widget]
+fn Counter() {
+    let count = {
+        let x = context.create_state(0i32).unwrap();
+        *x
+    };
+    let text_styles = Style {
+        bottom: StyleProp::Value(Units::Stretch(1.0)),
+        left: StyleProp::Value(Units::Stretch(1.0)),
+        right: StyleProp::Value(Units::Stretch(1.0)),
+        top: StyleProp::Value(Units::Stretch(1.0)),
+        height: StyleProp::Value(Units::Pixels(26.0)),
+        ..Default::default()
+    };
+
+    let id = self.get_id();
+    let on_event = OnEvent::new(move |context, event| match event.event_type {
+        EventType::Click => {
+            context.set_current_id(id);
+            context.set_state(count + 1);
+        }
+        _ => {}
+    });
+
+    rsx! {
+        <>
+            <Window position={(50.0, 50.0)} size={(300.0, 300.0)} title={"Counter Example".to_string()}>
+                <Text size={16.0} content={format!("Current Count: {}", count).to_string()}>{}</Text>
+                <Button on_event={Some(on_event)}>
+                    <Text styles={Some(text_styles)} size={24.0} content={"Count!".to_string()}>{}</Text>
+                </Button>
+            </Window>
+        </>
+    }
+}
+
+fn startup(mut commands: Commands, windows: Res<Windows>) {
+    commands.spawn_bundle(UICameraBundle::new());
+
+    let window_size = if let Some(window) = windows.get_primary() {
+        Vec2::new(window.width(), window.height())
+    } else {
+        panic!("Couldn't find primary window!");
+    };
+
+    let context = BevyContext::new(window_size.x, window_size.y, |styles, context| {
+        // Hack to trick the proc macro for right now..
+        let parent_id: Option<Index> = None;
+        rsx! {
+            <App styles={Some(styles.clone())}>
+                <Counter />
+            </App>
+        }
+    });
+
+    commands.insert_resource(context);
+}
+
+fn main() {
+    BevyApp::new()
+        .insert_resource(WindowDescriptor {
+            width: 1270.0,
+            height: 720.0,
+            title: String::from("UI Example"),
+            ..Default::default()
+        })
+        .add_plugins(PipelinedDefaultPlugins)
+        .add_plugin(BevyKayakUIPlugin)
+        .add_startup_system(startup)
+        .run();
+}
diff --git a/kayak_components/src/button.rs b/kayak_components/src/button.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9ca7e9b634a7e5751a59a97ee3775ea94cb1b887
--- /dev/null
+++ b/kayak_components/src/button.rs
@@ -0,0 +1,31 @@
+use kayak_core::{
+    color::Color,
+    render_command::RenderCommand,
+    rsx,
+    styles::{Style, StyleProp, Units},
+    widget, Children, Fragment,
+};
+
+#[widget]
+pub fn Button(children: Children, styles: Option<Style>) {
+    let base_styles = styles.clone().unwrap_or_default();
+    *styles = Some(Style {
+        render_command: StyleProp::Value(RenderCommand::Quad),
+        height: if base_styles.height == StyleProp::Default {
+            StyleProp::Value(Units::Pixels(45.0))
+        } else {
+            base_styles.height
+        },
+        background_color: if matches!(base_styles.background_color, StyleProp::Default) {
+            StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0))
+        } else {
+            base_styles.background_color
+        },
+        ..base_styles
+    });
+    rsx! {
+        <Fragment>
+            {children}
+        </Fragment>
+    }
+}
diff --git a/kayak_components/src/lib.rs b/kayak_components/src/lib.rs
index 9e72b31390ce26c450d96de9655ed159dc0a5355..a9b99766d6e61c29c1503cd17f00736729100b40 100644
--- a/kayak_components/src/lib.rs
+++ b/kayak_components/src/lib.rs
@@ -1,11 +1,13 @@
 mod app;
 mod background;
+mod button;
 mod clip;
 mod text;
 mod window;
 
 pub use app::*;
 pub use background::*;
+pub use button::*;
 pub use clip::*;
 pub use text::*;
 pub use window::*;
diff --git a/kayak_components/src/window.rs b/kayak_components/src/window.rs
index 3abf6e4b91a1320de1bf3a72b0d9b929bd350440..0671ff4a64a3cefd8ec23084f3090ef2516eacab 100644
--- a/kayak_components/src/window.rs
+++ b/kayak_components/src/window.rs
@@ -16,22 +16,6 @@ pub fn Window(
     size: (f32, f32),
     title: String,
 ) {
-    // let mut changed_styles = styles.clone().unwrap_or_default();
-    // changed_styles.render_command = RenderCommand::Quad;
-    // changed_styles.position_type = Some(PositionType::Absolute);
-    // changed_styles.background = Some(Color::new(0.0588, 0.0588, 0.588, 1.0));
-    // changed_styles.position = Some(Rect {
-    //     start: Dimension::Points(position.x),
-    //     end: Dimension::Points(position.x + size.width),
-    //     top: Dimension::Points(position.y),
-    //     bottom: Dimension::Points(position.y + size.height),
-    // });
-    // changed_styles.size = Some(Size {
-    //     width: Dimension::Points(size.width),
-    //     height: Dimension::Points(size.height),
-    // });
-    // styles = Some(changed_styles);
-
     *styles = Some(Style {
         background_color: StyleProp::Value(Color::new(0.125, 0.125, 0.125, 1.0)),
         render_command: StyleProp::Value(RenderCommand::Quad),
@@ -49,12 +33,7 @@ pub fn Window(
         ..Style::default()
     };
 
-    let title_text_styles = Style {
-        position_type: StyleProp::Value(PositionType::SelfDirected),
-        top: StyleProp::Value(Units::Pixels(-22.0)),
-        left: StyleProp::Value(Units::Pixels(5.0)),
-        ..Style::default()
-    };
+    let title_text_styles = Style { ..Style::default() };
 
     let title = title.clone();
     rsx! {
diff --git a/kayak_core/examples/test3.rs b/kayak_core/examples/test3.rs
index 34079bcc18ff2f0b476db53211570a431fc3ba87..12c568387ed725c52d41d1943a42315569b498a8 100644
--- a/kayak_core/examples/test3.rs
+++ b/kayak_core/examples/test3.rs
@@ -44,6 +44,7 @@ fn main() {
             height: StyleProp::Value(Units::Pixels(720.0)),
             ..Style::default()
         }),
+        on_event: None,
     };
 
     let (_, widget_id) = context.widget_manager.create_widget(0, my_widget, None);
diff --git a/kayak_core/src/context.rs b/kayak_core/src/context.rs
index 74cd09b3f76340ca262933350cc84a0fcf7f92c1..b18aa0ef8c79a7e4d7ea06e36515673cc6e77441 100644
--- a/kayak_core/src/context.rs
+++ b/kayak_core/src/context.rs
@@ -2,12 +2,13 @@ use std::collections::HashMap;
 
 use resources::Ref;
 
-use crate::widget_manager::WidgetManager;
+use crate::{node::NodeIndex, widget_manager::WidgetManager, Event, EventType, Index, InputEvent};
 
 pub struct KayakContext {
     component_states: HashMap<crate::Index, resources::Resources>,
     current_id: crate::Index,
     pub widget_manager: WidgetManager,
+    last_mouse_position: (f32, f32),
 }
 
 impl std::fmt::Debug for KayakContext {
@@ -24,6 +25,7 @@ impl KayakContext {
             component_states: HashMap::new(),
             current_id: crate::Index::default(),
             widget_manager: WidgetManager::new(),
+            last_mouse_position: (0.0, 0.0),
         }
     }
 
@@ -72,10 +74,7 @@ impl KayakContext {
                 );
             }
         } else {
-            panic!(
-                "No state created for component with id: {:?}!",
-                self.current_id
-            );
+            // Do nothing..
         }
     }
 
@@ -99,4 +98,64 @@ impl KayakContext {
         self.widget_manager.render();
         self.widget_manager.calculate_layout();
     }
+
+    pub fn process_events(&mut self, input_events: Vec<InputEvent>) {
+        let mut events_stream = Vec::new();
+        for (index, _) in self.widget_manager.nodes.iter() {
+            if let Some(layout) = self.widget_manager.layout_cache.rect.get(&NodeIndex(index)) {
+                for input_event in input_events.iter() {
+                    match input_event {
+                        InputEvent::MouseMoved(point) => {
+                            // Hover event.
+                            if layout.contains(point) {
+                                let hover_event = Event {
+                                    target: index,
+                                    event_type: EventType::Hover,
+                                    ..Event::default()
+                                };
+                                events_stream.push(hover_event);
+                            }
+                            self.last_mouse_position = *point;
+                        }
+                        InputEvent::MouseLeftClick => {
+                            if layout.contains(&self.last_mouse_position) {
+                                let click_event = Event {
+                                    target: index,
+                                    event_type: EventType::Click,
+                                    ..Event::default()
+                                };
+                                events_stream.push(click_event);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Propagate Events
+        for event in events_stream.iter_mut() {
+            let mut parents: Vec<Index> = Vec::new();
+            self.get_all_parents(event.target, &mut parents);
+
+            // First call target
+            let mut target_widget = self.widget_manager.take(event.target);
+            target_widget.on_event(self, event);
+            self.widget_manager.repossess(target_widget);
+
+            for parent in parents {
+                if event.should_propagate {
+                    let mut parent_widget = self.widget_manager.take(parent);
+                    parent_widget.on_event(self, event);
+                    self.widget_manager.repossess(parent_widget);
+                }
+            }
+        }
+    }
+
+    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);
+            self.get_all_parents(*parent, parents);
+        }
+    }
 }
diff --git a/kayak_core/src/event.rs b/kayak_core/src/event.rs
new file mode 100644
index 0000000000000000000000000000000000000000..92d54952fafd7f379164ab9515076708611d2236
--- /dev/null
+++ b/kayak_core/src/event.rs
@@ -0,0 +1,24 @@
+use crate::Index;
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct Event {
+    pub target: Index,
+    pub event_type: EventType,
+    pub(crate) should_propagate: bool,
+}
+
+impl Default for Event {
+    fn default() -> Self {
+        Self {
+            target: Default::default(),
+            event_type: EventType::Click,
+            should_propagate: true,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum EventType {
+    Click,
+    Hover,
+}
diff --git a/kayak_core/src/fragment.rs b/kayak_core/src/fragment.rs
index 837a5e6145f6ca947ef8d11e824f885226284248..744e444f82e48efaf5177b80bb2f4a40ed303ce6 100644
--- a/kayak_core/src/fragment.rs
+++ b/kayak_core/src/fragment.rs
@@ -6,9 +6,11 @@ use crate::{context::KayakContext, styles::Style, Index, Widget};
 #[derivative(Debug, PartialEq)]
 pub struct Fragment {
     pub id: Index,
+    pub styles: Option<Style>,
     #[derivative(Debug = "ignore", PartialEq = "ignore")]
     pub children: crate::Children,
-    pub styles: Option<Style>,
+    #[derivative(Debug = "ignore", PartialEq = "ignore")]
+    pub on_event: Option<crate::OnEvent>,
 }
 
 impl Widget for Fragment {
@@ -24,6 +26,14 @@ impl Widget for Fragment {
         self.styles.clone()
     }
 
+    fn get_name(&self) -> String {
+        String::from("Fragment")
+    }
+
+    fn on_event(&mut self, _context: &mut KayakContext, _event: &mut crate::Event) {
+        // Do nothing.
+    }
+
     fn render(&mut self, context: &mut KayakContext) {
         dbg!("Rendering fragment children!");
         if let Some(children) = self.children.as_ref() {
diff --git a/kayak_core/src/input_event.rs b/kayak_core/src/input_event.rs
new file mode 100644
index 0000000000000000000000000000000000000000..18856f738152c4db03c6bb6edfa2805e2edb69a6
--- /dev/null
+++ b/kayak_core/src/input_event.rs
@@ -0,0 +1,4 @@
+pub enum InputEvent {
+    MouseMoved((f32, f32)),
+    MouseLeftClick,
+}
diff --git a/kayak_core/src/layout_cache.rs b/kayak_core/src/layout_cache.rs
index 59f251ecbf8c322d0a44f8e043955d5157c4b746..c843be7332f35973d4dd37bd0a0d705ab5925962 100644
--- a/kayak_core/src/layout_cache.rs
+++ b/kayak_core/src/layout_cache.rs
@@ -13,6 +13,13 @@ pub struct Rect {
     pub z_index: f32,
 }
 
+impl Rect {
+    pub fn contains(&self, point: &(f32, f32)) -> bool {
+        (point.0 >= self.posx && point.0 <= self.posx + self.width)
+            && (point.1 >= self.posy && point.1 <= self.posy + self.height)
+    }
+}
+
 #[derive(Debug, Default, Clone, Copy)]
 pub struct Space {
     pub left: f32,
diff --git a/kayak_core/src/lib.rs b/kayak_core/src/lib.rs
index 73ad0d8d8aa726d2518b9962414c421951dc738f..47009cc660238e08faefea66b6ec6915f67e2674 100644
--- a/kayak_core/src/lib.rs
+++ b/kayak_core/src/lib.rs
@@ -1,6 +1,9 @@
 pub mod color;
 pub mod context;
+pub mod event;
 pub mod fragment;
+pub(crate) mod generational_arena;
+mod input_event;
 pub mod layout_cache;
 pub mod node;
 pub mod render_command;
@@ -10,19 +13,47 @@ pub mod tree;
 pub mod widget;
 pub mod widget_manager;
 
-pub(crate) mod generational_arena;
+use std::sync::{Arc, RwLock};
 
+pub use event::*;
+pub use fragment::Fragment;
 pub use generational_arena::{Arena, Index};
-
+pub use input_event::*;
+pub use kayak_render_macros::{render, rsx, widget};
 pub use widget::Widget;
 
-pub use kayak_render_macros::{render, rsx, widget};
+pub type Children =
+    Option<Arc<dyn Fn(Option<crate::Index>, &mut crate::context::KayakContext) + Send + Sync>>;
 
-pub use fragment::Fragment;
+#[derive(Clone)]
+pub struct OnEvent(
+    pub  Arc<
+        RwLock<dyn FnMut(&mut crate::context::KayakContext, &mut Event) + Send + Sync + 'static>,
+    >,
+);
+
+impl OnEvent {
+    pub fn new<F: FnMut(&mut crate::context::KayakContext, &mut Event) + Send + Sync + 'static>(
+        f: F,
+    ) -> OnEvent {
+        OnEvent(Arc::new(RwLock::new(f)))
+    }
+}
+
+// impl std::ops::Deref for OnEvent {
+//     type Target =
+//         Arc<RwLock<dyn FnMut(&mut crate::context::KayakContext, &mut Event) + Send + Sync>>;
+
+//     fn deref(&self) -> &Self::Target {
+//         &self.0
+//     }
+// }
 
-pub type Children = Option<
-    std::sync::Arc<dyn Fn(Option<crate::Index>, &mut crate::context::KayakContext) + Send + Sync>,
->;
+// impl std::ops::DerefMut for OnEvent {
+//     fn deref_mut(&mut self) -> &mut Self::Target {
+//         &mut self.0
+//     }
+// }
 
 pub mod derivative {
     pub use derivative::*;
diff --git a/kayak_core/src/node.rs b/kayak_core/src/node.rs
index 704cc010bed46b1df679c313a6a6bf89807d1391..47d79ca0c63d20eeb006ed1eb2347d561d3255b7 100644
--- a/kayak_core/src/node.rs
+++ b/kayak_core/src/node.rs
@@ -73,11 +73,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.layout_type {
                     StyleProp::Default => Some(morphorm::LayoutType::default()),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::LayoutType::default()),
                 };
             }
         }
-        return None;
+        return Some(morphorm::LayoutType::default());
     }
 
     fn position_type(&self, store: &'_ Self::Data) -> Option<morphorm::PositionType> {
@@ -86,11 +86,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.position_type {
                     StyleProp::Default => Some(morphorm::PositionType::default()),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::PositionType::default()),
                 };
             }
         }
-        return None;
+        return Some(morphorm::PositionType::default());
     }
 
     fn width(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -99,11 +99,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.width {
                     StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Stretch(1.0)),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Stretch(1.0));
     }
 
     fn height(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -112,11 +112,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.height {
                     StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Stretch(1.0)),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Stretch(1.0));
     }
 
     fn min_width(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -141,11 +141,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.left {
                     StyleProp::Default => Some(morphorm::Units::Auto),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Auto),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Auto);
     }
 
     fn right(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -154,11 +154,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.right {
                     StyleProp::Default => Some(morphorm::Units::Auto),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Auto),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Auto);
     }
 
     fn top(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -167,11 +167,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.top {
                     StyleProp::Default => Some(morphorm::Units::Auto),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Auto),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Auto);
     }
 
     fn bottom(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
@@ -180,11 +180,11 @@ impl<'a> morphorm::Node<'a> for NodeIndex {
                 return match node.styles.bottom {
                     StyleProp::Default => Some(morphorm::Units::Auto),
                     StyleProp::Value(prop) => Some(prop),
-                    _ => None,
+                    _ => Some(morphorm::Units::Auto),
                 };
             }
         }
-        return None;
+        return Some(morphorm::Units::Auto);
     }
 
     fn min_left(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
diff --git a/kayak_core/src/render_command.rs b/kayak_core/src/render_command.rs
index eb75d0b435e68a96ed89707ef33303c681247d90..31f034efcb8c6cbb7cd804da0fa2984288b605e4 100644
--- a/kayak_core/src/render_command.rs
+++ b/kayak_core/src/render_command.rs
@@ -1,6 +1,7 @@
 #[derive(Debug, Clone, PartialEq)]
 pub enum RenderCommand {
     Empty,
+    Window,
     Clip,
     Quad,
     Text {
diff --git a/kayak_core/src/render_primitive.rs b/kayak_core/src/render_primitive.rs
index 1c540547861fa4e6b2f8202ca7ecea1f3e80c1a4..6fa65a70890db73a6c8b68fc758cba027250934d 100644
--- a/kayak_core/src/render_primitive.rs
+++ b/kayak_core/src/render_primitive.rs
@@ -1,4 +1,9 @@
-use crate::{color::Color, layout_cache::Rect, render_command::RenderCommand, styles::Style};
+use crate::{
+    color::Color,
+    layout_cache::Rect,
+    render_command::RenderCommand,
+    styles::{Style, StyleProp},
+};
 
 #[derive(Debug, Clone, PartialEq)]
 pub enum RenderPrimitive {
@@ -34,13 +39,20 @@ impl From<&Style> for RenderPrimitive {
     fn from(style: &Style) -> Self {
         let render_command = style.render_command.resolve();
 
+        let background_color = if matches!(style.background_color, StyleProp::Default) {
+            Color::TRANSPARENT
+        } else {
+            style.background_color.resolve()
+        };
+
         match render_command {
+            RenderCommand::Window => Self::Empty,
             RenderCommand::Empty => Self::Empty,
             RenderCommand::Clip => Self::Clip {
                 layout: Rect::default(),
             },
             RenderCommand::Quad => Self::Quad {
-                background_color: style.background_color.resolve(),
+                background_color: background_color,
                 layout: Rect::default(),
             },
             RenderCommand::Text {
diff --git a/kayak_core/src/styles.rs b/kayak_core/src/styles.rs
index d75533a9d49f4e20fb5b41fae137eec3cfa2ac40..7302522dc86ee6b9be2791a77e83529928c3087f 100644
--- a/kayak_core/src/styles.rs
+++ b/kayak_core/src/styles.rs
@@ -49,7 +49,7 @@ pub struct Style {
 impl Default for Style {
     fn default() -> Self {
         Self {
-            background_color: StyleProp::Value(Color::TRANSPARENT),
+            background_color: StyleProp::Default,
             render_command: StyleProp::Value(RenderCommand::Empty),
             bottom: StyleProp::Default,
             color: StyleProp::Inherit,
diff --git a/kayak_core/src/widget.rs b/kayak_core/src/widget.rs
index 3e63d8701992694cb94cea79cb767e678d462c81..265e746b146414d59403e33df0780378cfbc3ba5 100644
--- a/kayak_core/src/widget.rs
+++ b/kayak_core/src/widget.rs
@@ -1,11 +1,13 @@
 use as_any::AsAny;
 
-use crate::{context::KayakContext, styles::Style, Index};
+use crate::{context::KayakContext, styles::Style, Event, Index};
 
 pub trait Widget: std::fmt::Debug + AsAny + Send + Sync {
     fn get_id(&self) -> Index;
     fn set_id(&mut self, id: Index);
     fn get_styles(&self) -> Option<Style>;
+    fn get_name(&self) -> String;
+    fn on_event(&mut self, context: &mut KayakContext, event: &mut Event);
     fn render(&mut self, context: &mut KayakContext);
 }
 
diff --git a/kayak_core/src/widget_manager.rs b/kayak_core/src/widget_manager.rs
index f4e3b702d4fa4eb6e8f3c418332e8f3e7481fcd6..f6792ba1fac87e91adfec08b447f420f9bf53935 100644
--- a/kayak_core/src/widget_manager.rs
+++ b/kayak_core/src/widget_manager.rs
@@ -1,6 +1,7 @@
 use crate::{
     layout_cache::LayoutCache,
     node::{Node, NodeBuilder, NodeIndex},
+    render_command::RenderCommand,
     render_primitive::RenderPrimitive,
     styles::Style,
     tree::Tree,
@@ -10,11 +11,12 @@ use as_any::Downcast;
 
 #[derive(Debug)]
 pub struct WidgetManager {
-    current_widgets: Arena<Option<Box<dyn Widget>>>,
+    pub(crate) current_widgets: Arena<Option<Box<dyn Widget>>>,
     pub(crate) dirty_render_nodes: Vec<Index>,
     pub(crate) dirty_nodes: Vec<Index>,
     pub(crate) nodes: Arena<Option<Node>>,
     pub tree: Tree,
+    pub node_tree: Tree,
     pub layout_cache: LayoutCache,
     current_z: f32,
 }
@@ -27,6 +29,7 @@ impl WidgetManager {
             dirty_nodes: Vec::new(),
             nodes: Arena::new(),
             tree: Tree::default(),
+            node_tree: Tree::default(),
             layout_cache: LayoutCache::default(),
             current_z: 0.0,
         }
@@ -63,23 +66,23 @@ impl WidgetManager {
                         self.dirty_nodes.remove(index);
                     }
 
-                    if &widget
-                        != self.current_widgets[*widget_id]
-                            .as_ref()
-                            .unwrap()
-                            .downcast_ref::<T>()
-                            .unwrap()
-                    {
-                        let boxed_widget: Box<dyn Widget> = Box::new(widget);
-                        *self.current_widgets[*widget_id].as_mut().unwrap() = boxed_widget;
-                        dbg!("Widget changed!");
-                        // Tell renderer that the nodes changed.
-                        self.dirty_render_nodes.push(*widget_id);
-                        return (true, *widget_id);
-                    } else {
-                        dbg!("No widget changes!");
-                        return (false, *widget_id);
-                    }
+                    // if &widget
+                    //     != self.current_widgets[*widget_id]
+                    //         .as_ref()
+                    //         .unwrap()
+                    //         .downcast_ref::<T>()
+                    //         .unwrap()
+                    // {
+                    let boxed_widget: Box<dyn Widget> = Box::new(widget);
+                    *self.current_widgets[*widget_id].as_mut().unwrap() = boxed_widget;
+                    dbg!("Widget changed!");
+                    // Tell renderer that the nodes changed.
+                    self.dirty_render_nodes.push(*widget_id);
+                    return (true, *widget_id);
+                    // } else {
+                    //     dbg!("No widget changes!");
+                    //     return (false, *widget_id);
+                    // }
                 }
             }
         }
@@ -169,7 +172,6 @@ impl WidgetManager {
                     z
                 }
             };
-            dbg!(current_z);
 
             let mut styles = dirty_widget.get_styles();
             if styles.is_some() {
@@ -181,19 +183,59 @@ impl WidgetManager {
                 .get(&dirty_node_index)
                 .cloned()
                 .unwrap_or(vec![]);
+            let styles = styles.unwrap_or(default_styles.clone());
+            if matches!(styles.render_command.resolve(), RenderCommand::Empty) {
+                continue;
+            }
             let mut node = NodeBuilder::empty()
                 .with_id(dirty_node_index)
-                .with_styles(styles.unwrap_or(default_styles.clone()))
+                .with_styles(styles)
                 .with_children(children)
                 .build();
             node.z = current_z;
 
             self.nodes[dirty_node_index] = Some(node);
         }
+
+        self.node_tree = self.build_nodes_tree();
+
+        // let mut last_parent = Index::default();
+        // let mut space_count_lookup = HashMap::<Index, u32>::new();
+        // let mut space_count: u32 = 0;
+        // for node in self.node_tree.down_iter() {
+        //     space_count_lookup.insert(node.0, space_count);
+        //     let child_widget = &self.current_widgets[node.0].as_ref().unwrap();
+        //     let (child_id, _) = node.0.into_raw_parts();
+        //     println!(
+        //         "{:indent$}Widget: {} {}",
+        //         "",
+        //         child_widget.get_name(),
+        //         child_id,
+        //         indent = space_count as usize,
+        //     );
+        //     if let Some(parent_id) = self.node_tree.parents.get(&node.0) {
+        //         let parent_widget = &self.current_widgets[*parent_id].as_ref().unwrap();
+        //         println!(
+        //             "{:indent$}parent: {} {}",
+        //             "",
+        //             parent_widget.get_name(),
+        //             parent_id.into_raw_parts().0,
+        //             indent = space_count as usize,
+        //         );
+        //         if last_parent != *parent_id {
+        //             if let Some(stored_space_count) = space_count_lookup.get(parent_id) {
+        //                 space_count = *stored_space_count;
+        //             }
+        //         }
+        //         last_parent = *parent_id;
+        //     }
+        //     space_count += 2;
+        // }
+        // panic!();
     }
 
     pub fn calculate_layout(&mut self) {
-        morphorm::layout(&mut self.layout_cache, &self.tree, &self.nodes);
+        morphorm::layout(&mut self.layout_cache, &self.node_tree, &self.nodes);
     }
 
     pub fn build_render_primitives(&self) -> Vec<RenderPrimitive> {
@@ -213,4 +255,63 @@ impl WidgetManager {
 
         render_primitives
     }
+
+    fn build_nodes_tree(&self) -> Tree {
+        let mut tree = Tree::default();
+        let (root_node_id, _) = self.current_widgets.iter().next().unwrap();
+        tree.root_node = root_node_id;
+        tree.children
+            .insert(tree.root_node, self.get_valid_node_children(tree.root_node));
+        for (widget_id, widget) in self.current_widgets.iter().skip(1) {
+            let widget_styles = widget.as_ref().unwrap().get_styles();
+            if let Some(widget_styles) = widget_styles {
+                // Only add widgets who have renderable nodes.
+                if widget_styles.render_command.resolve() != RenderCommand::Empty {
+                    let valid_children = self.get_valid_node_children(widget_id);
+                    tree.children.insert(widget_id, valid_children);
+                    let valid_parent = self.get_valid_parent(widget_id);
+                    if let Some(valid_parent) = valid_parent {
+                        tree.parents.insert(widget_id, valid_parent);
+                    }
+                }
+            }
+        }
+        tree
+    }
+
+    fn get_valid_node_children(&self, node_id: Index) -> Vec<Index> {
+        let mut children = Vec::new();
+        if let Some(node_children) = self.tree.children.get(&node_id) {
+            for child_id in node_children {
+                if let Some(child_widget) = &self.current_widgets[*child_id] {
+                    if let Some(child_styles) = child_widget.get_styles() {
+                        if child_styles.render_command.resolve() != RenderCommand::Empty {
+                            children.push(*child_id);
+                        } else {
+                            children.extend(self.get_valid_node_children(*child_id));
+                        }
+                    } else {
+                        children.extend(self.get_valid_node_children(*child_id));
+                    }
+                }
+            }
+        }
+
+        children
+    }
+
+    fn get_valid_parent(&self, node_id: Index) -> Option<Index> {
+        if let Some(parent_id) = self.tree.parents.get(&node_id) {
+            if let Some(parent_widget) = &self.current_widgets[*parent_id] {
+                if let Some(parent_styles) = parent_widget.get_styles() {
+                    if parent_styles.render_command.resolve() != RenderCommand::Empty {
+                        return Some(*parent_id);
+                    }
+                }
+
+                return self.get_valid_parent(*parent_id);
+            }
+        }
+        None
+    }
 }
diff --git a/kayak_render_macros/examples/main.rs b/kayak_render_macros/examples/main.rs
index 75d7cccc218b6da20316f5068594358dc9b1fa02..5fcb608ba84f0e35ce33195a5e0ffae507d891c2 100644
--- a/kayak_render_macros/examples/main.rs
+++ b/kayak_render_macros/examples/main.rs
@@ -11,6 +11,8 @@ struct Test {
     foo: u32,
     #[derivative(Debug = "ignore", PartialEq = "ignore")]
     children: Children,
+    #[derivative(Debug = "ignore", PartialEq = "ignore")]
+    pub on_event: Option<kayak_core::OnEvent>,
 }
 
 impl Widget for Test {
@@ -26,6 +28,14 @@ impl Widget for Test {
         todo!()
     }
 
+    fn get_name(&self) -> String {
+        todo!()
+    }
+
+    fn on_event(&mut self, _context: &mut KayakContext, _event: &mut kayak_core::Event) {
+        todo!()
+    }
+
     fn render(&mut self, _context: &mut KayakContext) {
         todo!()
     }
diff --git a/kayak_render_macros/src/children.rs b/kayak_render_macros/src/children.rs
index db5093c63243fa731c745bfd83d6454fa6f4614b..f948e6727cb1817f9b96c964ab349c6d73ab9471 100644
--- a/kayak_render_macros/src/children.rs
+++ b/kayak_render_macros/src/children.rs
@@ -16,10 +16,6 @@ impl Children {
         Children { nodes }
     }
 
-    pub fn len(&self) -> usize {
-        self.nodes.len()
-    }
-
     pub fn get_clonable_attributes(&self, index: usize) -> Vec<proc_macro2::TokenStream> {
         let mut tokens = Vec::new();
 
@@ -63,7 +59,7 @@ impl Children {
             .collect();
 
         match children_quotes.len() {
-            0 => quote! { Option::<()>::None },
+            0 => quote! { None },
             1 => {
                 let child = if children_quotes[0].to_string() == "{ }" {
                     quote! { None }
diff --git a/kayak_render_macros/src/function_component.rs b/kayak_render_macros/src/function_component.rs
index 55c82f3f44f0d6f323412c60d132bcbee13e4dd9..2ad9e3a416133e74f72da981fe378e9044f1562f 100644
--- a/kayak_render_macros/src/function_component.rs
+++ b/kayak_render_macros/src/function_component.rs
@@ -85,6 +85,13 @@ pub fn create_function_component(f: syn::ItemFn) -> TokenStream {
                 pub children: kayak_core::Children
             },
         ),
+        (
+            vec!["on_event : Option<kayak_core::OnEvent>"],
+            quote! {
+                #[derivative(Debug = "ignore", PartialEq = "ignore")]
+                pub on_event: Option<kayak_core::OnEvent>
+            },
+        ),
     ];
 
     for (names, token) in missing_struct_inputs {
@@ -144,8 +151,20 @@ pub fn create_function_component(f: syn::ItemFn) -> TokenStream {
                 self.styles.clone()
             }
 
+            fn get_name(&self) -> String {
+                String::from(stringify!(#struct_name))
+            }
+
+            fn on_event(&mut self, context: &mut ::kayak_core::context::KayakContext, event: &mut ::kayak_core::Event) {
+                if let Some(on_event) = self.on_event.as_ref() {
+                    if let Ok(mut on_event) = on_event.0.write() {
+                        on_event(context, event);
+                    }
+                }
+            }
+
             fn render(&mut self, context: &mut ::kayak_core::context::KayakContext) {
-                dbg!(stringify!(Rendering widget: #struct_name));
+                // dbg!(stringify!(Rendering widget: #struct_name));
                 let parent_id = self.get_id();
                 context.set_current_id(parent_id);
                 let parent_id = Some(parent_id);
diff --git a/kayak_render_macros/src/widget_attributes.rs b/kayak_render_macros/src/widget_attributes.rs
index 3f1c9db7ba677d7a7e15e0080f8a9d30b2e74551..020f54ae0add8e5b24f41b3ba064d5e16997bc36 100644
--- a/kayak_render_macros/src/widget_attributes.rs
+++ b/kayak_render_macros/src/widget_attributes.rs
@@ -83,21 +83,39 @@ impl<'a, 'c> ToTokens for CustomWidgetAttributes<'a, 'c> {
             })
             .collect();
 
-        if self.children.len() > 0 {
+        {
             let children_tuple = self.children.as_option_of_tuples_tokens();
             attrs.push(quote! {
                 children: #children_tuple
             });
         }
+
+        let missing = vec![
+            ("styles", quote! { styles: None }),
+            ("on_event", quote! { on_event: None }),
+        ];
+
+        for missed in missing {
+            if !self.attributes.iter().any(|attribute| {
+                attribute
+                    .ident()
+                    .to_token_stream()
+                    .to_string()
+                    .contains(missed.0)
+            }) {
+                attrs.push(missed.1);
+            }
+        }
+
         let quoted = if attrs.len() == 0 {
-            quote!({ id: kayak_core::Index::default(), styles: None, children: None })
+            quote!({ id: kayak_core::Index::default(), styles: None, children: None, on_event: None, })
         } else {
             if !self
                 .attributes
                 .iter()
                 .any(|attribute| attribute.ident().to_token_stream().to_string() == "styles")
             {
-                quote!({ #(#attrs),*, id: kayak_core::Index::default(), styles: None })
+                quote!({ #(#attrs),*, id: kayak_core::Index::default() })
             } else {
                 quote!({ #(#attrs),*, id: kayak_core::Index::default() })
             }