diff --git a/examples/basic_sprite.rs b/examples/basic_sprite.rs
index e01b4455bd6a84e7b915f29f4e1ebb6f57b6ed25..29b8b93c39573cb4d4fcdfb0b9c96e1571c5a4d9 100644
--- a/examples/basic_sprite.rs
+++ b/examples/basic_sprite.rs
@@ -1,7 +1,7 @@
 use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*, window::PrimaryWindow};
 use bevy_cosmic_edit::{
-    AttrsOwned, CosmicAttrs, CosmicEditPlugin, CosmicEditSpriteBundle, CosmicFontConfig,
-    CosmicMetrics, CosmicText, CosmicTextPosition, Focus,
+    AttrsOwned, CosmicAttrs, CosmicEditBundle, CosmicEditPlugin, CosmicFontConfig, CosmicMetrics,
+    CosmicText, CosmicTextPosition, Focus,
 };
 
 fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
@@ -20,21 +20,26 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
 
     let scale_factor = primary_window.scale_factor() as f32;
 
-    let cosmic_edit = CosmicEditSpriteBundle {
-        sprite: Sprite {
-            custom_size: Some(Vec2::new(primary_window.width(), primary_window.height())),
+    let cosmic_edit = (
+        CosmicEditBundle {
+            metrics: CosmicMetrics {
+                font_size: 14.,
+                line_height: 18.,
+                scale_factor,
+            },
+            text_position: CosmicTextPosition::Center,
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
             ..default()
         },
-        cosmic_metrics: CosmicMetrics {
-            font_size: 14.,
-            line_height: 18.,
-            scale_factor,
+        SpriteBundle {
+            sprite: Sprite {
+                custom_size: Some(Vec2::new(primary_window.width(), primary_window.height())),
+                ..default()
+            },
+            ..default()
         },
-        text_position: CosmicTextPosition::Center,
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
-        ..default()
-    };
+    );
 
     let cosmic_edit = commands.spawn(cosmic_edit).id();
 
diff --git a/examples/basic_ui.rs b/examples/basic_ui.rs
index f02ab728750a7c1210da1cd9df62a2987d5c1e1c..1688f79c194544722144347ce889810f07ba33fc 100644
--- a/examples/basic_ui.rs
+++ b/examples/basic_ui.rs
@@ -1,6 +1,6 @@
 use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*, window::PrimaryWindow};
 use bevy_cosmic_edit::{
-    AttrsOwned, CosmicAttrs, CosmicEditPlugin, CosmicEditUiBundle, CosmicEditor, CosmicFontConfig,
+    AttrsOwned, CosmicAttrs, CosmicEditBundle, CosmicEditPlugin, CosmicEditor, CosmicFontConfig,
     CosmicMetrics, CosmicText, CosmicTextPosition, Focus,
 };
 
@@ -20,22 +20,30 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
 
     let scale_factor = primary_window.scale_factor() as f32;
 
-    let cosmic_edit = CosmicEditUiBundle {
-        style: Style {
-            width: Val::Percent(100.),
-            height: Val::Percent(100.),
+    let cosmic_edit = (
+        CosmicEditBundle {
+            metrics: CosmicMetrics {
+                font_size: 14.,
+                line_height: 18.,
+                scale_factor,
+            },
+            text_position: CosmicTextPosition::Center,
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
             ..default()
         },
-        cosmic_metrics: CosmicMetrics {
-            font_size: 14.,
-            line_height: 18.,
-            scale_factor,
+        // Use buttonbundle for layout
+        ButtonBundle {
+            style: Style {
+                width: Val::Percent(100.),
+                height: Val::Percent(100.),
+                ..default()
+            },
+            // Needs to be set to prevent a bug where nothing is displayed
+            background_color: Color::WHITE.into(),
+            ..default()
         },
-        text_position: CosmicTextPosition::Center,
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
-        ..default()
-    };
+    );
 
     let cosmic_edit = commands.spawn(cosmic_edit).id();
 
diff --git a/examples/bevy_api_testing.rs b/examples/bevy_api_testing.rs
index f51ff48c77107186d6925db5da1fa5e6cf9bc194..892ccb08c48dc9833d7e089c5232b2a77c6456e8 100644
--- a/examples/bevy_api_testing.rs
+++ b/examples/bevy_api_testing.rs
@@ -5,37 +5,50 @@ fn setup(mut commands: Commands) {
     commands.spawn(Camera2dBundle::default());
 
     // spawn a new CosmicEditBundle
-    commands.spawn(CosmicEditUiBundle {
-        style: Style {
-            // Size and position of text box
-            width: Val::Px(300.),
-            height: Val::Px(50.),
-            left: Val::Px(100.),
-            top: Val::Px(100.),
+    let ui_editor = commands
+        .spawn(CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(
+                Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
+            )),
+            max_lines: CosmicMaxLines(1),
             ..default()
-        },
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(
-            Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
-        )),
-        max_lines: CosmicMaxLines(1),
-        placeholder_setter: PlaceholderText(CosmicText::OneStyle("Place held :)".into())),
-        ..default()
-    });
+        })
+        .insert(ButtonBundle {
+            style: Style {
+                // Size and position of text box
+                width: Val::Px(300.),
+                height: Val::Px(50.),
+                left: Val::Px(100.),
+                top: Val::Px(100.),
+                // needs to be set to prevent a bug where nothing is displayed
+                ..default()
+            },
+            background_color: BackgroundColor(Color::WHITE),
+            ..default()
+        })
+        .insert(CosmicEditPlaceholderBundle {
+            text_setter: PlaceholderText(CosmicText::OneStyle("Placeholder".into())),
+            attrs: PlaceholderAttrs(AttrsOwned::new(
+                Attrs::new().color(bevy_color_to_cosmic(Color::rgb_u8(128, 128, 128))),
+            )),
+        })
+        .id();
 
-    let sprite_editor = commands
-        .spawn(CosmicEditSpriteBundle {
+    commands.spawn((
+        CosmicEditBundle { ..default() },
+        SpriteBundle {
+            // Sets size of text box
             sprite: Sprite {
-                // Sets size of text box
                 custom_size: Some(Vec2::new(300., 100.)),
                 ..default()
             },
             // Position of text box
-            transform: Transform::from_xyz(100., 200., 0.),
+            transform: Transform::from_xyz(0., 100., 0.),
             ..default()
-        })
-        .id();
+        },
+    ));
 
-    commands.insert_resource(Focus(Some(sprite_editor)));
+    commands.insert_resource(Focus(Some(ui_editor)));
 }
 
 fn bevy_color_to_cosmic(color: bevy::prelude::Color) -> CosmicColor {
diff --git a/examples/every_option.rs b/examples/every_option.rs
index c2330f32a43203c6436fb5c6316965fb489339dd..28dbbae701d38926fb70e5683938f9a979c997e7 100644
--- a/examples/every_option.rs
+++ b/examples/every_option.rs
@@ -1,4 +1,4 @@
-use bevy::{prelude::*, ui::FocusPolicy, window::PrimaryWindow};
+use bevy::{prelude::*, window::PrimaryWindow};
 use bevy_cosmic_edit::*;
 
 #[derive(Resource)]
@@ -12,21 +12,23 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
     let primary_window = windows.single();
 
     let editor = commands
-        .spawn(CosmicEditUiBundle {
-            node: Node::default(),
-            button: Button,
-            visibility: Visibility::Visible,
-            computed_visibility: ComputedVisibility::default(),
-            z_index: ZIndex::default(),
-            image: UiImage::default(),
-            transform: Transform::default(),
-            interaction: Interaction::default(),
-            focus_policy: FocusPolicy::default(),
+        .spawn(CosmicEditBundle {
             text_position: CosmicTextPosition::default(),
             fill_color: FillColor::default(),
-            background_color: BackgroundColor::default(),
-            global_transform: GlobalTransform::default(),
             background_image: CosmicBackground::default(),
+            attrs: CosmicAttrs(attrs.clone()),
+            metrics: CosmicMetrics {
+                font_size: 16.,
+                line_height: 16.,
+                scale_factor: primary_window.scale_factor() as f32,
+            },
+            max_chars: CosmicMaxChars(15),
+            max_lines: CosmicMaxLines(1),
+            text_setter: CosmicText::OneStyle("BANANA IS THE CODEWORD!".into()),
+            mode: CosmicMode::Wrap,
+            canvas: Default::default(),
+        })
+        .insert(ButtonBundle {
             border_color: Color::LIME_GREEN.into(),
             style: Style {
                 // Size and position of text box
@@ -37,18 +39,12 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
                 top: Val::Px(100.),
                 ..default()
             },
-            cosmic_attrs: CosmicAttrs(attrs.clone()),
-            cosmic_metrics: CosmicMetrics {
-                font_size: 16.,
-                line_height: 16.,
-                scale_factor: primary_window.scale_factor() as f32,
-            },
-            max_chars: CosmicMaxChars(15),
-            max_lines: CosmicMaxLines(1),
-            text_setter: CosmicText::OneStyle("BANANA IS THE CODEWORD!".into()),
-            mode: CosmicMode::Wrap,
-            placeholder_setter: PlaceholderText(CosmicText::OneStyle("Placeholder".into())),
-            placeholder_attrs: PlaceholderAttrs(AttrsOwned::new(
+            background_color: Color::WHITE.into(),
+            ..default()
+        })
+        .insert(CosmicEditPlaceholderBundle {
+            text_setter: PlaceholderText(CosmicText::OneStyle("Placeholder".into())),
+            attrs: PlaceholderAttrs(AttrsOwned::new(
                 Attrs::new().color(CosmicColor::rgb(88, 88, 88)),
             )),
         })
diff --git a/examples/font_per_widget.rs b/examples/font_per_widget.rs
index 6a628051d9bd3f89226ffc19f3d5e1dfacee2969..a5cc79f70a11134e9992e8a7144345d30cb52268 100644
--- a/examples/font_per_widget.rs
+++ b/examples/font_per_widget.rs
@@ -207,45 +207,55 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
         )],
     ];
 
-    let cosmic_edit_1 = CosmicEditUiBundle {
-        text_position: bevy_cosmic_edit::CosmicTextPosition::Center,
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        cosmic_metrics: CosmicMetrics {
-            font_size: 18.,
-            line_height: 22.,
-            scale_factor: primary_window.scale_factor() as f32,
+    let cosmic_edit_1 = (
+        CosmicEditBundle {
+            text_position: bevy_cosmic_edit::CosmicTextPosition::Center,
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            metrics: CosmicMetrics {
+                font_size: 18.,
+                line_height: 22.,
+                scale_factor: primary_window.scale_factor() as f32,
+            },
+            text_setter: CosmicText::MultiStyle(lines),
+            ..default()
         },
-        style: Style {
-            width: Val::Percent(50.),
-            height: Val::Percent(100.),
+        ButtonBundle {
+            style: Style {
+                width: Val::Percent(50.),
+                height: Val::Percent(100.),
+                ..default()
+            },
+            background_color: BackgroundColor(Color::WHITE),
             ..default()
         },
-        background_color: BackgroundColor(Color::WHITE),
-        text_setter: CosmicText::MultiStyle(lines),
-        ..default()
-    };
+    );
 
     let mut attrs_2 = Attrs::new();
     attrs_2 = attrs_2.family(Family::Name("Times New Roman"));
     attrs_2.color_opt = Some(bevy_color_to_cosmic(Color::PURPLE));
 
-    let cosmic_edit_2 = CosmicEditUiBundle {
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs_2)),
-        cosmic_metrics: CosmicMetrics {
-            font_size: 28.,
-            line_height: 36.,
-            scale_factor: primary_window.scale_factor() as f32,
+    let cosmic_edit_2 = (
+        CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(attrs_2)),
+            metrics: CosmicMetrics {
+                font_size: 28.,
+                line_height: 36.,
+                scale_factor: primary_window.scale_factor() as f32,
+            },
+            text_position: CosmicTextPosition::Center,
+            text_setter: CosmicText::OneStyle("Widget 2.\nClick on me =>".to_string()),
+            ..default()
         },
-        text_position: CosmicTextPosition::Center,
-        background_color: BackgroundColor(Color::WHITE.with_a(0.8)),
-        style: Style {
-            width: Val::Percent(50.),
-            height: Val::Percent(100.),
+        ButtonBundle {
+            background_color: BackgroundColor(Color::WHITE.with_a(0.8)),
+            style: Style {
+                width: Val::Percent(50.),
+                height: Val::Percent(100.),
+                ..default()
+            },
             ..default()
         },
-        text_setter: CosmicText::OneStyle("Widget 2.\nClick on me =>".to_string()),
-        ..default()
-    };
+    );
 
     let mut id = None;
     // Spawn the CosmicEditUiBundles as children of root
diff --git a/examples/image_background.rs b/examples/image_background.rs
index cdc9d7d7e9de22dc87cd0a785e34ad108d51de14..8d700ae94948aff58409939d025b369b1c34e6a1 100644
--- a/examples/image_background.rs
+++ b/examples/image_background.rs
@@ -7,7 +7,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
     let bg_image_handle = asset_server.load("img/bevy_logo_light.png");
 
     let editor = commands
-        .spawn(CosmicEditUiBundle {
+        .spawn(CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(
+                Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
+            )),
+            background_image: CosmicBackground(Some(bg_image_handle)),
+            ..default()
+        })
+        .insert(ButtonBundle {
             style: Style {
                 // Size and position of text box
                 width: Val::Px(300.),
@@ -16,10 +23,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
                 top: Val::Px(100.),
                 ..default()
             },
-            cosmic_attrs: CosmicAttrs(AttrsOwned::new(
-                Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
-            )),
-            background_image: CosmicBackground(Some(bg_image_handle)),
+            background_color: Color::WHITE.into(),
             ..default()
         })
         .id();
diff --git a/examples/multiple_sprites.rs b/examples/multiple_sprites.rs
index 1f1942be689b4538f580fd50bb1cd104fe5a8af1..dc2f06fce6b10f7554659058ba95541eb3957824 100644
--- a/examples/multiple_sprites.rs
+++ b/examples/multiple_sprites.rs
@@ -20,43 +20,53 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
         scale_factor: primary_window.scale_factor() as f32,
     };
 
-    let cosmic_edit_1 = CosmicEditSpriteBundle {
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        cosmic_metrics: metrics.clone(),
-        sprite: Sprite {
-            custom_size: Some(Vec2 {
-                x: primary_window.width() / 2.,
-                y: primary_window.height(),
-            }),
+    let cosmic_edit_1 = (
+        CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            metrics: metrics.clone(),
+            text_position: CosmicTextPosition::Center,
+            fill_color: FillColor(Color::ALICE_BLUE),
+            text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
             ..default()
         },
-        transform: Transform::from_translation(Vec3::new(-primary_window.width() / 4., 0., 1.)),
-        text_position: CosmicTextPosition::Center,
-        fill_color: FillColor(Color::ALICE_BLUE),
-        text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()),
-        ..default()
-    };
+        SpriteBundle {
+            sprite: Sprite {
+                custom_size: Some(Vec2 {
+                    x: primary_window.width() / 2.,
+                    y: primary_window.height(),
+                }),
+                ..default()
+            },
+            transform: Transform::from_translation(Vec3::new(-primary_window.width() / 4., 0., 1.)),
+            ..default()
+        },
+    );
 
