diff --git a/CHANGELOG.md b/CHANGELOG.md
index 611187dc20527b5071d7f250f4982e00ebd69737..476b6336fde45eb391d0b224269e30f7f2eac3d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,8 @@ current (development)
   component in its parent. See #932
 - Feature: Add `EntryState::index`. This allows to get the index of a menu entry.
   See #932
+- Feature: Add `SliderOption::on_change`. This allows to set a callback when the
+  slider value changes. See #938.
 
 ### Dom
 - Feature: Add `hscroll_indicator`. It display an horizontal indicator
diff --git a/include/ftxui/component/component_options.hpp b/include/ftxui/component/component_options.hpp
index a55a4df842a9bc90c7ff66ff0991535e094c5dcd..e9dd0845365881dbc37d1d7b34ff6331bcb1cd33 100644
--- a/include/ftxui/component/component_options.hpp
+++ b/include/ftxui/component/component_options.hpp
@@ -228,6 +228,7 @@ struct SliderOption {
   Direction direction = Direction::Right;
   Color color_active = Color::White;
   Color color_inactive = Color::GrayDark;
+  std::function<void()> on_change;  ///> Called when `value` is updated.
 };
 
 // Parameter pack used by `WindowOptions::render`.
diff --git a/src/ftxui/component/slider.cpp b/src/ftxui/component/slider.cpp
index b1075805cab66c73c675594f2237aaf23f682125..e8efbb8576105b97f2da91f1a87e2bbe71c6c1aa 100644
--- a/src/ftxui/component/slider.cpp
+++ b/src/ftxui/component/slider.cpp
@@ -35,31 +35,26 @@ Decorator flexDirection(Direction direction) {
 }
 
 template <class T>
