diff --git a/Cargo.toml b/Cargo.toml
index 9204a8053d4bcb606ba0382e8311aa5bbdd2a679..02ee2caf477c6d7415862b45acaf81e0a63bf22f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,6 +30,7 @@ resources = "1.1"
 
 [dev-dependencies]
 fastrand = "1.8"
+bevy-inspector-egui = "0.14"
 
 [[example]]
 name = "tabs"
diff --git a/examples/todo/todo.rs b/examples/todo/todo.rs
index 3072de064177cf0e072df87b7adc5658d4a69bc5..0e50bea1313e7655e2bd1742f11e9716f2d02130 100644
--- a/examples/todo/todo.rs
+++ b/examples/todo/todo.rs
@@ -1,4 +1,5 @@
 use bevy::prelude::*;
+use bevy_inspector_egui::WorldInspectorPlugin;
 use kayak_ui::prelude::{widgets::*, *};
 
 mod input;
@@ -105,6 +106,7 @@ fn main() {
     App::new()
         .insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
         .add_plugins(DefaultPlugins)
+        .add_plugin(WorldInspectorPlugin::new())
         .add_plugin(KayakContextPlugin)
         .add_plugin(KayakWidgets)
         .insert_non_send_resource(TodoList::new())
diff --git a/kayak_font/src/layout/glyph.rs b/kayak_font/src/layout/glyph.rs
index cfd33e3b8350e560c87784bb42f5831eb0239781..a7d7f8429634d18e409ad23cbfa7cdb29f96151f 100644
--- a/kayak_font/src/layout/glyph.rs
+++ b/kayak_font/src/layout/glyph.rs
@@ -1,5 +1,7 @@
+use bevy::reflect::{FromReflect, Reflect};
+
 /// Layout information for a renderable glyph.
-#[derive(Default, Debug, Clone, Copy, PartialEq)]
+#[derive(Default, Reflect, FromReflect, Debug, Clone, Copy, PartialEq)]
 pub struct GlyphRect {
     pub position: (f32, f32),
     pub size: (f32, f32),
diff --git a/kayak_font/src/layout/grapheme.rs b/kayak_font/src/layout/grapheme.rs
index 23cf11850eb7f027f9965489989a2e3697bb527b..df0ce15308f14e0dc548cdb1558b17415aa106cc 100644
--- a/kayak_font/src/layout/grapheme.rs
+++ b/kayak_font/src/layout/grapheme.rs
@@ -1,9 +1,11 @@
 use std::cmp::Ordering;
 
+use bevy::reflect::{FromReflect, Reflect};
+
 /// A representation of a grapheme cluster, as defined by [Unicode UAX #29].
 ///
 /// [Unicode UAX #29]: https://unicode.org/reports/tr29/
-#[derive(Default, Debug, Copy, Clone, PartialEq)]
+#[derive(Default, Debug, Reflect, FromReflect, Copy, Clone, PartialEq)]
 pub struct Grapheme {
     /// The index of the starting char within this grapheme, relative to the entire text content.
     pub char_index: usize,
diff --git a/kayak_font/src/layout/line.rs b/kayak_font/src/layout/line.rs
index bd6a688970c517c33916373dcd904e427aca3a3c..41e07030599b773aa1bb757189c6f3bbf2482f72 100644
--- a/kayak_font/src/layout/line.rs
+++ b/kayak_font/src/layout/line.rs
@@ -1,10 +1,12 @@
+use bevy::reflect::{FromReflect, Reflect};
+
 use crate::layout::grapheme::Grapheme;
 use std::cmp::Ordering;
 use std::ops::Index;
 use std::slice::SliceIndex;
 
 /// Contains details for a calculated line of text.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Reflect, FromReflect, Debug, PartialEq)]
 pub struct Line {
     grapheme_index: usize,
     graphemes: Vec<Grapheme>,
diff --git a/kayak_font/src/layout/text.rs b/kayak_font/src/layout/text.rs
index fd646a3a1ce8fde5282eecd50deb0b6e2c70aaf5..8d5a59031799cf9979a846bcf526b518e2dd116d 100644
--- a/kayak_font/src/layout/text.rs
+++ b/kayak_font/src/layout/text.rs
@@ -1,8 +1,10 @@
+use bevy::reflect::{FromReflect, Reflect};
+
 use crate::{GlyphRect, Line, RowCol};
 use std::cmp::Ordering;
 
 /// The text alignment.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Reflect, FromReflect, Debug, PartialEq, Eq)]
 pub enum Alignment {
     Start,
     Middle,
@@ -10,7 +12,7 @@ pub enum Alignment {
 }
 
 /// Properties to control text layout.
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Reflect, FromReflect, Debug, PartialEq)]
 pub struct TextProperties {
     /// The font size (in pixels).
     pub font_size: f32,
@@ -39,7 +41,7 @@ impl Default for TextProperties {
 /// Calculated text layout.
 ///
 /// This can be retrieved using [`measure`](crate::KayakFont::measure).
-#[derive(Clone, Debug, Default, PartialEq)]
+#[derive(Clone, Reflect, FromReflect, Debug, Default, PartialEq)]
 pub struct TextLayout {
     glyphs: Vec<GlyphRect>,
     lines: Vec<Line>,
diff --git a/src/children.rs b/src/children.rs
index c2e2de6915d696c5fcc711d0fe562bcc4fe90ff1..d5dd84503177b45045a2eab4141f3a26cd90078d 100644
--- a/src/children.rs
+++ b/src/children.rs
@@ -3,7 +3,8 @@ use bevy::prelude::*;
 use crate::prelude::KayakWidgetContext;
 
 /// Defers widgets being added to the widget tree.
-#[derive(Component, Debug, Default, Clone, PartialEq, Eq)]
+#[derive(Component, Reflect, Debug, Default, Clone, PartialEq, Eq)]
+#[reflect(Component)]
 pub struct KChildren {
     inner: Vec<Entity>,
 }
diff --git a/src/context.rs b/src/context.rs
index a8389ab1dc1a75dce070d1f43328bbe51b996bc3..4cac17487e7d4c9e2b924d9c588b43f0d2909f98 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -12,6 +12,7 @@ use crate::{
     children::KChildren,
     clone_component::{clone_state, clone_system, EntityCloneSystems, PreviousWidget},
     context_entities::ContextEntities,
+    cursor::PointerEvents,
     event_dispatcher::EventDispatcher,
     focus_tree::FocusTree,
     input::query_world,
@@ -20,14 +21,18 @@ use crate::{
     node::{DirtyNode, WrappedIndex},
     prelude::KayakWidgetContext,
     render_primitive::RenderPrimitive,
-    styles::KStyle,
+    styles::{
+        Corner, Edge, KCursorIcon, KPositionType, KStyle, LayoutType, RenderCommand, StyleProp,
+        Units,
+    },
     tree::{Change, Tree},
     widget_state::WidgetState,
     Focusable, KayakUIPlugin, WindowSize,
 };
 
 /// A tag component representing when a widget has been mounted(added to the tree).
-#[derive(Component)]
+#[derive(Component, Reflect, Default)]
+#[reflect(Component)]
 pub struct Mounted;
 
 const UPDATE_DEPTH: u32 = 0;
@@ -976,6 +981,25 @@ impl Plugin for KayakContextPlugin {
             .add_system_to_stage(CoreStage::PostUpdate, update_widgets_sys.at_start())
             .add_system_to_stage(CoreStage::PostUpdate, calculate_ui.at_end())
             .add_system(crate::window_size::update_window_size);
+
+        // Register reflection types.
+        // A bit annoying..
+        app.register_type::<KStyle>()
+            .register_type::<KChildren>()
+            .register_type::<WidgetName>()
+            .register_type::<StyleProp<Color>>()
+            .register_type::<StyleProp<Corner<f32>>>()
+            .register_type::<StyleProp<Edge<f32>>>()
+            .register_type::<StyleProp<Units>>()
+            .register_type::<StyleProp<KCursorIcon>>()
+            .register_type::<StyleProp<String>>()
+            .register_type::<StyleProp<f32>>()
+            .register_type::<StyleProp<LayoutType>>()
+            .register_type::<StyleProp<Edge<Units>>>()
+            .register_type::<StyleProp<PointerEvents>>()
+            .register_type::<StyleProp<KPositionType>>()
+            .register_type::<StyleProp<RenderCommand>>()
+            .register_type::<StyleProp<i32>>();
     }
 }
 
@@ -1040,9 +1064,17 @@ fn calculate_ui(world: &mut World) {
 
 /// A simple component that stores the type name of a widget
 /// This is used by Kayak in order to find out which systems to run.
-#[derive(Component, Debug, Clone, PartialEq, Eq)]
+#[derive(Component, Reflect, Debug, Clone, PartialEq, Eq)]
+#[reflect(Component)]
 pub struct WidgetName(pub String);
 
+impl Default for WidgetName {
+    fn default() -> Self {
+        log::warn!("You did not specify a widget name for a widget!");
+        Self("NO_NAME".to_string())
+    }
+}
+
 impl From<String> for WidgetName {
     fn from(value: String) -> Self {
         WidgetName(value)
diff --git a/src/cursor.rs b/src/cursor.rs
index 2b4539050e4b86d5e3c0aef5be631a9656073f4f..b3df333cc497d41e653d6f4e4973ea23acf92010 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -1,47 +1,49 @@
-/// Controls how the cursor interacts on a given node
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum PointerEvents {
-    /// Allow all pointer events on this node and its children
-    All,
-    /// Allow pointer events on this node but not on its children
-    SelfOnly,
-    /// Allow pointer events on this node's children but not on itself
-    ChildrenOnly,
-    /// Disallow all pointer events on this node and its children
-    None,
-}
-
-impl Default for PointerEvents {
-    fn default() -> Self {
-        Self::All
-    }
-}
-
-#[derive(Default, Debug, Copy, Clone, PartialEq)]
-pub struct CursorEvent {
-    pub pressed: bool,
-    pub just_pressed: bool,
-    pub just_released: bool,
-    pub position: (f32, f32),
-}
-
-/// An event created on scroll
-#[derive(Default, Debug, Copy, Clone, PartialEq)]
-pub struct ScrollEvent {
-    /// The amount scrolled
-    pub delta: ScrollUnit,
-}
-
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum ScrollUnit {
-    /// A scroll unit that goes by a "line of text"
-    Line { x: f32, y: f32 },
-    /// A scroll unit that goes by individual pixels
-    Pixel { x: f32, y: f32 },
-}
-
-impl Default for ScrollUnit {
-    fn default() -> Self {
-        ScrollUnit::Pixel { x: 0.0, y: 0.0 }
-    }
-}
+use bevy::reflect::{FromReflect, Reflect};
+
+/// Controls how the cursor interacts on a given node
+#[derive(Debug, Reflect, FromReflect, Copy, Clone, PartialEq, Eq)]
+pub enum PointerEvents {
+    /// Allow all pointer events on this node and its children
+    All,
+    /// Allow pointer events on this node but not on its children
+    SelfOnly,
+    /// Allow pointer events on this node's children but not on itself
+    ChildrenOnly,
+    /// Disallow all pointer events on this node and its children
+    None,
+}
+
+impl Default for PointerEvents {
+    fn default() -> Self {
+        Self::All
+    }
+}
+
+#[derive(Default, Debug, Copy, Clone, PartialEq)]
+pub struct CursorEvent {
+    pub pressed: bool,
+    pub just_pressed: bool,
+    pub just_released: bool,
+    pub position: (f32, f32),
+}
+
+/// An event created on scroll
+#[derive(Default, Debug, Copy, Clone, PartialEq)]
+pub struct ScrollEvent {
+    /// The amount scrolled
+    pub delta: ScrollUnit,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum ScrollUnit {
+    /// A scroll unit that goes by a "line of text"
+    Line { x: f32, y: f32 },
+    /// A scroll unit that goes by individual pixels
+    Pixel { x: f32, y: f32 },
+}
+
+impl Default for ScrollUnit {
+    fn default() -> Self {
+        ScrollUnit::Pixel { x: 0.0, y: 0.0 }
+    }
+}
diff --git a/src/focus_tree.rs b/src/focus_tree.rs
index 038e8c66a4b1cdfdf7140167ae8295cf93f496ec..b3dfbc066679cd5026d51183506b7e6cfc25dfc1 100644
--- a/src/focus_tree.rs
+++ b/src/focus_tree.rs
@@ -1,8 +1,12 @@
-use bevy::{prelude::Component, utils::HashMap};
+use bevy::{
+    prelude::{Component, Reflect, ReflectComponent},
+    utils::HashMap,
+};
 
 use crate::{node::WrappedIndex, prelude::Tree};
 
-#[derive(Component, Default, Clone, Copy)]
+#[derive(Component, Reflect, Default, Clone, Copy)]
+#[reflect(Component)]
 pub struct Focusable;
 
 #[derive(Debug, Default, PartialEq, Eq)]
diff --git a/src/layout.rs b/src/layout.rs
index 8f49ce57135f0da52018c11c4277e02bf73e2650..3cffb5bb5922cae2a0067882d2bfa9ff034bff81 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -1,13 +1,16 @@
 use std::collections::hash_map::Iter;
 use std::collections::HashMap;
 
-use bevy::prelude::{Entity, Query};
+use bevy::{
+    prelude::{Entity, Query},
+    reflect::{FromReflect, Reflect},
+};
 use morphorm::Cache;
 pub use morphorm::GeometryChanged;
 
 use crate::node::WrappedIndex;
 
-#[derive(Debug, Default, Clone, Copy, PartialEq)]
+#[derive(Debug, Reflect, FromReflect, Default, Clone, Copy, PartialEq)]
 pub struct Rect {
     pub posx: f32,
     pub posy: f32,
diff --git a/src/node.rs b/src/node.rs
index d10ba9eb9c668b656dadc2e2847fb1b925b984f1..9c655a2613d988c6712df13a0f1fa37c8ebc1f8f 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -1,4 +1,7 @@
-use bevy::prelude::{Component, Entity, Query};
+use bevy::{
+    prelude::{Component, Entity, Query, Reflect, ReflectComponent},
+    reflect::FromReflect,
+};
 
 use crate::{
     render_primitive::RenderPrimitive,
@@ -9,7 +12,8 @@ use crate::{
 pub struct DirtyNode;
 
 /// A widget node used for building the layout tree
-#[derive(Debug, Clone, PartialEq, Component)]
+#[derive(Debug, Reflect, Clone, PartialEq, Component)]
+#[reflect(Component)]
 pub struct Node {
     /// The list of children directly under this node
     pub children: Vec<WrappedIndex>,
@@ -107,7 +111,7 @@ impl NodeBuilder {
     }
 }
 
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Reflect, FromReflect, Clone, Copy, Hash, PartialEq, Eq)]
 pub struct WrappedIndex(pub Entity);
 
 impl<'a> morphorm::Node<'a> for WrappedIndex {
@@ -117,7 +121,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.layout_type {
                 StyleProp::Default => Some(morphorm::LayoutType::default()),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::LayoutType::default()),
             };
         }
@@ -128,7 +132,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.position_type {
                 StyleProp::Default => Some(morphorm::PositionType::default()),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::PositionType::default()),
             };
         }
@@ -139,7 +143,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.width {
                 StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Stretch(1.0)),
             };
         }
@@ -150,7 +154,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.height {
                 StyleProp::Default => Some(morphorm::Units::Stretch(1.0)),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Stretch(1.0)),
             };
         }
@@ -161,7 +165,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.min_width {
                 StyleProp::Default => Some(morphorm::Units::Pixels(0.0)),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -172,7 +176,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.min_height {
                 StyleProp::Default => Some(morphorm::Units::Pixels(0.0)),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -183,7 +187,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.max_width {
                 StyleProp::Default => Some(morphorm::Units::Auto),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -194,7 +198,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.max_height {
                 StyleProp::Default => Some(morphorm::Units::Auto),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -206,10 +210,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.left {
                 StyleProp::Default => match node.resolved_styles.offset {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.left),
+                    StyleProp::Value(prop) => Some(prop.left.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -221,10 +225,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.right {
                 StyleProp::Default => match node.resolved_styles.offset {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.right),
+                    StyleProp::Value(prop) => Some(prop.right.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -236,10 +240,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.top {
                 StyleProp::Default => match node.resolved_styles.offset {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.top),
+                    StyleProp::Value(prop) => Some(prop.top.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -251,10 +255,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.bottom {
                 StyleProp::Default => match node.resolved_styles.offset {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.bottom),
+                    StyleProp::Value(prop) => Some(prop.bottom.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -298,10 +302,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.padding_left {
                 StyleProp::Default => match node.resolved_styles.padding {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.left),
+                    StyleProp::Value(prop) => Some(prop.left.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -313,10 +317,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.padding_right {
                 StyleProp::Default => match node.resolved_styles.padding {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.right),
+                    StyleProp::Value(prop) => Some(prop.right.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -328,10 +332,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.padding_top {
                 StyleProp::Default => match node.resolved_styles.padding {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.top),
+                    StyleProp::Value(prop) => Some(prop.top.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -343,10 +347,10 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
             return match node.resolved_styles.padding_bottom {
                 StyleProp::Default => match node.resolved_styles.padding {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(prop.bottom),
+                    StyleProp::Value(prop) => Some(prop.bottom.into()),
                     _ => Some(morphorm::Units::Auto),
                 },
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -357,7 +361,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.row_between {
                 StyleProp::Default => Some(morphorm::Units::Auto),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
@@ -368,7 +372,7 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         if let Ok(node) = store.get(self.0) {
             return match node.resolved_styles.col_between {
                 StyleProp::Default => Some(morphorm::Units::Auto),
-                StyleProp::Value(prop) => Some(prop),
+                StyleProp::Value(prop) => Some(prop.into()),
                 _ => Some(morphorm::Units::Auto),
             };
         }
diff --git a/src/render_primitive.rs b/src/render_primitive.rs
index 3a3d95caa8abaaaf5669ddc4233137b2e7ad4df4..9c3fa2d6820b8bc656199be97f0ffffe9d9e30aa 100644
--- a/src/render_primitive.rs
+++ b/src/render_primitive.rs
@@ -2,10 +2,13 @@ use crate::{
     layout::Rect,
     styles::{Corner, Edge, KStyle, RenderCommand},
 };
-use bevy::prelude::{Color, Handle, Image, Vec2};
+use bevy::{
+    prelude::{Color, Handle, Image, Vec2},
+    reflect::Reflect,
+};
 use kayak_font::{TextLayout, TextProperties};
 
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Reflect, Clone, PartialEq)]
 pub enum RenderPrimitive {
     Empty,
     Clip {
diff --git a/src/styles/corner.rs b/src/styles/corner.rs
index dfbfcdbbfeb720ca06d25819392e2e33fa379f54..fa02cdd1f73f6542bce7e84fced2185c68ab332a 100644
--- a/src/styles/corner.rs
+++ b/src/styles/corner.rs
@@ -1,234 +1,236 @@
-use std::ops::{Mul, MulAssign};
-
-/// A struct for defining properties related to the corners of widgets
-///
-/// This is useful for things like border radii, etc.
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
-pub struct Corner<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    /// The value of the top-left corner
-    pub top_left: T,
-    /// The value of the top-right corner
-    pub top_right: T,
-    /// The value of the bottom-left corner
-    pub bottom_left: T,
-    /// The value of the bottom-right corner
-    pub bottom_right: T,
-}
-
-impl<T> Corner<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    /// Creates a new `Corner` with values individually specified for each corner
-    ///
-    /// # Arguments
-    ///
-    /// * `top_left`: The top-left corner value
-    /// * `top_right`: The top_-right corner value
-    /// * `bottom_left`: The bottom_-left corner value
-    /// * `bottom_right`: The bottom_-right corner value
-    ///
-    pub fn new(top_left: T, top_right: T, bottom_left: T, bottom_right: T) -> Self {
-        Self {
-            top_left,
-            top_right,
-            bottom_left,
-            bottom_right,
-        }
-    }
-
-    /// Creates a new `Corner` with matching top corners and matching bottom corners
-    ///
-    /// # Arguments
-    ///
-    /// * `top`: The value of the top corners
-    /// * `bottom`: The value of the bottom corners
-    ///
-    /// ```
-    /// # use kayak_core::styles::Corner;
-    /// // Creates a `Corner` with only the top corners rounded
-    /// let corner_radius = Corner::vertical(10.0, 0.0);
-    ///
-    /// // Creates a `Corner` with only the bottom corners rounded
-    /// let corner_radius = Corner::vertical(0.0, 10.0);
-    /// ```
-    pub fn vertical(top: T, bottom: T) -> Self {
-        Self {
-            top_left: top,
-            top_right: top,
-            bottom_left: bottom,
-            bottom_right: bottom,
-        }
-    }
-
-    /// Creates a new `Corner` with matching left corners and matching right corners
-    ///
-    /// # Arguments
-    ///
-    /// * `left`: The value of the left corners
-    /// * `right`: The value of the right corners
-    ///
-    /// ```
-    /// # use kayak_core::styles::Corner;
-    /// // Creates a `Corner` with only the left corners rounded
-    /// let corner_radius = Corner::horizontal(10.0, 0.0);
-    ///
-    /// // Creates a `Corner` with only the right corners rounded
-    /// let corner_radius = Corner::horizontal(0.0, 10.0);
-    /// ```
-    pub fn horizontal(left: T, right: T) -> Self {
-        Self {
-            top_left: left,
-            top_right: right,
-            bottom_left: left,
-            bottom_right: right,
-        }
-    }
-
-    /// Creates a new `Corner` with all corners having the same value
-    ///
-    /// # Arguments
-    ///
-    /// * `value`: The value of all corners
-    ///
-    pub fn all(value: T) -> Self {
-        Self {
-            top_left: value,
-            top_right: value,
-            bottom_left: value,
-            bottom_right: value,
-        }
-    }
-
-    /// Converts this `Corner` into a tuple matching `(Top Left, Top Right, Bottom Left, Bottom Right)`
-    pub fn into_tuple(self) -> (T, T, T, T) {
-        (
-            self.top_left,
-            self.top_right,
-            self.bottom_left,
-            self.bottom_right,
-        )
-    }
-}
-
-impl<T> From<Corner<T>> for (T, T, T, T)
-where
-    T: Copy + Default + PartialEq,
-{
-    /// Creates a tuple matching the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
-    fn from(edge: Corner<T>) -> Self {
-        edge.into_tuple()
-    }
-}
-
-impl<T> From<T> for Corner<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    fn from(value: T) -> Self {
-        Corner::all(value)
-    }
-}
-
-impl<T> From<(T, T, T, T)> for Corner<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    /// Converts the tuple according to the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
-    fn from(value: (T, T, T, T)) -> Self {
-        Corner::new(value.0, value.1, value.2, value.3)
-    }
-}
-
-impl<T> Mul<T> for Corner<T>
-where
-    T: Copy + Default + PartialEq + Mul<Output = T>,
-{
-    type Output = Self;
-
-    fn mul(self, rhs: T) -> Self::Output {
-        Self {
-            top_left: self.top_left * rhs,
-            top_right: self.top_right * rhs,
-            bottom_left: self.bottom_left * rhs,
-            bottom_right: self.bottom_right * rhs,
-        }
-    }
-}
-
-impl<T> Mul<Corner<T>> for Corner<T>
-where
-    T: Copy + Default + PartialEq + Mul<Output = T>,
-{
-    type Output = Self;
-
-    fn mul(self, rhs: Corner<T>) -> Self::Output {
-        Self {
-            top_left: rhs.top_left * self.top_left,
-            top_right: rhs.top_right * self.top_right,
-            bottom_left: rhs.bottom_left * self.bottom_left,
-            bottom_right: rhs.bottom_right * self.bottom_right,
-        }
-    }
-}
-
-impl<T> MulAssign<T> for Corner<T>
-where
-    T: Copy + Default + PartialEq + MulAssign,
-{
-    fn mul_assign(&mut self, rhs: T) {
-        self.top_left *= rhs;
-        self.top_right *= rhs;
-        self.bottom_left *= rhs;
-        self.bottom_right *= rhs;
-    }
-}
-
-impl<T> MulAssign<Corner<T>> for Corner<T>
-where
-    T: Copy + Default + PartialEq + MulAssign,
-{
-    fn mul_assign(&mut self, rhs: Corner<T>) {
-        self.top_left *= rhs.top_left;
-        self.top_right *= rhs.top_right;
-        self.bottom_left *= rhs.bottom_left;
-        self.bottom_right *= rhs.bottom_right;
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::Corner;
-
-    #[test]
-    fn tuples_should_convert_to_corner() {
-        let expected = (1.0, 2.0, 3.0, 4.0);
-        let corner: Corner<f32> = expected.into();
-        assert_eq!(expected, corner.into_tuple());
-
-        let expected = (1.0, 1.0, 1.0, 1.0);
-        let corner: Corner<f32> = (expected.0).into();
-        assert_eq!(expected, corner.into_tuple());
-
-        let expected = (1.0, 1.0, 1.0, 1.0);
-        let corner: Corner<f32> = expected.0.into();
-        assert_eq!(expected, corner.into_tuple());
-    }
-
-    #[test]
-    fn multiplication_should_work_on_corners() {
-        let expected = (10.0, 20.0, 30.0, 40.0);
-        let mut corner = Corner::new(1.0, 2.0, 3.0, 4.0);
-
-        // Basic multiplication
-        let multiplied = corner * 10.0;
-        assert_eq!(expected, multiplied.into_tuple());
-
-        // Multiply and assign
-        corner *= 10.0;
-        assert_eq!(expected, corner.into_tuple());
-    }
-}
+use std::ops::{Mul, MulAssign};
+
+use bevy::reflect::{FromReflect, Reflect};
+
+/// A struct for defining properties related to the corners of widgets
+///
+/// This is useful for things like border radii, etc.
+#[derive(Debug, Default, Reflect, FromReflect, Copy, Clone, PartialEq, Eq)]
+pub struct Corner<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// The value of the top-left corner
+    pub top_left: T,
+    /// The value of the top-right corner
+    pub top_right: T,
+    /// The value of the bottom-left corner
+    pub bottom_left: T,
+    /// The value of the bottom-right corner
+    pub bottom_right: T,
+}
+
+impl<T> Corner<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// Creates a new `Corner` with values individually specified for each corner
+    ///
+    /// # Arguments
+    ///
+    /// * `top_left`: The top-left corner value
+    /// * `top_right`: The top_-right corner value
+    /// * `bottom_left`: The bottom_-left corner value
+    /// * `bottom_right`: The bottom_-right corner value
+    ///
+    pub fn new(top_left: T, top_right: T, bottom_left: T, bottom_right: T) -> Self {
+        Self {
+            top_left,
+            top_right,
+            bottom_left,
+            bottom_right,
+        }
+    }
+
+    /// Creates a new `Corner` with matching top corners and matching bottom corners
+    ///
+    /// # Arguments
+    ///
+    /// * `top`: The value of the top corners
+    /// * `bottom`: The value of the bottom corners
+    ///
+    /// ```
+    /// # use kayak_core::styles::Corner;
+    /// // Creates a `Corner` with only the top corners rounded
+    /// let corner_radius = Corner::vertical(10.0, 0.0);
+    ///
+    /// // Creates a `Corner` with only the bottom corners rounded
+    /// let corner_radius = Corner::vertical(0.0, 10.0);
+    /// ```
+    pub fn vertical(top: T, bottom: T) -> Self {
+        Self {
+            top_left: top,
+            top_right: top,
+            bottom_left: bottom,
+            bottom_right: bottom,
+        }
+    }
+
+    /// Creates a new `Corner` with matching left corners and matching right corners
+    ///
+    /// # Arguments
+    ///
+    /// * `left`: The value of the left corners
+    /// * `right`: The value of the right corners
+    ///
+    /// ```
+    /// # use kayak_core::styles::Corner;
+    /// // Creates a `Corner` with only the left corners rounded
+    /// let corner_radius = Corner::horizontal(10.0, 0.0);
+    ///
+    /// // Creates a `Corner` with only the right corners rounded
+    /// let corner_radius = Corner::horizontal(0.0, 10.0);
+    /// ```
+    pub fn horizontal(left: T, right: T) -> Self {
+        Self {
+            top_left: left,
+            top_right: right,
+            bottom_left: left,
+            bottom_right: right,
+        }
+    }
+
+    /// Creates a new `Corner` with all corners having the same value
+    ///
+    /// # Arguments
+    ///
+    /// * `value`: The value of all corners
+    ///
+    pub fn all(value: T) -> Self {
+        Self {
+            top_left: value,
+            top_right: value,
+            bottom_left: value,
+            bottom_right: value,
+        }
+    }
+
+    /// Converts this `Corner` into a tuple matching `(Top Left, Top Right, Bottom Left, Bottom Right)`
+    pub fn into_tuple(self) -> (T, T, T, T) {
+        (
+            self.top_left,
+            self.top_right,
+            self.bottom_left,
+            self.bottom_right,
+        )
+    }
+}
+
+impl<T> From<Corner<T>> for (T, T, T, T)
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// Creates a tuple matching the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
+    fn from(edge: Corner<T>) -> Self {
+        edge.into_tuple()
+    }
+}
+
+impl<T> From<T> for Corner<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    fn from(value: T) -> Self {
+        Corner::all(value)
+    }
+}
+
+impl<T> From<(T, T, T, T)> for Corner<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// Converts the tuple according to the pattern: `(Top Left, Top Right, Bottom Left, Bottom Right)`
+    fn from(value: (T, T, T, T)) -> Self {
+        Corner::new(value.0, value.1, value.2, value.3)
+    }
+}
+
+impl<T> Mul<T> for Corner<T>
+where
+    T: Copy + Default + PartialEq + Mul<Output = T> + Reflect,
+{
+    type Output = Self;
+
+    fn mul(self, rhs: T) -> Self::Output {
+        Self {
+            top_left: self.top_left * rhs,
+            top_right: self.top_right * rhs,
+            bottom_left: self.bottom_left * rhs,
+            bottom_right: self.bottom_right * rhs,
+        }
+    }
+}
+
+impl<T> Mul<Corner<T>> for Corner<T>
+where
+    T: Copy + Default + PartialEq + Mul<Output = T> + Reflect,
+{
+    type Output = Self;
+
+    fn mul(self, rhs: Corner<T>) -> Self::Output {
+        Self {
+            top_left: rhs.top_left * self.top_left,
+            top_right: rhs.top_right * self.top_right,
+            bottom_left: rhs.bottom_left * self.bottom_left,
+            bottom_right: rhs.bottom_right * self.bottom_right,
+        }
+    }
+}
+
+impl<T> MulAssign<T> for Corner<T>
+where
+    T: Copy + Default + PartialEq + MulAssign + Reflect,
+{
+    fn mul_assign(&mut self, rhs: T) {
+        self.top_left *= rhs;
+        self.top_right *= rhs;
+        self.bottom_left *= rhs;
+        self.bottom_right *= rhs;
+    }
+}
+
+impl<T> MulAssign<Corner<T>> for Corner<T>
+where
+    T: Copy + Default + PartialEq + MulAssign + Reflect,
+{
+    fn mul_assign(&mut self, rhs: Corner<T>) {
+        self.top_left *= rhs.top_left;
+        self.top_right *= rhs.top_right;
+        self.bottom_left *= rhs.bottom_left;
+        self.bottom_right *= rhs.bottom_right;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Corner;
+
+    #[test]
+    fn tuples_should_convert_to_corner() {
+        let expected = (1.0, 2.0, 3.0, 4.0);
+        let corner: Corner<f32> = expected.into();
+        assert_eq!(expected, corner.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let corner: Corner<f32> = (expected.0).into();
+        assert_eq!(expected, corner.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let corner: Corner<f32> = expected.0.into();
+        assert_eq!(expected, corner.into_tuple());
+    }
+
+    #[test]
+    fn multiplication_should_work_on_corners() {
+        let expected = (10.0, 20.0, 30.0, 40.0);
+        let mut corner = Corner::new(1.0, 2.0, 3.0, 4.0);
+
+        // Basic multiplication
+        let multiplied = corner * 10.0;
+        assert_eq!(expected, multiplied.into_tuple());
+
+        // Multiply and assign
+        corner *= 10.0;
+        assert_eq!(expected, corner.into_tuple());
+    }
+}
diff --git a/src/styles/edge.rs b/src/styles/edge.rs
index dabef3afc026612cdf66b4c9806a7f75183485b2..b11e1bc2de636b494bfbdf7e04807179ecdf784e 100644
--- a/src/styles/edge.rs
+++ b/src/styles/edge.rs
@@ -1,208 +1,210 @@
-use std::ops::{Mul, MulAssign};
-
-/// A struct for defining properties related to the edges of widgets
-///
-/// This is useful for things like borders, padding, etc.
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
-pub struct Edge<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    /// The value of the top edge
-    pub top: T,
-    /// The value of the right edge
-    pub right: T,
-    /// The value of the bottom edge
-    pub bottom: T,
-    /// The value of the left edge
-    pub left: T,
-}
-
-impl<T> Edge<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    /// Creates a new `Edge` with values individually specified for each edge
-    ///
-    /// # Arguments
-    ///
-    /// * `top`: The top edge value
-    /// * `right`: The right edge value
-    /// * `bottom`: The bottom edge value
-    /// * `left`: The left edge value
-    ///
-    pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
-        Self {
-            top,
-            right,
-            bottom,
-            left,
-        }
-    }
-
-    /// Creates a new `Edge` with matching vertical edges and matching horizontal edges
-    ///
-    /// # Arguments
-    ///
-    /// * `vertical`: The value of the vertical edges
-    /// * `horizontal`: The value of the horizontal edges
-    ///
-    pub fn axis(vertical: T, horizontal: T) -> Self {
-        Self {
-            top: vertical,
-            right: horizontal,
-            bottom: vertical,
-            left: horizontal,
-        }
-    }
-
-    /// Creates a new `Edge` with all edges having the same value
-    ///
-    /// # Arguments
-    ///
-    /// * `value`: The value of all edges
-    ///
-    pub fn all(value: T) -> Self {
-        Self {
-            top: value,
-            right: value,
-            bottom: value,
-            left: value,
-        }
-    }
-
-    /// Converts this `Edge` into a tuple matching `(Top, Right, Bottom, Left)`
-    pub fn into_tuple(self) -> (T, T, T, T) {
-        (self.top, self.right, self.bottom, self.left)
-    }
-}
-
-impl<T> From<Edge<T>> for (T, T, T, T)
-where
-    T: Copy + Default + PartialEq,
-{
-    fn from(edge: Edge<T>) -> Self {
-        edge.into_tuple()
-    }
-}
-
-impl<T> From<T> for Edge<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    fn from(value: T) -> Self {
-        Edge::all(value)
-    }
-}
-
-impl<T> From<(T, T)> for Edge<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    fn from(value: (T, T)) -> Self {
-        Edge::axis(value.0, value.1)
-    }
-}
-
-impl<T> From<(T, T, T, T)> for Edge<T>
-where
-    T: Copy + Default + PartialEq,
-{
-    fn from(value: (T, T, T, T)) -> Self {
-        Edge::new(value.0, value.1, value.2, value.3)
-    }
-}
-
-impl<T> Mul<T> for Edge<T>
-where
-    T: Copy + Default + PartialEq + Mul<Output = T>,
-{
-    type Output = Self;
-
-    fn mul(self, rhs: T) -> Self::Output {
-        Self {
-            top: self.top * rhs,
-            right: self.right * rhs,
-            bottom: self.bottom * rhs,
-            left: self.left * rhs,
-        }
-    }
-}
-
-impl<T> Mul<Edge<T>> for Edge<T>
-where
-    T: Copy + Default + PartialEq + Mul<Output = T>,
-{
-    type Output = Self;
-
-    fn mul(self, rhs: Edge<T>) -> Self::Output {
-        Self {
-            top: rhs.top * self.top,
-            right: rhs.right * self.right,
-            bottom: rhs.bottom * self.bottom,
-            left: rhs.left * self.left,
-        }
-    }
-}
-
-impl<T> MulAssign<T> for Edge<T>
-where
-    T: Copy + Default + PartialEq + MulAssign,
-{
-    fn mul_assign(&mut self, rhs: T) {
-        self.top *= rhs;
-        self.right *= rhs;
-        self.bottom *= rhs;
-        self.left *= rhs;
-    }
-}
-
-impl<T> MulAssign<Edge<T>> for Edge<T>
-where
-    T: Copy + Default + PartialEq + MulAssign,
-{
-    fn mul_assign(&mut self, rhs: Edge<T>) {
-        self.top *= rhs.top;
-        self.right *= rhs.right;
-        self.bottom *= rhs.bottom;
-        self.left *= rhs.left;
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::Edge;
-
-    #[test]
-    fn tuples_should_convert_to_edge() {
-        let expected = (1.0, 2.0, 3.0, 4.0);
-        let edge: Edge<f32> = expected.into();
-        assert_eq!(expected, edge.into_tuple());
-
-        let expected = (1.0, 2.0, 1.0, 2.0);
-        let edge: Edge<f32> = (expected.0, expected.1).into();
-        assert_eq!(expected, edge.into_tuple());
-
-        let expected = (1.0, 1.0, 1.0, 1.0);
-        let edge: Edge<f32> = (expected.0).into();
-        assert_eq!(expected, edge.into_tuple());
-
-        let expected = (1.0, 1.0, 1.0, 1.0);
-        let edge: Edge<f32> = expected.0.into();
-        assert_eq!(expected, edge.into_tuple());
-    }
-
-    #[test]
-    fn multiplication_should_work_on_edges() {
-        let expected = (10.0, 20.0, 30.0, 40.0);
-        let mut corner = Edge::new(1.0, 2.0, 3.0, 4.0);
-
-        // Basic multiplication
-        let multiplied = corner * 10.0;
-        assert_eq!(expected, multiplied.into_tuple());
-
-        // Multiply and assign
-        corner *= 10.0;
-        assert_eq!(expected, corner.into_tuple());
-    }
-}
+use std::ops::{Mul, MulAssign};
+
+use bevy::reflect::{FromReflect, Reflect};
+
+/// A struct for defining properties related to the edges of widgets
+///
+/// This is useful for things like borders, padding, etc.
+#[derive(Debug, Default, Reflect, FromReflect, Copy, Clone, PartialEq, Eq)]
+pub struct Edge<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// The value of the top edge
+    pub top: T,
+    /// The value of the right edge
+    pub right: T,
+    /// The value of the bottom edge
+    pub bottom: T,
+    /// The value of the left edge
+    pub left: T,
+}
+
+impl<T> Edge<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    /// Creates a new `Edge` with values individually specified for each edge
+    ///
+    /// # Arguments
+    ///
+    /// * `top`: The top edge value
+    /// * `right`: The right edge value
+    /// * `bottom`: The bottom edge value
+    /// * `left`: The left edge value
+    ///
+    pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
+        Self {
+            top,
+            right,
+            bottom,
+            left,
+        }
+    }
+
+    /// Creates a new `Edge` with matching vertical edges and matching horizontal edges
+    ///
+    /// # Arguments
+    ///
+    /// * `vertical`: The value of the vertical edges
+    /// * `horizontal`: The value of the horizontal edges
+    ///
+    pub fn axis(vertical: T, horizontal: T) -> Self {
+        Self {
+            top: vertical,
+            right: horizontal,
+            bottom: vertical,
+            left: horizontal,
+        }
+    }
+
+    /// Creates a new `Edge` with all edges having the same value
+    ///
+    /// # Arguments
+    ///
+    /// * `value`: The value of all edges
+    ///
+    pub fn all(value: T) -> Self {
+        Self {
+            top: value,
+            right: value,
+            bottom: value,
+            left: value,
+        }
+    }
+
+    /// Converts this `Edge` into a tuple matching `(Top, Right, Bottom, Left)`
+    pub fn into_tuple(self) -> (T, T, T, T) {
+        (self.top, self.right, self.bottom, self.left)
+    }
+}
+
+impl<T> From<Edge<T>> for (T, T, T, T)
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    fn from(edge: Edge<T>) -> Self {
+        edge.into_tuple()
+    }
+}
+
+impl<T> From<T> for Edge<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    fn from(value: T) -> Self {
+        Edge::all(value)
+    }
+}
+
+impl<T> From<(T, T)> for Edge<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    fn from(value: (T, T)) -> Self {
+        Edge::axis(value.0, value.1)
+    }
+}
+
+impl<T> From<(T, T, T, T)> for Edge<T>
+where
+    T: Copy + Default + PartialEq + Reflect,
+{
+    fn from(value: (T, T, T, T)) -> Self {
+        Edge::new(value.0, value.1, value.2, value.3)
+    }
+}
+
+impl<T> Mul<T> for Edge<T>
+where
+    T: Copy + Default + PartialEq + Mul<Output = T> + Reflect,
+{
+    type Output = Self;
+
+    fn mul(self, rhs: T) -> Self::Output {
+        Self {
+            top: self.top * rhs,
+            right: self.right * rhs,
+            bottom: self.bottom * rhs,
+            left: self.left * rhs,
+        }
+    }
+}
+
+impl<T> Mul<Edge<T>> for Edge<T>
+where
+    T: Copy + Default + PartialEq + Mul<Output = T> + Reflect,
+{
+    type Output = Self;
+
+    fn mul(self, rhs: Edge<T>) -> Self::Output {
+        Self {
+            top: rhs.top * self.top,
+            right: rhs.right * self.right,
+            bottom: rhs.bottom * self.bottom,
+            left: rhs.left * self.left,
+        }
+    }
+}
+
+impl<T> MulAssign<T> for Edge<T>
+where
+    T: Copy + Default + PartialEq + MulAssign + Reflect,
+{
+    fn mul_assign(&mut self, rhs: T) {
+        self.top *= rhs;
+        self.right *= rhs;
+        self.bottom *= rhs;
+        self.left *= rhs;
+    }
+}
+
+impl<T> MulAssign<Edge<T>> for Edge<T>
+where
+    T: Copy + Default + PartialEq + MulAssign + Reflect,
+{
+    fn mul_assign(&mut self, rhs: Edge<T>) {
+        self.top *= rhs.top;
+        self.right *= rhs.right;
+        self.bottom *= rhs.bottom;
+        self.left *= rhs.left;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Edge;
+
+    #[test]
+    fn tuples_should_convert_to_edge() {
+        let expected = (1.0, 2.0, 3.0, 4.0);
+        let edge: Edge<f32> = expected.into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 2.0, 1.0, 2.0);
+        let edge: Edge<f32> = (expected.0, expected.1).into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let edge: Edge<f32> = (expected.0).into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let edge: Edge<f32> = expected.0.into();
+        assert_eq!(expected, edge.into_tuple());
+    }
+
+    #[test]
+    fn multiplication_should_work_on_edges() {
+        let expected = (10.0, 20.0, 30.0, 40.0);
+        let mut corner = Edge::new(1.0, 2.0, 3.0, 4.0);
+
+        // Basic multiplication
+        let multiplied = corner * 10.0;
+        assert_eq!(expected, multiplied.into_tuple());
+
+        // Multiply and assign
+        corner *= 10.0;
+        assert_eq!(expected, corner.into_tuple());
+    }
+}
diff --git a/src/styles/mod.rs b/src/styles/mod.rs
index c6c91acb511bb0f6524d7a5804dfec3c386c3901..2ffda25864e0c179e0e809fc2f4d3d60982e277c 100644
--- a/src/styles/mod.rs
+++ b/src/styles/mod.rs
@@ -3,9 +3,11 @@ mod edge;
 mod options_ref;
 mod render_command;
 mod style;
+mod units;
 
 pub use corner::Corner;
 pub use edge::Edge;
 pub use options_ref::AsRefOption;
 pub use render_command::RenderCommand;
 pub use style::*;
+pub use units::*;
diff --git a/src/styles/render_command.rs b/src/styles/render_command.rs
index eafb32c58690efa6c2da550465f31c745f29d591..d5a2630214bf9738b15858a23017f631f7c9110c 100644
--- a/src/styles/render_command.rs
+++ b/src/styles/render_command.rs
@@ -1,36 +1,39 @@
-use bevy::prelude::{Handle, Image, Vec2};
-use kayak_font::Alignment;
-
-use super::Edge;
-
-#[derive(Debug, Clone, PartialEq)]
-pub enum RenderCommand {
-    Empty,
-    /// Represents a node that has no renderable object but contributes to the layout.
-    Layout,
-    Clip,
-    Quad,
-    Text {
-        content: String,
-        alignment: Alignment,
-        word_wrap: bool,
-    },
-    Image {
-        handle: Handle<Image>,
-    },
-    TextureAtlas {
-        position: Vec2,
-        size: Vec2,
-        handle: Handle<Image>,
-    },
-    NinePatch {
-        border: Edge<f32>,
-        handle: Handle<Image>,
-    },
-}
-
-impl Default for RenderCommand {
-    fn default() -> Self {
-        Self::Empty
-    }
-}
+use bevy::{
+    prelude::{Handle, Image, Vec2},
+    reflect::{FromReflect, Reflect},
+};
+use kayak_font::Alignment;
+
+use super::Edge;
+
+#[derive(Debug, Reflect, FromReflect, Clone, PartialEq)]
+pub enum RenderCommand {
+    Empty,
+    /// Represents a node that has no renderable object but contributes to the layout.
+    Layout,
+    Clip,
+    Quad,
+    Text {
+        content: String,
+        alignment: Alignment,
+        word_wrap: bool,
+    },
+    Image {
+        handle: Handle<Image>,
+    },
+    TextureAtlas {
+        position: Vec2,
+        size: Vec2,
+        handle: Handle<Image>,
+    },
+    NinePatch {
+        border: Edge<f32>,
+        handle: Handle<Image>,
+    },
+}
+
+impl Default for RenderCommand {
+    fn default() -> Self {
+        Self::Empty
+    }
+}
diff --git a/src/styles/style.rs b/src/styles/style.rs
index 4439a2fd49a286e919c6a078d124e6365a4f1efe..70b7f8f17344d4dd1e606ca5530f1cc5c4095bbe 100644
--- a/src/styles/style.rs
+++ b/src/styles/style.rs
@@ -2,10 +2,13 @@
 
 use std::ops::Add;
 
+pub use super::units::{KPositionType, LayoutType, Units};
 use bevy::prelude::Color;
 use bevy::prelude::Component;
+use bevy::prelude::ReflectComponent;
+use bevy::reflect::FromReflect;
+use bevy::reflect::Reflect;
 use bevy::window::CursorIcon;
-pub use morphorm::{LayoutType, PositionType as KPositionType, Units};
 
 use crate::cursor::PointerEvents;
 
@@ -15,8 +18,14 @@ pub use super::Edge;
 use super::RenderCommand;
 
 /// Just a wrapper around bevy's CursorIcon so we can define a default.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct KCursorIcon(pub CursorIcon);
+#[derive(Debug, Reflect, Clone, PartialEq, Eq)]
+pub struct KCursorIcon(#[reflect(ignore)] pub CursorIcon);
+
+impl FromReflect for KCursorIcon {
+    fn from_reflect(_reflect: &dyn Reflect) -> Option<Self> {
+        None
+    }
+}
 
 impl Default for KCursorIcon {
     fn default() -> Self {
@@ -27,8 +36,8 @@ impl Default for KCursorIcon {
 /// The base container of all style properties
 ///
 /// The default value for this enum is [`StyleProp::Unset`].
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum StyleProp<T: Default + Clone> {
+#[derive(Debug, Reflect, FromReflect, Clone, PartialEq, Eq)]
+pub enum StyleProp<T: Default + Clone + Reflect + FromReflect> {
     /// This prop is unset, meaning its actual value is not determined until style resolution,
     /// wherein it will be set to the property's default value.
     ///
@@ -46,7 +55,7 @@ pub enum StyleProp<T: Default + Clone> {
 
 impl<T> Default for StyleProp<T>
 where
-    T: Default + Clone,
+    T: Default + Clone + Reflect + FromReflect,
 {
     fn default() -> Self {
         Self::Unset
@@ -55,7 +64,7 @@ where
 
 impl<T> StyleProp<T>
 where
-    T: Default + Clone,
+    T: Default + Clone + Reflect + FromReflect,
 {
     /// Resolves this style property into a concrete value.
     ///
@@ -122,7 +131,7 @@ where
     }
 }
 
-impl<T: Default + Clone> From<T> for StyleProp<T> {
+impl<T: Default + Clone + Reflect + FromReflect> From<T> for StyleProp<T> {
     fn from(value: T) -> Self {
         StyleProp::Value(value)
     }
@@ -239,7 +248,8 @@ define_styles! {
     ///   // Applied second (sets any remaining `StyleProp::Unset` fields)
     ///   .with_style(&style_b);
     /// ```
-    #[derive(Component, Debug, Default, Clone, PartialEq)]
+    #[derive(Component, Reflect, FromReflect, Debug, Default, Clone, PartialEq)]
+    #[reflect(Component)]
     pub struct KStyle {
         /// The background color of this widget
         ///
@@ -275,6 +285,7 @@ define_styles! {
         /// The spacing between child widgets along the horizontal axis
         pub col_between: StyleProp<Units>,
         /// The cursor icon to display when hovering this widget
+        #[reflect(ignore)]
         pub cursor: StyleProp<KCursorIcon>,
         /// The font name for this widget
         ///
diff --git a/src/styles/units.rs b/src/styles/units.rs
new file mode 100644
index 0000000000000000000000000000000000000000..01c563153c3db11b0b397b677c2a89f2ada5b967
--- /dev/null
+++ b/src/styles/units.rs
@@ -0,0 +1,126 @@
+use bevy::reflect::{FromReflect, Reflect};
+
+/// The layout type determines how nodes will be positioned when directed by the parent
+#[derive(Debug, FromReflect, Reflect, Clone, Copy, PartialEq)]
+pub enum LayoutType {
+    /// Stack child elements horizontally
+    Row,
+    /// Stack child elements vertically
+    Column,
+    /// Position child elements into specified rows and columns
+    Grid,
+}
+
+impl Default for LayoutType {
+    fn default() -> Self {
+        LayoutType::Column
+    }
+}
+
+impl Into<morphorm::LayoutType> for LayoutType {
+    fn into(self) -> morphorm::LayoutType {
+        match self {
+            LayoutType::Column => morphorm::LayoutType::Column,
+            LayoutType::Row => morphorm::LayoutType::Row,
+            LayoutType::Grid => morphorm::LayoutType::Grid,
+        }
+    }
+}
+
+/// The position type determines whether a node will be positioned in-line with its siblings or seperate
+#[derive(Debug, Reflect, FromReflect, Clone, Copy, PartialEq)]
+pub enum KPositionType {
+    /// Node is positioned relative to parent but ignores its siblings
+    SelfDirected,
+    /// Node is positioned relative to parent and in-line with siblings
+    ParentDirected,
+}
+
+impl Default for KPositionType {
+    fn default() -> Self {
+        KPositionType::ParentDirected
+    }
+}
+
+impl Into<morphorm::PositionType> for KPositionType {
+    fn into(self) -> morphorm::PositionType {
+        match self {
+            Self::ParentDirected => morphorm::PositionType::ParentDirected,
+            Self::SelfDirected => morphorm::PositionType::SelfDirected,
+        }
+    }
+}
+
+/// Units which describe spacing and size
+#[derive(Debug, FromReflect, Reflect, Clone, Copy, PartialEq)]
+pub enum Units {
+    /// A number of pixels
+    Pixels(f32),
+    /// A percentage of the parent dimension
+    Percentage(f32),
+    /// A factor of the remaining free space
+    Stretch(f32),
+    /// Automatically determine the value
+    Auto,
+}
+
+impl Default for Units {
+    fn default() -> Self {
+        Units::Auto
+    }
+}
+
+impl Into<morphorm::Units> for Units {
+    fn into(self) -> morphorm::Units {
+        match self {
+            Self::Pixels(value) => morphorm::Units::Pixels(value),
+            Self::Percentage(value) => morphorm::Units::Percentage(value),
+            Self::Stretch(value) => morphorm::Units::Stretch(value),
+            Self::Auto => morphorm::Units::Auto,
+        }
+    }
+}
+
+impl Units {
+    /// Converts the units to an f32 value
+    pub fn value_or(&self, parent_value: f32, auto: f32) -> f32 {
+        match self {
+            &Units::Pixels(pixels) => pixels,
+            &Units::Percentage(percentage) => (percentage / 100.0) * parent_value,
+            &Units::Stretch(_) => auto,
+            &Units::Auto => auto,
+        }
+    }
+
+    /// Returns true if the value is in pixels
+    pub fn is_pixels(&self) -> bool {
+        match self {
+            Units::Pixels(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the value is a percentage
+    pub fn is_percentage(&self) -> bool {
+        match self {
+            Units::Percentage(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the value is a stretch factor
+    pub fn is_stretch(&self) -> bool {
+        match self {
+            Units::Stretch(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the value is auto
+    pub fn is_auto(&self) -> bool {
+        match self {
+            Units::Auto => true,
+            _ => false,
+        }
+    }
+}
diff --git a/src/widgets/app.rs b/src/widgets/app.rs
index 9d371177800e0a1acfc94a5745c6f84952d1026a..c234a92142ae98331e46de8ec5eb3b67e720b352 100644
--- a/src/widgets/app.rs
+++ b/src/widgets/app.rs
@@ -1,12 +1,11 @@
 use bevy::prelude::*;
 use kayak_ui_macros::rsx;
-use morphorm::Units;
 
 use crate::{
     children::KChildren,
     context::WidgetName,
     prelude::KayakWidgetContext,
-    styles::{KStyle, RenderCommand, StyleProp},
+    styles::{KStyle, RenderCommand, StyleProp, Units},
     widget::{EmptyState, Widget, WidgetParam},
     CameraUIKayak,
 };