-    let cosmic_edit_2 = CosmicEditSpriteBundle {
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        cosmic_metrics: metrics,
-        sprite: Sprite {
-            custom_size: Some(Vec2 {
-                x: primary_window.width() / 2.,
-                y: primary_window.height() / 2.,
-            }),
+    let cosmic_edit_2 = (
+        CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            metrics,
+            text_position: CosmicTextPosition::Center,
+            fill_color: FillColor(Color::GRAY.with_a(0.5)),
+            text_setter: CosmicText::OneStyle("Widget_2. Click on me".to_string()),
             ..default()
         },
-        transform: Transform::from_translation(Vec3::new(
-            primary_window.width() / 4.,
-            -primary_window.height() / 4.,
-            1.,
-        )),
-        text_position: CosmicTextPosition::Center,
-        fill_color: FillColor(Color::GRAY.with_a(0.5)),
-        text_setter: CosmicText::OneStyle("Widget_2. Click on me".to_string()),
-        ..default()
-    };
+        SpriteBundle {
+            sprite: Sprite {
+                custom_size: Some(Vec2 {
+                    x: primary_window.width() / 2.,
+                    y: primary_window.height() / 2.,
+                }),
+                ..default()
+            },
+            transform: Transform::from_translation(Vec3::new(
+                primary_window.width() / 4.,
+                -primary_window.height() / 4.,
+                1.,
+            )),
+            ..default()
+        },
+    );
 
     let id = commands.spawn(cosmic_edit_1).id();
 