-class SliderBase : public ComponentBase {
+class SliderBase : public SliderOption<T>, public ComponentBase {
  public:
-  explicit SliderBase(SliderOption<T> options)
-      : value_(options.value),
-        min_(options.min),
-        max_(options.max),
-        increment_(options.increment),
-        options_(options) {}
+  explicit SliderBase(SliderOption<T> options) : SliderOption<T>(options) {}
 
   Element Render() override {
-    auto gauge_color = Focused() ? color(options_.color_active)
-                                 : color(options_.color_inactive);
-    const float percent = float(value_() - min_()) / float(max_() - min_());
-    return gaugeDirection(percent, options_.direction) |
-           flexDirection(options_.direction) | reflect(gauge_box_) |
-           gauge_color;
+    auto gauge_color =
+        Focused() ? color(this->color_active) : color(this->color_inactive);
+    const float percent =
+        float(this->value() - this->min()) / float(this->max() - this->min());
+    return gaugeDirection(percent, this->direction) |
+           flexDirection(this->direction) | reflect(gauge_box_) | gauge_color;
   }
 
   void OnLeft() {
-    switch (options_.direction) {
+    switch (this->direction) {
       case Direction::Right:
-        value_() -= increment_();
+        this->value() -= this->increment();
         break;
       case Direction::Left:
-        value_() += increment_();
+        this->value() += this->increment();
         break;
       case Direction::Up:
       case Direction::Down:
@@ -68,12 +63,12 @@ class SliderBase : public ComponentBase {
   }
 
   void OnRight() {
-    switch (options_.direction) {
+    switch (this->direction) {
       case Direction::Right:
-        value_() += increment_();
+        this->value() += this->increment();
         break;
       case Direction::Left:
-        value_() -= increment_();
+        this->value() -= this->increment();
         break;
       case Direction::Up:
       case Direction::Down:
@@ -82,12 +77,12 @@ class SliderBase : public ComponentBase {
   }
 
   void OnUp() {
-    switch (options_.direction) {
+    switch (this->direction) {
       case Direction::Up:
-        value_() -= increment_();
+        this->value() -= this->increment();
         break;
       case Direction::Down:
-        value_() += increment_();
+        this->value() += this->increment();
         break;
       case Direction::Left:
       case Direction::Right:
@@ -96,12 +91,12 @@ class SliderBase : public ComponentBase {
   }
 
   void OnDown() {
-    switch (options_.direction) {
+    switch (this->direction) {
       case Direction::Down:
-        value_() -= increment_();
+        this->value() += this->increment();
         break;
       case Direction::Up:
-        value_() += increment_();
+        this->value() -= this->increment();
         break;
       case Direction::Left:
       case Direction::Right:
@@ -114,7 +109,7 @@ class SliderBase : public ComponentBase {
       return OnMouseEvent(event);
     }
 
-    T old_value = value_();
+    T old_value = this->value();
     if (event == Event::ArrowLeft || event == Event::Character('h')) {
       OnLeft();
     }
@@ -128,8 +123,11 @@ class SliderBase : public ComponentBase {
       OnUp();
     }
 
-    value_() = util::clamp(value_(), min_(), max_());
-    if (old_value != value_()) {
+    this->value() = std::max(this->min(), std::min(this->max(), this->value()));
+    if (old_value != this->value()) {
+      if (this->on_change) {
+        this->on_change();
+      }
       return true;
     }
 
@@ -143,33 +141,45 @@ class SliderBase : public ComponentBase {
         return true;
       }
 
-      switch (options_.direction) {
+      T old_value = this->value();
+      switch (this->direction) {
         case Direction::Right: {
-          value_() = min_() + (event.mouse().x - gauge_box_.x_min) *
-                                  (max_() - min_()) /
-                                  (gauge_box_.x_max - gauge_box_.x_min);
+          this->value() =
+              this->min() + (event.mouse().x - gauge_box_.x_min) *
+                                (this->max() - this->min()) /
+                                (gauge_box_.x_max - gauge_box_.x_min);
+
           break;
         }
         case Direction::Left: {
-          value_() = max_() - (event.mouse().x - gauge_box_.x_min) *
-                                  (max_() - min_()) /
-                                  (gauge_box_.x_max - gauge_box_.x_min);
+          this->value() =
+              this->max() - (event.mouse().x - gauge_box_.x_min) *
+                                (this->max() - this->min()) /
+                                (gauge_box_.x_max - gauge_box_.x_min);
           break;
         }
         case Direction::Down: {
-          value_() = min_() + (event.mouse().y - gauge_box_.y_min) *
-                                  (max_() - min_()) /
-                                  (gauge_box_.y_max - gauge_box_.y_min);
+          this->value() =
+              this->min() + (event.mouse().y - gauge_box_.y_min) *
+                                (this->max() - this->min()) /
+                                (gauge_box_.y_max - gauge_box_.y_min);
           break;
         }
         case Direction::Up: {
-          value_() = max_() - (event.mouse().y - gauge_box_.y_min) *
-                                  (max_() - min_()) /
-                                  (gauge_box_.y_max - gauge_box_.y_min);
+          this->value() =
+              this->max() - (event.mouse().y - gauge_box_.y_min) *
+                                (this->max() - this->min()) /
+                                (gauge_box_.y_max - gauge_box_.y_min);
           break;
         }
       }
-      value_() = std::max(min_(), std::min(max_(), value_()));
+
+      this->value() =
+          std::max(this->min(), std::min(this->max(), this->value()));
+
+      if (old_value != this->value() && this->on_change) {
+        this->on_change();
+      }
       return true;
     }
 
@@ -197,11 +207,6 @@ class SliderBase : public ComponentBase {
   bool Focusable() const final { return true; }
 
  private:
-  Ref<T> value_;
-  ConstRef<T> min_;
-  ConstRef<T> max_;
-  ConstRef<T> increment_;
-  SliderOption<T> options_;
   Box gauge_box_;
   CapturedMouse captured_mouse_;
 };
@@ -256,6 +261,7 @@ class SliderWithLabel : public ComponentBase {
   Box box_;
   bool mouse_hover_ = false;
 };
+
 }  // namespace
 
 /// @brief An horizontal slider.
@@ -340,6 +346,7 @@ template <typename T>
 Component Slider(SliderOption<T> options) {
   return Make<SliderBase<T>>(options);
 }
+
 template Component Slider(SliderOption<int8_t>);
 template Component Slider(SliderOption<int16_t>);
 template Component Slider(SliderOption<int32_t>);
diff --git a/src/ftxui/component/slider_test.cpp b/src/ftxui/component/slider_test.cpp
index c2057555726b0f78d7e0d8b4f4e37b14256dc34b..21b9656948a3495c043a04baf5c218a4db9572bc 100644
--- a/src/ftxui/component/slider_test.cpp
+++ b/src/ftxui/component/slider_test.cpp
@@ -45,6 +45,7 @@ Event MouseReleased(int x, int y) {
 }  // namespace
 
 TEST(SliderTest, Right) {
+  int updated = 0;
   int value = 50;
   auto slider = Slider<int>({
       .value = &value,
@@ -52,23 +53,31 @@ TEST(SliderTest, Right) {
       .max = 100,
       .increment = 10,
       .direction = Direction::Right,
+      .on_change = [&]() { updated++; },
   });
   Screen screen(11, 1);
   Render(screen, slider->Render());
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(3, 0)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(9, 0)));
   EXPECT_EQ(value, 90);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(9, 2)));
   EXPECT_EQ(value, 90);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(5, 2)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 2);
   EXPECT_TRUE(slider->OnEvent(MouseReleased(5, 2)));
   EXPECT_FALSE(slider->OnEvent(MousePressed(5, 2)));
+  EXPECT_EQ(value, 50);
 }
 
 TEST(SliderTest, Left) {
+  int updated = 0;
   int value = 50;
   auto slider = Slider<int>({
       .value = &value,
@@ -76,23 +85,31 @@ TEST(SliderTest, Left) {
       .max = 100,
       .increment = 10,
       .direction = Direction::Left,
+      .on_change = [&]() { updated++; },
   });
   Screen screen(11, 1);
   Render(screen, slider->Render());
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(3, 0)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(9, 0)));
   EXPECT_EQ(value, 10);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(9, 2)));
   EXPECT_EQ(value, 10);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(5, 2)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 2);
   EXPECT_TRUE(slider->OnEvent(MouseReleased(5, 2)));
   EXPECT_FALSE(slider->OnEvent(MousePressed(5, 2)));
+  EXPECT_EQ(value, 50);
 }
 
 TEST(SliderTest, Down) {
+  int updated = 0;
   int value = 50;
   auto slider = Slider<int>({
       .value = &value,
@@ -100,23 +117,32 @@ TEST(SliderTest, Down) {
       .max = 100,
       .increment = 10,
       .direction = Direction::Down,
+      .on_change = [&]() { updated++; },
   });
   Screen screen(1, 11);
   Render(screen, slider->Render());
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(0, 3)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(0, 9)));
   EXPECT_EQ(value, 90);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(2, 9)));
   EXPECT_EQ(value, 90);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(2, 5)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 2);
   EXPECT_TRUE(slider->OnEvent(MouseReleased(2, 5)));
   EXPECT_FALSE(slider->OnEvent(MousePressed(2, 5)));
+  EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 2);
 }
 
 TEST(SliderTest, Up) {
+  int updated = 0;
   int value = 50;
   auto slider = Slider<int>({
       .value = &value,
@@ -124,20 +150,27 @@ TEST(SliderTest, Up) {
       .max = 100,
       .increment = 10,
       .direction = Direction::Up,
+      .on_change = [&]() { updated++; },
   });
   Screen screen(1, 11);
   Render(screen, slider->Render());
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(0, 3)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 0);
   EXPECT_TRUE(slider->OnEvent(MousePressed(0, 9)));
   EXPECT_EQ(value, 10);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(2, 9)));
   EXPECT_EQ(value, 10);
+  EXPECT_EQ(updated, 1);
   EXPECT_TRUE(slider->OnEvent(MousePressed(2, 5)));
   EXPECT_EQ(value, 50);
+  EXPECT_EQ(updated, 2);
   EXPECT_TRUE(slider->OnEvent(MouseReleased(2, 5)));
   EXPECT_FALSE(slider->OnEvent(MousePressed(2, 5)));
+  EXPECT_EQ(value, 50);
 }
 
 TEST(SliderTest, Focus) {