diff --git a/examples/every_option.rs b/examples/every_option.rs
index 05b7473901c7fcacc3ad15f2e58473a9a4fc218a..96c86c3ece4a9fcab843b1538971a5c70c8c0863 100644
--- a/examples/every_option.rs
+++ b/examples/every_option.rs
@@ -26,6 +26,7 @@ fn setup(mut commands: Commands, mut font_system: ResMut<CosmicFontSystem>) {
             max_chars: MaxChars(15),
             max_lines: MaxLines(1),
             mode: CosmicWrap::Wrap,
+            hover_cursor: HoverCursor(CursorIcon::Pointer),
             // CosmicEdit draws to this spritebundle
             sprite_bundle: SpriteBundle {
                 sprite: Sprite {
diff --git a/examples/password.rs b/examples/password.rs
index 75bfac024f3cd96cd5f746e1ef203c6c817d0e1c..290a2c7288cb9771ffe1ab1090906dfdf6325e09 100644
--- a/examples/password.rs
+++ b/examples/password.rs
@@ -29,10 +29,7 @@ fn setup(mut commands: Commands) {
 fn main() {
     App::new()
         .add_plugins(DefaultPlugins)
-        .add_plugins(CosmicEditPlugin {
-            change_cursor: CursorConfig::Default,
-            ..default()
-        })
+        .add_plugins(CosmicEditPlugin { ..default() })
         .add_systems(Startup, setup)
         .add_systems(
             Update,
diff --git a/examples/sprite_and_ui_clickable.rs b/examples/sprite_and_ui_clickable.rs
index 76c8cd70b36e677a23c6023d576119dd84e7957f..290edaf10e754ce4f841dbd6433a49b40e707f1e 100644
--- a/examples/sprite_and_ui_clickable.rs
+++ b/examples/sprite_and_ui_clickable.rs
@@ -68,10 +68,7 @@ fn ev_test(
 fn main() {
     App::new()
         .add_plugins(DefaultPlugins)
-        .add_plugins(CosmicEditPlugin {
-            change_cursor: CursorConfig::Default,
-            ..default()
-        })
+        .add_plugins(CosmicEditPlugin { ..default() })
         .add_systems(Startup, setup)
         .add_systems(
             Update,
diff --git a/src/cosmic_edit.rs b/src/cosmic_edit.rs
index 3ac21ed7258744bba7f148e293ff9c5db32c9104..d3f430d3266fb2191ab6c216d56a0f14c42e055b 100644
--- a/src/cosmic_edit.rs
+++ b/src/cosmic_edit.rs
@@ -187,6 +187,7 @@ pub struct CosmicEditBundle {
     pub text_position: CosmicTextAlign,
     pub padding: CosmicPadding,
     pub widget_size: CosmicWidgetSize,
+    pub hover_cursor: HoverCursor,
 }
 
 impl Default for CosmicEditBundle {
@@ -213,6 +214,7 @@ impl Default for CosmicEditBundle {
             x_offset: Default::default(),
             padding: Default::default(),
             widget_size: Default::default(),
+            hover_cursor: Default::default(),
         }
     }
 }
diff --git a/src/cursor.rs b/src/cursor.rs
index 04bb4e03bc0e08838ee5bef7d950a6ceb48b5fad..f54fef69fdd8a5b2c728f236aa98bd98207e9089 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -8,51 +8,38 @@ use bevy::{input::mouse::MouseMotion, prelude::*, window::PrimaryWindow};
 #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CursorSet;
 
-/// Config enum for mouse cursor events.
-#[derive(Default, Clone)]
-pub enum CursorConfig {
-    /// Emit [`TextHoverIn`] and [`TextHoverOut`] events and change mouse cursor on hover
-    #[default]
-    Default,
-    /// Emit [`TextHoverIn`] and [`TextHoverOut`] events, but do not change the cursor
-    Events,
-    /// Ignore mouse events
-    None,
-}
-
-pub(crate) struct CursorPlugin {
-    pub change_cursor: CursorConfig,
-}
+pub struct CursorPlugin;
 
 impl Plugin for CursorPlugin {
     fn build(&self, app: &mut App) {
-        match self.change_cursor {
-            CursorConfig::Default => {
-                app.add_systems(Update, (hover_sprites, hover_ui, change_cursor))
-                    .add_event::<TextHoverIn>()
-                    .add_event::<TextHoverOut>();
-            }
-            CursorConfig::Events => {
-                app.add_systems(Update, (hover_sprites, hover_ui))
-                    .add_event::<TextHoverIn>()
-                    .add_event::<TextHoverOut>();
-            }
-            CursorConfig::None => {}
-        }
+        app.add_systems(Update, ((hover_sprites, hover_ui), change_cursor).chain())
+            .add_event::<TextHoverIn>()
+            .add_event::<TextHoverOut>();
     }
 }
 
-/// For use with custom cursor control; Event is emitted when cursor enters a text widget
-#[derive(Event)]
-pub struct TextHoverIn;
+#[derive(Component, Deref)]
+pub struct HoverCursor(pub CursorIcon);
+
+impl Default for HoverCursor {
+    fn default() -> Self {
+        Self(CursorIcon::Text)
+    }
+}
+
+/// For use with custom cursor control
+/// Event is emitted when cursor enters a text widget
+/// Event contains the cursor from the buffer's [`HoverCursor`]
+#[derive(Event, Deref)]
+pub struct TextHoverIn(pub CursorIcon);
 
-/// For use with custom cursor control; Event is emitted when cursor leaves a text widget
+/// For use with custom cursor control
+/// Event is emitted when cursor leaves a text widget
 #[derive(Event)]
 pub struct TextHoverOut;
 
-/// Switches mouse cursor icon when hover events are received
-pub fn change_cursor(
-    evr_hover_in: EventReader<TextHoverIn>,
+pub(crate) fn change_cursor(
+    mut evr_hover_in: EventReader<TextHoverIn>,
     evr_hover_out: EventReader<TextHoverOut>,
     evr_text_changed: EventReader<CosmicTextChanged>,
     evr_mouse_motion: EventReader<MouseMotion>,
@@ -63,15 +50,17 @@ pub fn change_cursor(
         return;
     }
     let mut window = windows.single_mut();
-    if !evr_hover_in.is_empty() {
-        window.cursor.icon = CursorIcon::Text;
-    }
-    if !evr_hover_out.is_empty() {
+
+    if let Some(ev) = evr_hover_in.read().last() {
+        window.cursor.icon = ev.0;
+    } else if !evr_hover_out.is_empty() {
         window.cursor.icon = CursorIcon::Default;
     }
+
     if !evr_text_changed.is_empty() {
         window.cursor.visible = false;
     }
+
     if mouse_buttons.get_just_pressed().len() != 0 || !evr_mouse_motion.is_empty() {
         window.cursor.visible = true;
     }
@@ -84,11 +73,12 @@ type CameraQuery<'a, 'b, 'c, 'd> =
 #[cfg(not(feature = "multicam"))]
 type CameraQuery<'a, 'b, 'c, 'd> = Query<'a, 'b, (&'c Camera, &'d GlobalTransform)>;
 
-/// Sprite widget mouse cursor hover detection system. Sends [`TextHoverIn`] and [`TextHoverOut`]
-/// events.
-pub fn hover_sprites(
+pub(crate) fn hover_sprites(
     windows: Query<&Window, With<PrimaryWindow>>,
-    mut cosmic_edit_query: Query<(&mut Sprite, &Visibility, &GlobalTransform), With<CosmicBuffer>>,
+    mut cosmic_edit_query: Query<
+        (&mut Sprite, &Visibility, &GlobalTransform, &HoverCursor),
+        With<CosmicBuffer>,
+    >,
     camera_q: CameraQuery,
     mut hovered: Local<bool>,
     mut last_hovered: Local<bool>,
@@ -101,7 +91,10 @@ pub fn hover_sprites(
     }
     let window = windows.single();
     let (camera, camera_transform) = camera_q.single();
-    for (sprite, visibility, node_transform) in &mut cosmic_edit_query.iter_mut() {
+
+    let mut icon = CursorIcon::Default;
+
+    for (sprite, visibility, node_transform, hover) in &mut cosmic_edit_query.iter_mut() {
         if visibility == Visibility::Hidden {
             continue;
         }
@@ -115,6 +108,7 @@ pub fn hover_sprites(
             if let Some(pos) = camera.viewport_to_world_2d(camera_transform, pos) {
                 if x_min < pos.x && pos.x < x_max && y_min < pos.y && pos.y < y_max {
                     *hovered = true;
+                    icon = hover.0;
                 }
             }
         }
@@ -122,7 +116,7 @@ pub fn hover_sprites(
 
     if *last_hovered != *hovered {
         if *hovered {
-            evw_hover_in.send(TextHoverIn);
+            evw_hover_in.send(TextHoverIn(icon));
         } else {
             evw_hover_out.send(TextHoverOut);
         }
@@ -131,20 +125,21 @@ pub fn hover_sprites(
     *last_hovered = *hovered;
 }
 
-/// UI widget mouse cursor hover detection system. Sends [`TextHoverIn`] and [`TextHoverOut`]
-/// events.
-pub fn hover_ui(
-    mut interaction_query: Query<&Interaction, (Changed<Interaction>, With<CosmicSource>)>,
+pub(crate) fn hover_ui(
+    interaction_query: Query<(&Interaction, &CosmicSource), Changed<Interaction>>,
+    cosmic_query: Query<&HoverCursor, With<CosmicBuffer>>,
     mut evw_hover_in: EventWriter<TextHoverIn>,
     mut evw_hover_out: EventWriter<TextHoverOut>,
 ) {
-    for interaction in interaction_query.iter_mut() {
+    for (interaction, source) in interaction_query.iter() {
         match interaction {
             Interaction::None => {
                 evw_hover_out.send(TextHoverOut);
             }
             Interaction::Hovered => {
-                evw_hover_in.send(TextHoverIn);
+                if let Ok(hover) = cosmic_query.get(source.0) {
+                    evw_hover_in.send(TextHoverIn(hover.0));
+                }
             }
             _ => {}
         }
diff --git a/src/lib.rs b/src/lib.rs
index bec8d56a5160b54d63eae8f00718f5e56f587178..3c1331d414fd0ebf018f8530b6127a4db81ae0bf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -116,7 +116,6 @@ pub use widget::*;
 #[derive(Default)]
 pub struct CosmicEditPlugin {
     pub font_config: CosmicFontConfig,
-    pub change_cursor: CursorConfig,
 }
 
 impl Plugin for CosmicEditPlugin {
@@ -129,9 +128,7 @@ impl Plugin for CosmicEditPlugin {
             WidgetPlugin,
             InputPlugin,
             FocusPlugin,
-            CursorPlugin {
-                change_cursor: self.change_cursor.clone(),
-            },
+            CursorPlugin,
             PlaceholderPlugin,
             PasswordPlugin,
             EventsPlugin,