diff --git a/examples/readonly.rs b/examples/readonly.rs
index 58035b7af7b16c5514a4f19aa06e21cceb450146..e218b099058122cb8bf36eb563f9532d55fe0a27 100644
--- a/examples/readonly.rs
+++ b/examples/readonly.rs
@@ -20,23 +20,28 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
     attrs = attrs.family(Family::Name("Victor Mono"));
     attrs = attrs.color(bevy_color_to_cosmic(Color::PURPLE));
 
-    let cosmic_edit = CosmicEditUiBundle {
-        style: Style {
-            width: Val::Percent(100.),
-            height: Val::Percent(100.),
+    let cosmic_edit = (
+        CosmicEditBundle {
+            attrs: CosmicAttrs(AttrsOwned::new(attrs)),
+            text_position: CosmicTextPosition::Center,
+            metrics: CosmicMetrics {
+                font_size: 14.,
+                line_height: 18.,
+                scale_factor: primary_window.scale_factor() as f32,
+            },
+            text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y\nRead only widget".to_string()),
             ..default()
         },
-        cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)),
-        text_position: CosmicTextPosition::Center,
-        background_color: BackgroundColor(Color::WHITE),
-        cosmic_metrics: CosmicMetrics {
-            font_size: 14.,
-            line_height: 18.,
-            scale_factor: primary_window.scale_factor() as f32,
+        ButtonBundle {
+            style: Style {
+                width: Val::Percent(100.),
+                height: Val::Percent(100.),
+                ..default()
+            },
+            background_color: BackgroundColor(Color::WHITE),
+            ..default()
         },
-        text_setter: CosmicText::OneStyle("馃榾馃榾馃榾 x => y\nRead only widget".to_string()),
-        ..default()
-    };
+    );
 
     let mut id = None;
     // Spawn the CosmicEditUiBundle as a child of root
diff --git a/examples/text_input.rs b/examples/text_input.rs
index f031b9816e67116894deab1d2bba2f70d2e9ccb8..7ba06f178d7668a5c9f19cc742d9724296306973 100644
--- a/examples/text_input.rs
+++ b/examples/text_input.rs
@@ -10,30 +10,38 @@ fn create_editable_widget(commands: &mut Commands, scale_factor: f32, text: Stri
     let placeholder_attrs =
         AttrsOwned::new(Attrs::new().color(bevy_color_to_cosmic(Color::hex("#e6e6e6").unwrap())));
     commands
-        .spawn(CosmicEditUiBundle {
-            border_color: Color::hex("#ededed").unwrap().into(),
-            style: Style {
-                border: UiRect::all(Val::Px(3.)),
-                width: Val::Percent(20.),
-                height: Val::Px(50.),
-                left: Val::Percent(40.),
-                top: Val::Px(100.),
+        .spawn((
+            CosmicEditBundle {
+                attrs: CosmicAttrs(attrs.clone()),
+                metrics: CosmicMetrics {
+                    font_size: 18.,
+                    line_height: 18. * 1.2,
+                    scale_factor,
+                },
+                max_lines: CosmicMaxLines(1),
+                text_setter: CosmicText::OneStyle(text),
+                text_position: CosmicTextPosition::Left { padding: 20 },
+                mode: CosmicMode::InfiniteLine,
+                ..default()
+            },
+            ButtonBundle {
+                border_color: Color::hex("#ededed").unwrap().into(),
+                style: Style {
+                    border: UiRect::all(Val::Px(3.)),
+                    width: Val::Percent(20.),
+                    height: Val::Px(50.),
+                    left: Val::Percent(40.),
+                    top: Val::Px(100.),
+                    ..default()
+                },
+                background_color: Color::WHITE.into(),
                 ..default()
             },
-            cosmic_attrs: CosmicAttrs(attrs.clone()),
-            cosmic_metrics: CosmicMetrics {
-                font_size: 18.,
-                line_height: 18. * 1.2,
-                scale_factor,
+            CosmicEditPlaceholderBundle {
+                text_setter: PlaceholderText(CosmicText::OneStyle("Type something...".into())),
+                attrs: PlaceholderAttrs(placeholder_attrs.clone()),
             },
-            max_lines: CosmicMaxLines(1),
-            text_setter: CosmicText::OneStyle(text),
-            text_position: CosmicTextPosition::Left { padding: 20 },
-            mode: CosmicMode::InfiniteLine,
-            placeholder_setter: PlaceholderText(CosmicText::OneStyle("Type something...".into())),
-            placeholder_attrs: PlaceholderAttrs(placeholder_attrs.clone()),
-            ..default()
-        })
+        ))
         .id()
 }
 
@@ -42,7 +50,19 @@ fn create_readonly_widget(commands: &mut Commands, scale_factor: f32, text: Stri
         AttrsOwned::new(Attrs::new().color(bevy_color_to_cosmic(Color::hex("4d4d4d").unwrap())));
     commands
         .spawn((
-            CosmicEditUiBundle {
+            CosmicEditBundle {
+                attrs: CosmicAttrs(attrs.clone()),
+                metrics: CosmicMetrics {
+                    font_size: 18.,
+                    line_height: 18. * 1.2,
+                    scale_factor,
+                },
+                text_setter: CosmicText::OneStyle(text),
+                text_position: CosmicTextPosition::Left { padding: 20 },
+                mode: CosmicMode::AutoHeight,
+                ..default()
+            },
+            ButtonBundle {
                 border_color: Color::hex("#ededed").unwrap().into(),
                 style: Style {
                     border: UiRect::all(Val::Px(3.)),
@@ -52,15 +72,7 @@ fn create_readonly_widget(commands: &mut Commands, scale_factor: f32, text: Stri
                     top: Val::Px(100.),
                     ..default()
                 },
-                cosmic_attrs: CosmicAttrs(attrs.clone()),
-                cosmic_metrics: CosmicMetrics {
-                    font_size: 18.,
-                    line_height: 18. * 1.2,
-                    scale_factor,
-                },
-                text_setter: CosmicText::OneStyle(text),
-                text_position: CosmicTextPosition::Left { padding: 20 },
-                mode: CosmicMode::AutoHeight,
+                background_color: Color::WHITE.into(),
                 ..default()
             },
             ReadOnly,
diff --git a/src/lib.rs b/src/lib.rs
index 63f126bd428c63309cb19b22cd3fe2ee330ae98e..a13ee14e62e7c271609c4c77b066df407fe742e3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,9 +6,7 @@ mod render;
 
 use std::{collections::VecDeque, path::PathBuf};
 
-use bevy::{
-    prelude::*, render::texture::DEFAULT_IMAGE_HANDLE, transform::TransformSystem, ui::FocusPolicy,
-};
+use bevy::{prelude::*, render::texture::DEFAULT_IMAGE_HANDLE, transform::TransformSystem};
 pub use cosmic_text::{
     Action, Attrs, AttrsOwned, Color as CosmicColor, Cursor, Edit, Family, Style as FontStyle,
     Weight as FontWeight,
@@ -209,154 +207,36 @@ impl Default for PlaceholderAttrs {
         Self(AttrsOwned::new(Attrs::new()))
     }
 }
-#[derive(Bundle)]
-pub struct CosmicEditUiBundle {
-    // Bevy UI bits
-    /// Describes the logical size of the node
-    pub node: Node,
-    /// Marker component that signals this node is a button
-    pub button: Button,
-    /// Styles which control the layout (size and position) of the node and it's children
-    /// In some cases these styles also affect how the node drawn/painted.
-    pub style: Style,
-    /// Describes whether and how the button has been interacted with by the input
-    pub interaction: Interaction,
-    /// Whether this node should block interaction with lower nodes
-    pub focus_policy: FocusPolicy,
-    /// UiNode Background Color, works as a tint.
-    pub background_color: BackgroundColor,
-    /// The background color, which serves as a "fill" for this node
-    pub fill_color: FillColor,
-    /// The color of the Node's border
-    pub border_color: BorderColor,
-    /// This is used as the cosmic text canvas
-    pub image: UiImage,
-    /// The transform of the node
-    ///
-    /// This field is automatically managed by the UI layout system.
-    /// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
-    pub transform: Transform,
-    /// The global transform of the node
-    ///
-    /// This field is automatically managed by the UI layout system.
-    /// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
-    pub global_transform: GlobalTransform,
-    /// Describes the visibility properties of the node
-    pub visibility: Visibility,
-    /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
-    pub computed_visibility: ComputedVisibility,
-    /// Indicates the depth at which the node should appear in the UI
-    pub z_index: ZIndex,
-    // cosmic bits
-    /// text positioning enum
-    pub text_position: CosmicTextPosition,
-    /// text metrics
-    pub cosmic_metrics: CosmicMetrics,
-    /// text attributes
-    pub cosmic_attrs: CosmicAttrs,
-    /// bg img
-    pub background_image: CosmicBackground,
-    /// How many lines are allowed in buffer, 0 for no limit
-    pub max_lines: CosmicMaxLines,
-    /// How many characters are allowed in buffer, 0 for no limit
-    pub max_chars: CosmicMaxChars,
-    /// Setting this will update the buffer's text
-    pub text_setter: CosmicText,
-    /// Text input mode
-    pub mode: CosmicMode,
-    /// Setting this will update the placeholder text
-    pub placeholder_setter: PlaceholderText,
-    pub placeholder_attrs: PlaceholderAttrs,
-}
 
-impl Default for CosmicEditUiBundle {
+#[derive(Component)]
+pub struct CosmicCanvas(pub Handle<Image>);
+
+impl Default for CosmicCanvas {
     fn default() -> Self {
-        Self {
-            focus_policy: FocusPolicy::Block,
-            node: Default::default(),
-            button: Default::default(),
-            style: Default::default(),
-            border_color: BorderColor(Color::NONE),
-            interaction: Default::default(),
-            fill_color: Default::default(),
-            image: Default::default(),
-            transform: Default::default(),
-            global_transform: Default::default(),
-            visibility: Default::default(),
-            computed_visibility: Default::default(),
-            z_index: Default::default(),
-            text_position: Default::default(),
-            cosmic_metrics: Default::default(),
-            cosmic_attrs: Default::default(),
-            background_image: Default::default(),
-            max_lines: Default::default(),
-            max_chars: Default::default(),
-            text_setter: Default::default(),
-            mode: Default::default(),
-            background_color: BackgroundColor(Color::WHITE),
-            placeholder_setter: Default::default(),
-            placeholder_attrs: Default::default(),
-        }
+        CosmicCanvas(DEFAULT_IMAGE_HANDLE.typed())
     }
 }
 
-#[derive(Bundle)]
-pub struct CosmicEditSpriteBundle {
-    // Bevy Sprite Bits
-    pub sprite: Sprite,
-    pub transform: Transform,
-    pub global_transform: GlobalTransform,
-    pub texture: Handle<Image>,
-    /// User indication of whether an entity is visible
-    pub visibility: Visibility,
-    /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
-    pub computed_visibility: ComputedVisibility,
-    /// Widget background color
-    pub fill_color: FillColor,
+#[derive(Bundle, Default)]
+pub struct CosmicEditBundle {
     // cosmic bits
-    /// text positioning enum
+    pub fill_color: FillColor,
     pub text_position: CosmicTextPosition,
-    /// text metrics
-    pub cosmic_metrics: CosmicMetrics,
-    /// text attributes
-    pub cosmic_attrs: CosmicAttrs,
-    /// bg img
+    pub metrics: CosmicMetrics,
+    pub attrs: CosmicAttrs,
     pub background_image: CosmicBackground,
-    /// How many lines are allowed in buffer, 0 for no limit
     pub max_lines: CosmicMaxLines,
-    /// How many characters are allowed in buffer, 0 for no limit
     pub max_chars: CosmicMaxChars,
-    /// Setting this will update the buffer's text
     pub text_setter: CosmicText,
-    /// Text input mode
     pub mode: CosmicMode,
-    /// Setting this will update the placeholder text
-    pub placeholder_setter: PlaceholderText,
-    pub placeholder_attrs: PlaceholderAttrs,
+    pub canvas: CosmicCanvas,
 }
 
-impl Default for CosmicEditSpriteBundle {
-    fn default() -> Self {
-        Self {
-            sprite: Default::default(),
-            transform: Default::default(),
-            global_transform: Default::default(),
-            texture: DEFAULT_IMAGE_HANDLE.typed(),
-            visibility: Visibility::Visible,
-            computed_visibility: Default::default(),
-            fill_color: Default::default(),
-            text_position: Default::default(),
-            cosmic_metrics: Default::default(),
-            cosmic_attrs: Default::default(),
-            background_image: Default::default(),
-            max_lines: Default::default(),
-            max_chars: Default::default(),
-            text_setter: Default::default(),
-            mode: Default::default(),
-            placeholder_setter: Default::default(),
-            placeholder_attrs: Default::default(),
-        }
-    }
+#[derive(Bundle)]
+pub struct CosmicEditPlaceholderBundle {
+    /// set this to update placeholder text
+    pub text_setter: PlaceholderText,
+    pub attrs: PlaceholderAttrs,
 }
 
 #[derive(Clone)]
@@ -411,6 +291,8 @@ impl Plugin for CosmicEditPlugin {
                 cosmic_editor_builder,
                 placeholder_builder,
                 on_scale_factor_change,
+                render::cosmic_ui_to_canvas,
+                render::cosmic_sprite_to_canvas,
             ),
         )
         .add_systems(PreUpdate, (update_buffer_text, update_placeholder_text))
@@ -425,6 +307,8 @@ impl Plugin for CosmicEditPlugin {
                 freeze_cursor_blink,
                 hide_inactive_or_readonly_cursor,
                 clear_inactive_selection,
+                render::update_handle_ui,
+                render::update_handle_sprite,
             ),
         )
         .add_systems(
@@ -807,7 +691,7 @@ mod tests {
     use crate::*;
 
     fn test_spawn_cosmic_edit_system(mut commands: Commands) {
-        commands.spawn(CosmicEditUiBundle {
+        commands.spawn(CosmicEditBundle {
             text_setter: CosmicText::OneStyle("Blah".into()),
             ..Default::default()
         });
diff --git a/src/render.rs b/src/render.rs
index 90a92e385a31fce6535660386cb85b0fd9e65644..cb585f6028b8818963b41d77aca7c4469d8f6b6b 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -11,8 +11,8 @@ use image::{imageops::FilterType, GenericImageView};
 
 use crate::{
     get_text_size, get_x_offset_center, get_y_offset_center, CosmicAttrs, CosmicBackground,
-    CosmicEditor, CosmicFontSystem, CosmicMetrics, CosmicMode, CosmicTextPosition, FillColor,
-    Focus, Placeholder, ReadOnly, XOffset,
+    CosmicCanvas, CosmicEditor, CosmicFontSystem, CosmicMetrics, CosmicMode, CosmicTextPosition,
+    FillColor, Focus, Placeholder, ReadOnly, XOffset,
 };
 
 #[derive(Resource)]
@@ -35,12 +35,11 @@ pub(crate) fn cosmic_edit_redraw_buffer(
         &CosmicAttrs,
         &CosmicBackground,
         &FillColor,
+        &mut CosmicCanvas,
         &CosmicTextPosition,
-        Option<&mut UiImage>,
         Option<&Node>,
         Option<&mut Style>,
         Option<&mut Sprite>,
-        Option<&mut Handle<Image>>,
         &mut XOffset,
         &CosmicMode,
         Option<&mut Placeholder>,
@@ -55,12 +54,11 @@ pub(crate) fn cosmic_edit_redraw_buffer(
         attrs,
         background_image,
         fill_color,
+        mut canvas,
         text_position,
-        ui_image_opt,
         node_opt,
         style_opt,
         sprite_opt,
-        handle_opt,
         mut x_offset,
         mode,
         mut placeholder_opt,
@@ -236,61 +234,37 @@ pub(crate) fn cosmic_edit_redraw_buffer(
             },
         );
 
-        // replace target image with modified pixel buffer
-        match handle_opt {
-            Some(mut handle) => replace_target_image(
-                &mut handle,
-                &mut images,
-                widget_width,
-                widget_height,
-                pixels,
-            ),
-            None => replace_target_image(
-                &mut ui_image_opt.unwrap().texture,
-                &mut images,
-                widget_width,
-                widget_height,
-                pixels,
-            ),
+        let canvas = &mut canvas.0;
+
+        if let Some(prev_image) = images.get_mut(canvas) {
+            if *canvas == bevy::render::texture::DEFAULT_IMAGE_HANDLE.typed() {
+                let mut prev_image = prev_image.clone();
+                prev_image.data.clear();
+                prev_image.data.extend_from_slice(pixels.as_slice());
+                prev_image.resize(Extent3d {
+                    width: widget_width as u32,
+                    height: widget_height as u32,
+                    depth_or_array_layers: 1,
+                });
+                let handle_id: HandleId = HandleId::random::<Image>();
+                let new_handle: Handle<Image> = Handle::weak(handle_id);
+                let new_handle = images.set(new_handle, prev_image);
+                *canvas = new_handle;
+            } else {
+                prev_image.data.clear();
+                prev_image.data.extend_from_slice(pixels.as_slice());
+                prev_image.resize(Extent3d {
+                    width: widget_width as u32,
+                    height: widget_height as u32,
+                    depth_or_array_layers: 1,
+                });
+            }
         }
 
         editor.buffer_mut().set_redraw(false);
     }
 }
 
-fn replace_target_image(
-    cosmic_canvas_img_handle: &mut Handle<Image>,
-    images: &mut ResMut<Assets<Image>>,
-    width: f32,
-    height: f32,
-    pixels: Vec<u8>,
-) {
-    if let Some(prev_image) = images.get_mut(cosmic_canvas_img_handle) {
-        if *cosmic_canvas_img_handle == bevy::render::texture::DEFAULT_IMAGE_HANDLE.typed() {
-            let mut prev_image = prev_image.clone();
-            prev_image.data.clear();
-            prev_image.data.extend_from_slice(pixels.as_slice());
-            prev_image.resize(Extent3d {
-                width: width as u32,
-                height: height as u32,
-                depth_or_array_layers: 1,
-            });
-            let handle_id: HandleId = HandleId::random::<Image>();
-            let new_handle: Handle<Image> = Handle::weak(handle_id);
-            let new_handle = images.set(new_handle, prev_image);
-            *cosmic_canvas_img_handle = new_handle;
-        } else {
-            prev_image.data.clear();
-            prev_image.data.extend_from_slice(pixels.as_slice());
-            prev_image.resize(Extent3d {
-                width: width as u32,
-                height: height as u32,
-                depth_or_array_layers: 1,
-            });
-        }
-    }
-}
-
 fn draw_pixel(
     buffer: &mut [u8],
     width: i32,
@@ -475,3 +449,35 @@ pub(crate) fn on_scale_factor_change(
         }
     }
 }
+
+pub(crate) fn cosmic_ui_to_canvas(
+    mut added_ui_images: Query<(&mut UiImage, &CosmicCanvas), Added<UiImage>>,
+) {
+    for (mut ui_image, canvas) in added_ui_images.iter_mut() {
+        ui_image.texture = canvas.0.clone_weak();
+    }
+}
+
+pub(crate) fn update_handle_ui(
+    mut changed_handles: Query<(&mut UiImage, &CosmicCanvas), Changed<CosmicCanvas>>,
+) {
+    for (mut ui_image, canvas) in changed_handles.iter_mut() {
+        ui_image.texture = canvas.0.clone_weak();
+    }
+}
+
+pub(crate) fn cosmic_sprite_to_canvas(
+    mut added_sprite_textures: Query<(&mut Handle<Image>, &CosmicCanvas), Added<Handle<Image>>>,
+) {
+    for (mut handle, canvas) in added_sprite_textures.iter_mut() {
+        *handle = canvas.0.clone_weak();
+    }
+}
+
+pub(crate) fn update_handle_sprite(
+    mut changed_handles: Query<(&mut Handle<Image>, &CosmicCanvas), Changed<CosmicCanvas>>,
+) {
+    for (mut handle, canvas) in changed_handles.iter_mut() {
+        *handle = canvas.0.clone_weak();
+    }
+}