diff --git a/.clang-tidy b/.clang-tidy
index cf1723de038e0476aade3dd83d21b0535d90eb46..d775961af01a191bc3d71f04debed688dfaa9923 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,6 +1,8 @@
 ---
 Checks: "*,
+        -*-magic-numbers,
         -*-narrowing-conversions
+        -*-unnecessary-value-param,
         -*-uppercase-literal-suffix,
         -abseil-*,
         -altera-*,
@@ -9,6 +11,7 @@ Checks: "*,
         -cppcoreguidelines-non-private-member-variables-in-classes,
         -fuchsia-*,
         -google-*,
+        -hicpp-signed-bitwise,
         -llvm*,
         -misc-no-recursion,
         -misc-non-private-member-variables-in-classes,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 200b7a1a5e385b68f495fc045f7d967048857d9f..f9f0e341bbf36f3601b9f67ab4958c693c260e45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,10 +9,23 @@ current (development)
 - Breaking: GaugeDirection enum is renamed Direction
 - Breaking: Direction enum is renamed WidthOrHeight
 - Breaking: Remove `ComponentBase` copy constructor/assignment.
+- Breaking: MenuOption::entries is renamed MenuOption::entries_option.
+- Breaking: Ref<XxxOption> becomes XxxOption in component constructors.
 - Feature: `ResizeableSplit` now support arbitrary element as a separator.
 - Feature: `input` is now supporting multiple lines.
 - Feature: `input` style is now customizeable.
 - Bugfix: Support F1-F5 from OS terminal.
+- Feature: Add struct based constructor:
+  ```cpp
+  Component Button(ButtonOption options);
+  Component Checkbox(CheckboxOption options);
+  Component Input(InputOption options);
+  Component Menu(MenuOption options);
+  Component MenuEntry(MenuEntryOption options);
+  Component Radiobox(RadioboxOption options);
+  Component Slider(SliderOption<T> options);
+  Component ResizableSplit(ResizableSplitOption options);
+  ```
 
 ### Dom
 - Feature: Add `hyperlink` decorator. For instance:
diff --git a/cmake/ftxui_test.cmake b/cmake/ftxui_test.cmake
index 4c1b15a612b557a1b38ae7e7c4dd349c9a2b8596..71caa6919ea4be4c1a4a93f81dbd492f59e1dc74 100644
--- a/cmake/ftxui_test.cmake
+++ b/cmake/ftxui_test.cmake
@@ -69,4 +69,6 @@ gtest_discover_tests(ftxui-tests
   DISCOVERY_TIMEOUT 600
 )
 
-set(CMAKE_CTEST_ARGUMENTS "--rerun-failed --output-on-failure")
+#set(CMAKE_CTEST_ARGUMENTS "--rerun-failed --output-on-failure")
+#set_tests_properties(gen_init_queries PROPERTIES FIXTURES_SETUP f_init_queries)
+#set_tests_properties(test PROPERTIES  FIXTURES_REQUIRED f_init_queries)
diff --git a/examples/component/button_in_frame.cpp b/examples/component/button_in_frame.cpp
index 44034d69227406893e25d217f1cb66a06cc85aad..26ba62233636818dfd3693bf766e9083516c78c8 100644
--- a/examples/component/button_in_frame.cpp
+++ b/examples/component/button_in_frame.cpp
@@ -15,13 +15,12 @@ int main() {
   int counter = 0;
   auto on_click = [&] { counter++; };
 
-  auto button_style = ButtonOption::Animated(Color::Default, Color::GrayDark,
-                                             Color::Default, Color::White);
+  auto style = ButtonOption::Animated(Color::Default, Color::GrayDark,
+                                      Color::Default, Color::White);
 
   auto container = Container::Vertical({});
   for (int i = 0; i < 30; ++i) {
-    auto button =
-        Button("Button " + std::to_string(i), on_click, &button_style);
+    auto button = Button("Button " + std::to_string(i), on_click, style);
     container->Add(button);
   }
 
diff --git a/examples/component/menu.cpp b/examples/component/menu.cpp
index a0d03c6e5244799d18b8e513118ebc2aaa456a35..0794691bc487193114643758094911de2494c813 100644
--- a/examples/component/menu.cpp
+++ b/examples/component/menu.cpp
@@ -21,7 +21,7 @@ int main() {
 
   MenuOption option;
   option.on_enter = screen.ExitLoopClosure();
-  auto menu = Menu(&entries, &selected, &option);
+  auto menu = Menu(&entries, &selected, option);
 
   screen.Loop(menu);
 
diff --git a/examples/component/menu2.cpp b/examples/component/menu2.cpp
index 88713df57b30556b1e7322c297b97e44e2abc6e6..9854f80384d06fb48f562a58c94db7fa70396ea3 100644
--- a/examples/component/menu2.cpp
+++ b/examples/component/menu2.cpp
@@ -27,9 +27,9 @@ int main() {
   int left_menu_selected = 0;
   int right_menu_selected = 0;
   Component left_menu_ =
-      Menu(&left_menu_entries, &left_menu_selected, &menu_option);
+      Menu(&left_menu_entries, &left_menu_selected, menu_option);
   Component right_menu_ =
-      Menu(&right_menu_entries, &right_menu_selected, &menu_option);
+      Menu(&right_menu_entries, &right_menu_selected, menu_option);
 
   Component container = Container::Horizontal({
       left_menu_,
diff --git a/examples/component/menu_style.cpp b/examples/component/menu_style.cpp
index b7924176714bc5346505c9517f0f302257feeea1..b9fd71a74130daa77ee8720ccad503771a84258f 100644
--- a/examples/component/menu_style.cpp
+++ b/examples/component/menu_style.cpp
@@ -110,7 +110,7 @@ int main() {
 
 Component VMenu1(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     state.label = (state.active ? "> " : "  ") + state.label;
     Element e = text(state.label);
     if (state.focused)
@@ -124,7 +124,7 @@ Component VMenu1(std::vector<std::string>* entries, int* selected) {
 
 Component VMenu2(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     state.label += (state.active ? " <" : "  ");
     Element e = hbox(filler(), text(state.label));
     if (state.focused)
@@ -138,7 +138,7 @@ Component VMenu2(std::vector<std::string>* entries, int* selected) {
 
 Component VMenu3(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     Element e = state.active ? text("[" + state.label + "]")
                              : text(" " + state.label + " ");
     if (state.focused)
@@ -155,7 +155,7 @@ Component VMenu3(std::vector<std::string>* entries, int* selected) {
 
 Component VMenu4(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     if (state.active && state.focused) {
       return text(state.label) | color(Color::Yellow) | bgcolor(Color::Black) |
              bold;
@@ -175,7 +175,7 @@ Component VMenu4(std::vector<std::string>* entries, int* selected) {
 
 Component VMenu5(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     auto element = text(state.label);
     if (state.active && state.focused) {
       return element | borderDouble;
@@ -201,19 +201,19 @@ Component VMenu6(std::vector<std::string>* entries, int* selected) {
 
 Component VMenu7(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.animated_colors.foreground.enabled = true;
-  option.entries.animated_colors.background.enabled = true;
-  option.entries.animated_colors.background.active = Color::Red;
-  option.entries.animated_colors.background.inactive = Color::Black;
-  option.entries.animated_colors.foreground.active = Color::White;
-  option.entries.animated_colors.foreground.inactive = Color::Red;
+  option.entries_option.animated_colors.foreground.enabled = true;
+  option.entries_option.animated_colors.background.enabled = true;
+  option.entries_option.animated_colors.background.active = Color::Red;
+  option.entries_option.animated_colors.background.inactive = Color::Black;
+  option.entries_option.animated_colors.foreground.active = Color::White;
+  option.entries_option.animated_colors.foreground.inactive = Color::Red;
   return Menu(entries, selected, option);
 }
 
 Component VMenu8(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::Vertical();
-  option.entries.animated_colors.foreground.Set(Color::Red, Color::White,
-                                                std::chrono::milliseconds(500));
+  option.entries_option.animated_colors.foreground.Set(
+      Color::Red, Color::White, std::chrono::milliseconds(500));
   return Menu(entries, selected, option);
 }
 
@@ -240,7 +240,7 @@ Component HMenu5(std::vector<std::string>* entries, int* selected) {
   auto option = MenuOption::HorizontalAnimated();
   option.underline.SetAnimation(std::chrono::milliseconds(1500),
                                 animation::easing::ElasticOut);
-  option.entries.transform = [](EntryState state) {
+  option.entries_option.transform = [](EntryState state) {
     Element e = text(state.label) | hcenter | flex;
     if (state.active && state.focused)
       e = e | bold;
diff --git a/include/ftxui/component/component.hpp b/include/ftxui/component/component.hpp
index a9289ae872ba852d5f64995e402e8389f9097259..1842bf4b342cb9b500c6e587d158630c637c1a93 100644
--- a/include/ftxui/component/component.hpp
+++ b/include/ftxui/component/component.hpp
@@ -40,37 +40,42 @@ Component Vertical(Components children, int* selector);
 Component Horizontal(Components children);
 Component Horizontal(Components children, int* selector);
 Component Tab(Components children, int* selector);
-
 }  // namespace Container
 
+Component Button(ButtonOption options);
 Component Button(ConstStringRef label,
                  std::function<void()> on_click,
-                 Ref<ButtonOption> = ButtonOption::Simple());
+                 ButtonOption options = ButtonOption::Simple());
 
+Component Checkbox(CheckboxOption options);
 Component Checkbox(ConstStringRef label,
                    bool* checked,
-                   Ref<CheckboxOption> option = CheckboxOption::Simple());
+                   CheckboxOption options = CheckboxOption::Simple());
 
-Component Input(StringRef content, Ref<InputOption> option = {});
+Component Input(InputOption options = {});
+Component Input(StringRef content, InputOption options = {});
 Component Input(StringRef content,
                 StringRef placeholder,
-                Ref<InputOption> option = {});
+                InputOption options = {});
 
+Component Menu(MenuOption options);
 Component Menu(ConstStringListRef entries,
                int* selected_,
-               Ref<MenuOption> = MenuOption::Vertical());
-Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> = {});
-
-Component Dropdown(ConstStringListRef entries, int* selected);
+               MenuOption options = MenuOption::Vertical());
+Component MenuEntry(MenuEntryOption options);
+Component MenuEntry(ConstStringRef label, MenuEntryOption options = {});
 
+Component Radiobox(RadioboxOption options);
 Component Radiobox(ConstStringListRef entries,
                    int* selected_,
-                   Ref<RadioboxOption> option = {});
+                   RadioboxOption options = {});
+
+Component Dropdown(ConstStringListRef entries, int* selected);
 Component Toggle(ConstStringListRef entries, int* selected);
 
 // General slider constructor:
 template <typename T>
-Component Slider(SliderOption<T> options = {});
+Component Slider(SliderOption<T> options);
 
 // Shorthand without the `SliderOption` constructor:
 Component Slider(ConstStringRef label,
@@ -89,11 +94,11 @@ Component Slider(ConstStringRef label,
                  ConstRef<long> max = 100l,
                  ConstRef<long> increment = 5l);
 
+Component ResizableSplit(ResizableSplitOption options);
 Component ResizableSplitLeft(Component main, Component back, int* main_size);
 Component ResizableSplitRight(Component main, Component back, int* main_size);
 Component ResizableSplitTop(Component main, Component back, int* main_size);
 Component ResizableSplitBottom(Component main, Component back, int* main_size);
-Component ResizableSplit(ResizableSplitOption options);
 
 Component Renderer(Component child, std::function<Element()>);
 Component Renderer(std::function<Element()>);
diff --git a/include/ftxui/component/component_options.hpp b/include/ftxui/component/component_options.hpp
index c5b330fa157b0163efd363c40209638f13ceef63..0967306eec49205335ba29aa3e881e08fdad8229 100644
--- a/include/ftxui/component/component_options.hpp
+++ b/include/ftxui/component/component_options.hpp
@@ -72,6 +72,7 @@ struct AnimatedColorsOption {
 /// @brief Option for the MenuEntry component.
 /// @ingroup component
 struct MenuEntryOption {
+  ConstStringRef label = "MenuEntry";
   std::function<Element(const EntryState& state)> transform;
   AnimatedColorsOption animated_colors;
 };
@@ -86,9 +87,12 @@ struct MenuOption {
   static MenuOption VerticalAnimated();
   static MenuOption Toggle();
 
+  ConstStringListRef entries;  ///> The list of entries.
+  Ref<int> selected = 0;       ///> The index of the selected entry.
+
   // Style:
   UnderlineOption underline;
-  MenuEntryOption entries;
+  MenuEntryOption entries_option;
   Direction direction = Direction::Down;
   std::function<Element()> elements_prefix;
   std::function<Element()> elements_infix;
@@ -115,6 +119,9 @@ struct ButtonOption {
                                Color background_active,
                                Color foreground_active);
 
+  ConstStringRef label = "Button";
+  std::function<void()> on_click = [] {};
+
   // Style:
   std::function<Element(const EntryState&)> transform;
   AnimatedColorsOption animated_colors;
@@ -126,6 +133,10 @@ struct CheckboxOption {
   // Standard constructors:
   static CheckboxOption Simple();
 
+  ConstStringRef label = "Checkbox";
+
+  Ref<bool> checked = false;
+
   // Style:
   std::function<Element(const EntryState&)> transform;
 
@@ -153,6 +164,9 @@ struct InputOption {
   /// @brief A white on black style with high margins:
   static InputOption Spacious();
 
+  /// The content of the input.
+  StringRef content = "";
+
   /// The content of the input when it's empty.
   StringRef placeholder = "";
 
@@ -176,6 +190,10 @@ struct RadioboxOption {
   // Standard constructors:
   static RadioboxOption Simple();
 
+  // Content:
+  ConstStringListRef entries;
+  Ref<int> selected = 0;
+
   // Style:
   std::function<Element(const EntryState&)> transform;
 
diff --git a/include/ftxui/screen/screen.hpp b/include/ftxui/screen/screen.hpp
index f73557ce4248103c4fea05174919929657c82ef0..68cb331cd64cbc01494c819bf12a646a58af7590 100644
--- a/include/ftxui/screen/screen.hpp
+++ b/include/ftxui/screen/screen.hpp
@@ -106,7 +106,7 @@ class Screen {
 
   // Store an hyperlink in the screen. Return the id of the hyperlink. The id is
   // used to identify the hyperlink when the user click on it.
-  uint8_t RegisterHyperlink(std::string link);
+  uint8_t RegisterHyperlink(const std::string& link);
   const std::string& Hyperlink(uint8_t id) const;
 
   Box stencil;
diff --git a/include/ftxui/util/ref.hpp b/include/ftxui/util/ref.hpp
index c650bc4222b1b14f622cb801814246d39ce1f8bb..e47743f9e4a285160a1926577f349151e6a4d950 100644
--- a/include/ftxui/util/ref.hpp
+++ b/include/ftxui/util/ref.hpp
@@ -13,6 +13,12 @@ class ConstRef {
   ConstRef() {}
   ConstRef(T t) : owned_(t) {}
   ConstRef(const T* t) : address_(t) {}
+  ConstRef(const ConstRef& t) : owned_(t.owned_), address_(t.address_) {}
+  ConstRef& operator=(const ConstRef& t) {
+    owned_ = t.owned_;
+    address_ = t.address_;
+    return *this;
+  }
   const T& operator*() const { return address_ ? *address_ : owned_; }
   const T& operator()() const { return address_ ? *address_ : owned_; }
   const T* operator->() const { return address_ ? address_ : &owned_; }
@@ -30,6 +36,12 @@ class Ref {
   Ref(const T& t) : owned_(t) {}
   Ref(T&& t) : owned_(std::forward<T>(t)) {}
   Ref(T* t) : owned_(), address_(t) {}
+  Ref(const Ref& t) : owned_(t.owned_), address_(t.address_) {}
+  Ref& operator=(const Ref& t) {
+    owned_ = t.owned_;
+    address_ = t.address_;
+    return *this;
+  }
   T& operator*() { return address_ ? *address_ : owned_; }
   T& operator()() { return address_ ? *address_ : owned_; }
   T* operator->() { return address_ ? address_ : &owned_; }
@@ -47,6 +59,12 @@ class StringRef {
   StringRef(std::string ref) : owned_(std::move(ref)) {}
   StringRef(const wchar_t* ref) : StringRef(to_string(std::wstring(ref))) {}
   StringRef(const char* ref) : StringRef(std::string(ref)) {}
+  StringRef(const StringRef& t) : owned_(t.owned_), address_(t.address_) {}
+  StringRef& operator=(const StringRef& t) {
+    owned_ = t.owned_;
+    address_ = t.address_;
+    return *this;
+  }
   std::string& operator*() { return address_ ? *address_ : owned_; }
   std::string& operator()() { return address_ ? *address_ : owned_; }
   std::string* operator->() { return address_ ? address_ : &owned_; }
@@ -67,6 +85,18 @@ class ConstStringRef {
   ConstStringRef(const wchar_t* ref) : ConstStringRef(std::wstring(ref)) {}
   ConstStringRef(const char* ref)
       : ConstStringRef(to_wstring(std::string(ref))) {}
+  ConstStringRef(const ConstStringRef& t)
+      : owned_(t.owned_), address_(t.address_) {}
+  ConstStringRef& operator=(const ConstStringRef& t) {
+    owned_ = t.owned_;
+    address_ = t.address_;
+    return *this;
+  }
+  ConstStringRef& operator=(ConstStringRef&& t) {
+    owned_ = std::move(t.owned_);
+    address_ = t.address_;
+    return *this;
+  }
   const std::string& operator()() const {
     return address_ ? *address_ : owned_;
   }
@@ -76,19 +106,35 @@ class ConstStringRef {
   }
 
  private:
-  const std::string owned_;
+  std::string owned_;
   const std::string* address_ = nullptr;
 };
 
 /// @brief An adapter. Reference a list of strings.
 class ConstStringListRef {
  public:
+  ConstStringListRef() = default;
   ConstStringListRef(const std::vector<std::string>* ref) : ref_(ref) {}
   ConstStringListRef(const std::vector<std::wstring>* ref) : ref_wide_(ref) {}
 
-  size_t size() const { return ref_ ? ref_->size() : ref_wide_->size(); }
+  size_t size() const {
+    if (ref_) {
+      return ref_->size();
+    }
+    if (ref_wide_) {
+      return ref_wide_->size();
+    }
+    return 0;
+  }
+
   std::string operator[](size_t i) const {
-    return ref_ ? (*ref_)[i] : to_string((*ref_wide_)[i]);
+    if (ref_) {
+      return (*ref_)[i];
+    }
+    if (ref_wide_) {
+      return to_string((*ref_wide_)[i]);
+    }
+    return "";
   }
 
  private:
diff --git a/src/ftxui/component/button.cpp b/src/ftxui/component/button.cpp
index 1c05d83c3baf9a686ff4e43f8cb0aa93797b14f1..c558dfbe219bfed372f35f18ecb1335c2101b931 100644
--- a/src/ftxui/component/button.cpp
+++ b/src/ftxui/component/button.cpp
@@ -30,7 +30,148 @@ Element DefaultTransform(EntryState params) {  // NOLINT
   return element;
 }
 
+class ButtonBase : public ComponentBase, public ButtonOption {
+ public:
+  explicit ButtonBase(ButtonOption option) : ButtonOption(std::move(option)) {}
+
+  // Component implementation:
+  Element Render() override {
+    const bool active = Active();
+    const bool focused = Focused();
+    const bool focused_or_hover = focused || mouse_hover_;
+
+    float target = focused_or_hover ? 1.f : 0.f;  // NOLINT
+    if (target != animator_background_.to()) {
+      SetAnimationTarget(target);
+    }
+
+    auto focus_management = focused ? focus : active ? select : nothing;
+    const EntryState state = {
+        *label,
+        false,
+        active,
+        focused_or_hover,
+    };
+
+    auto element = (transform ? transform : DefaultTransform)  //
+        (state);
+    return element | AnimatedColorStyle() | focus_management | reflect(box_);
+  }
+
+  Decorator AnimatedColorStyle() {
+    Decorator style = nothing;
+    if (animated_colors.background.enabled) {
+      style = style |
+              bgcolor(Color::Interpolate(animation_foreground_,  //
+                                         animated_colors.background.inactive,
+                                         animated_colors.background.active));
+    }
+    if (animated_colors.foreground.enabled) {
+      style =
+          style | color(Color::Interpolate(animation_foreground_,  //
+                                           animated_colors.foreground.inactive,
+                                           animated_colors.foreground.active));
+    }
+    return style;
+  }
+
+  void SetAnimationTarget(float target) {
+    if (animated_colors.foreground.enabled) {
+      animator_foreground_ = animation::Animator(
+          &animation_foreground_, target, animated_colors.foreground.duration,
+          animated_colors.foreground.function);
+    }
+    if (animated_colors.background.enabled) {
+      animator_background_ = animation::Animator(
+          &animation_background_, target, animated_colors.background.duration,
+          animated_colors.background.function);
+    }
+  }
+
+  void OnAnimation(animation::Params& p) override {
+    animator_background_.OnAnimation(p);
+    animator_foreground_.OnAnimation(p);
+  }
+
+  void OnClick() {
+    on_click();
+    animation_background_ = 0.5F;  // NOLINT
+    animation_foreground_ = 0.5F;  // NOLINT
+    SetAnimationTarget(1.F);       // NOLINT
+  }
+
+  bool OnEvent(Event event) override {
+    if (event.is_mouse()) {
+      return OnMouseEvent(event);
+    }
+
+    if (event == Event::Return) {
+      OnClick();
+      return true;
+    }
+    return false;
+  }
+
+  bool OnMouseEvent(Event event) {
+    mouse_hover_ =
+        box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
+
+    if (!mouse_hover_) {
+      return false;
+    }
+
+    if (event.mouse().button == Mouse::Left &&
+        event.mouse().motion == Mouse::Pressed) {
+      TakeFocus();
+      OnClick();
+      return true;
+    }
+
+    return false;
+  }
+
+  bool Focusable() const final { return true; }
+
+ private:
+  bool mouse_hover_ = false;
+  Box box_;
+  ButtonOption option_;
+  float animation_background_ = 0;
+  float animation_foreground_ = 0;
+  animation::Animator animator_background_ =
+      animation::Animator(&animation_background_);
+  animation::Animator animator_foreground_ =
+      animation::Animator(&animation_foreground_);
+};
+
 }  // namespace
+   //
+/// @brief Draw a button. Execute a function when clicked.
+/// @param option Additional optional parameters.
+/// @ingroup component
+/// @see ButtonBase
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::FitComponent();
+/// Component button = Button({
+///   .label = "Click to quit",
+///   .on_click = screen.ExitLoopClosure(),
+/// });
+/// screen.Loop(button)
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// ┌─────────────┐
+/// │Click to quit│
+/// └─────────────┘
+/// ```
+Component Button(ButtonOption option) {
+  return Make<ButtonBase>(std::move(option));
+}
 
 /// @brief Draw a button. Execute a function when clicked.
 /// @param label The label of the button.
@@ -55,135 +196,13 @@ Element DefaultTransform(EntryState params) {  // NOLINT
 /// │Click to quit│
 /// └─────────────┘
 /// ```
-// NOLINTNEXTLINE(readability-function-cognitive-complexity)
+// NOLINTNEXTLINE
 Component Button(ConstStringRef label,
                  std::function<void()> on_click,
-                 Ref<ButtonOption> option) {
-  class Impl : public ComponentBase {
-   public:
-    Impl(ConstStringRef label,
-         std::function<void()> on_click,
-         Ref<ButtonOption> option)
-        : label_(std::move(label)),
-          on_click_(std::move(on_click)),
-          option_(std::move(option)) {}
-
-    // Component implementation:
-    Element Render() override {
-      const bool active = Active();
-      const bool focused = Focused();
-      const bool focused_or_hover = focused || mouse_hover_;
-
-      float target = focused_or_hover ? 1.f : 0.f;  // NOLINT
-      if (target != animator_background_.to()) {
-        SetAnimationTarget(target);
-      }
-
-      auto focus_management = focused ? focus : active ? select : nothing;
-      const EntryState state = {
-          *label_,
-          false,
-          active,
-          focused_or_hover,
-      };
-
-      auto element =
-          (option_->transform ? option_->transform : DefaultTransform)  //
-          (state);
-      return element | AnimatedColorStyle() | focus_management | reflect(box_);
-    }
-
-    Decorator AnimatedColorStyle() {
-      Decorator style = nothing;
-      if (option_->animated_colors.background.enabled) {
-        style = style | bgcolor(Color::Interpolate(
-                            animation_foreground_,  //
-                            option_->animated_colors.background.inactive,
-                            option_->animated_colors.background.active));
-      }
-      if (option_->animated_colors.foreground.enabled) {
-        style = style | color(Color::Interpolate(
-                            animation_foreground_,  //
-                            option_->animated_colors.foreground.inactive,
-                            option_->animated_colors.foreground.active));
-      }
-      return style;
-    }
-
-    void SetAnimationTarget(float target) {
-      if (option_->animated_colors.foreground.enabled) {
-        animator_foreground_ =
-            animation::Animator(&animation_foreground_, target,
-                                option_->animated_colors.foreground.duration,
-                                option_->animated_colors.foreground.function);
-      }
-      if (option_->animated_colors.background.enabled) {
-        animator_background_ =
-            animation::Animator(&animation_background_, target,
-                                option_->animated_colors.background.duration,
-                                option_->animated_colors.background.function);
-      }
-    }
-
-    void OnAnimation(animation::Params& p) override {
-      animator_background_.OnAnimation(p);
-      animator_foreground_.OnAnimation(p);
-    }
-
-    void OnClick() {
-      on_click_();
-      animation_background_ = 0.5F;  // NOLINT
-      animation_foreground_ = 0.5F;  // NOLINT
-      SetAnimationTarget(1.F);       // NOLINT
-    }
-
-    bool OnEvent(Event event) override {
-      if (event.is_mouse()) {
-        return OnMouseEvent(event);
-      }
-
-      if (event == Event::Return) {
-        OnClick();
-        return true;
-      }
-      return false;
-    }
-
-    bool OnMouseEvent(Event event) {
-      mouse_hover_ =
-          box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
-
-      if (!mouse_hover_) {
-        return false;
-      }
-
-      if (event.mouse().button == Mouse::Left &&
-          event.mouse().motion == Mouse::Pressed) {
-        TakeFocus();
-        OnClick();
-        return true;
-      }
-
-      return false;
-    }
-
-    bool Focusable() const final { return true; }
-
-   private:
-    ConstStringRef label_;
-    std::function<void()> on_click_;
-    bool mouse_hover_ = false;
-    Box box_;
-    Ref<ButtonOption> option_;
-    float animation_background_ = 0;
-    float animation_foreground_ = 0;
-    animation::Animator animator_background_ =
-        animation::Animator(&animation_background_);
-    animation::Animator animator_foreground_ =
-        animation::Animator(&animation_foreground_);
-  };
-
-  return Make<Impl>(std::move(label), std::move(on_click), std::move(option));
+                 ButtonOption option) {
+  option.label = label;
+  option.on_click = std::move(on_click);
+  return Make<ButtonBase>(std::move(option));
 }
 
 }  // namespace ftxui
diff --git a/src/ftxui/component/checkbox.cpp b/src/ftxui/component/checkbox.cpp
index 14a05ff0830d75b5d0b3bea6dc98e232da17e9f1..e65ac6b1484037929bfd03d8a6db5460362b4c48 100644
--- a/src/ftxui/component/checkbox.cpp
+++ b/src/ftxui/component/checkbox.cpp
@@ -14,10 +14,10 @@
 namespace ftxui {
 
 namespace {
-class CheckboxBase : public ComponentBase {
+class CheckboxBase : public ComponentBase, public CheckboxOption {
  public:
-  CheckboxBase(ConstStringRef label, bool* state, Ref<CheckboxOption> option)
-      : label_(std::move(label)), state_(state), option_(std::move(option)) {}
+  explicit CheckboxBase(CheckboxOption option)
+      : CheckboxOption(std::move(option)) {}
 
  private:
   // Component implementation.
@@ -25,15 +25,14 @@ class CheckboxBase : public ComponentBase {
     const bool is_focused = Focused();
     const bool is_active = Active();
     auto focus_management = is_focused ? focus : is_active ? select : nothing;
-    auto state = EntryState{
-        *label_,
-        *state_,
+    auto entry_state = EntryState{
+        *label,
+        *checked,
         is_active,
         is_focused || hovered_,
     };
-    auto element =
-        (option_->transform ? option_->transform
-                            : CheckboxOption::Simple().transform)(state);
+    auto element = (transform ? transform : CheckboxOption::Simple().transform)(
+        entry_state);
     return element | focus_management | reflect(box_);
   }
 
@@ -48,8 +47,8 @@ class CheckboxBase : public ComponentBase {
 
     hovered_ = false;
     if (event == Event::Character(' ') || event == Event::Return) {
-      *state_ = !*state_;
-      option_->on_change();
+      *checked = !*checked;
+      on_change();
       TakeFocus();
       return true;
     }
@@ -69,8 +68,8 @@ class CheckboxBase : public ComponentBase {
 
     if (event.mouse().button == Mouse::Left &&
         event.mouse().motion == Mouse::Pressed) {
-      *state_ = !*state_;
-      option_->on_change();
+      *checked = !*checked;
+      on_change();
       return true;
     }
 
@@ -79,10 +78,7 @@ class CheckboxBase : public ComponentBase {
 
   bool Focusable() const final { return true; }
 
-  ConstStringRef label_;
-  bool* const state_;
   bool hovered_ = false;
-  Ref<CheckboxOption> option_;
   Box box_;
 };
 }  // namespace
@@ -109,10 +105,11 @@ class CheckboxBase : public ComponentBase {
 /// ```bash
 /// ☐ Make a sandwitch
 /// ```
-Component Checkbox(ConstStringRef label,
-                   bool* checked,
-                   Ref<CheckboxOption> option) {
-  return Make<CheckboxBase>(std::move(label), checked, std::move(option));
+// NOLINTNEXTLINE
+Component Checkbox(ConstStringRef label, bool* checked, CheckboxOption option) {
+  option.label = label;
+  option.checked = checked;
+  return Make<CheckboxBase>(std::move(option));
 }
 
 }  // namespace ftxui
diff --git a/src/ftxui/component/collapsible.cpp b/src/ftxui/component/collapsible.cpp
index 2adf205f1909f9986089103e97147e5db856b088..995efa2b9402d021ddf75e23ce105d985124e5d1 100644
--- a/src/ftxui/component/collapsible.cpp
+++ b/src/ftxui/component/collapsible.cpp
@@ -27,6 +27,7 @@ namespace ftxui {
 /// ▼ Show details
 /// <details component>
 ///  ```
+// NOLINTNEXTLINE
 Component Collapsible(ConstStringRef label, Component child, Ref<bool> show) {
   class Impl : public ComponentBase {
    public:
@@ -44,7 +45,7 @@ Component Collapsible(ConstStringRef label, Component child, Ref<bool> show) {
         return hbox({prefix, t});
       };
       Add(Container::Vertical({
-          Checkbox(std::move(label), show_.operator->(), opt),
+          Checkbox(label, show_.operator->(), opt),
           Maybe(std::move(child), show_.operator->()),
       }));
     }
diff --git a/src/ftxui/component/component_options.cpp b/src/ftxui/component/component_options.cpp
index aaebf19241d557ac9fc24d42315fc0998f4ef7bb..5e25ef24dd6734e2271319a2579e20f04039fccb 100644
--- a/src/ftxui/component/component_options.cpp
+++ b/src/ftxui/component/component_options.cpp
@@ -48,7 +48,7 @@ void UnderlineOption::SetAnimationFunction(
 MenuOption MenuOption::Horizontal() {
   MenuOption option;
   option.direction = Direction::Right;
-  option.entries.transform = [](const EntryState& state) {
+  option.entries_option.transform = [](const EntryState& state) {
     Element e = text(state.label);
     if (state.focused) {
       e |= inverted;
@@ -76,7 +76,7 @@ MenuOption MenuOption::HorizontalAnimated() {
 // static
 MenuOption MenuOption::Vertical() {
   MenuOption option;
-  option.entries.transform = [](const EntryState& state) {
+  option.entries_option.transform = [](const EntryState& state) {
     Element e = text((state.active ? "> " : "  ") + state.label);  // NOLINT
     if (state.focused) {
       e |= inverted;
@@ -95,7 +95,7 @@ MenuOption MenuOption::Vertical() {
 // static
 MenuOption MenuOption::VerticalAnimated() {
   auto option = MenuOption::Vertical();
-  option.entries.transform = [](const EntryState& state) {
+  option.entries_option.transform = [](const EntryState& state) {
     Element e = text(state.label);
     if (state.focused) {
       e |= inverted;
@@ -124,9 +124,9 @@ MenuOption MenuOption::Toggle() {
 ButtonOption ButtonOption::Ascii() {
   ButtonOption option;
   option.transform = [](const EntryState& s) {
-    const std::string label = s.focused ? "[" + s.label + "]"  //
-                                        : " " + s.label + " ";
-    return text(label);
+    const std::string t = s.focused ? "[" + s.label + "]"  //
+                                    : " " + s.label + " ";
+    return text(t);
   };
   return option;
 }
diff --git a/src/ftxui/component/input.cpp b/src/ftxui/component/input.cpp
index 1f49d919e77980c0a9292c06f6f3727ad051a7ad..0f32946e337803732b58edb5f34d1d89d6e292b2 100644
--- a/src/ftxui/component/input.cpp
+++ b/src/ftxui/component/input.cpp
@@ -34,17 +34,19 @@ std::vector<std::string> Split(const std::string& input) {
     output.push_back(line);
   }
   if (input.back() == '\n') {
-    output.push_back("");
+    output.emplace_back("");
   }
   return output;
 }
 
 size_t GlyphWidth(const std::string& input, size_t iter) {
   uint32_t ucs = 0;
-  if (!EatCodePoint(input, iter, &iter, &ucs))
+  if (!EatCodePoint(input, iter, &iter, &ucs)) {
     return 0;
-  if (IsFullWidth(ucs))
+  }
+  if (IsFullWidth(ucs)) {
     return 2;
+  }
   return 1;
 }
 
@@ -86,11 +88,10 @@ bool IsWordCharacter(const std::string& input, size_t iter) {
 }
 
 // An input box. The user can type text into it.
-class InputBase : public ComponentBase {
+class InputBase : public ComponentBase, public InputOption {
  public:
   // NOLINTNEXTLINE
-  InputBase(StringRef content, Ref<InputOption> option)
-      : content_(std::move(content)), option_(std::move(option)) {}
+  InputBase(InputOption option) : InputOption(std::move(option)) {}
 
  private:
   // Component implementation:
@@ -99,17 +100,17 @@ class InputBase : public ComponentBase {
     const auto focused =
         (is_focused || hovered_) ? focusCursorBarBlinking : select;
 
-    auto transform = option_->transform ? option_->transform
-                                        : InputOption::Default().transform;
+    auto transform_func =
+        transform ? transform : InputOption::Default().transform;
 
     // placeholder.
-    if (content_->empty()) {
-      auto element = text(option_->placeholder()) | xflex | frame;
+    if (content->empty()) {
+      auto element = text(placeholder()) | xflex | frame;
       if (is_focused) {
         element |= focus;
       }
 
-      return transform({
+      return transform_func({
                  std::move(element), hovered_, is_focused,
                  true  // placeholder
              }) |
@@ -117,14 +118,13 @@ class InputBase : public ComponentBase {
     }
 
     Elements elements;
-    const std::vector<std::string> lines = Split(*content_);
+    const std::vector<std::string> lines = Split(*content);
 
-    int& cursor_position = option_->cursor_position();
-    cursor_position = util::clamp(cursor_position, 0, (int)content_->size());
+    cursor_position() = util::clamp(cursor_position(), 0, (int)content->size());
 
     // Find the line and index of the cursor.
     int cursor_line = 0;
-    int cursor_char_index = cursor_position;
+    int cursor_char_index = cursor_position();
     for (const auto& line : lines) {
       if (cursor_char_index <= (int)line.size()) {
         break;
@@ -175,7 +175,7 @@ class InputBase : public ComponentBase {
     }
 
     auto element = vbox(std::move(elements)) | frame;
-    return transform({
+    return transform_func({
                std::move(element), hovered_, is_focused,
                false  // placeholder
            }) |
@@ -183,7 +183,7 @@ class InputBase : public ComponentBase {
   }
 
   Element Text(const std::string& input) {
-    if (!option_->password()) {
+    if (!password()) {
       return text(input);
     }
 
@@ -196,108 +196,101 @@ class InputBase : public ComponentBase {
   }
 
   bool HandleBackspace() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == 0) {
+    if (cursor_position() == 0) {
       return false;
     }
-    const size_t start = GlyphPrevious(content_(), cursor_position);
-    const size_t end = cursor_position;
-    content_->erase(start, end - start);
-    cursor_position = start;
+    const size_t start = GlyphPrevious(content(), cursor_position());
+    const size_t end = cursor_position();
+    content->erase(start, end - start);
+    cursor_position() = start;
     return true;
   }
 
   bool HandleDelete() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == (int)content_->size()) {
+    if (cursor_position() == (int)content->size()) {
       return false;
     }
-    const size_t start = cursor_position;
-    const size_t end = GlyphNext(content_(), cursor_position);
-    content_->erase(start, end - start);
+    const size_t start = cursor_position();
+    const size_t end = GlyphNext(content(), cursor_position());
+    content->erase(start, end - start);
     return true;
   }
 
   bool HandleArrowLeft() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == 0) {
+    if (cursor_position() == 0) {
       return false;
     }
 
-    cursor_position = GlyphPrevious(content_(), cursor_position);
+    cursor_position() = GlyphPrevious(content(), cursor_position());
     return true;
   }
 
   bool HandleArrowRight() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == (int)content_->size()) {
+    if (cursor_position() == (int)content->size()) {
       return false;
     }
 
-    cursor_position = GlyphNext(content_(), cursor_position);
+    cursor_position() = GlyphNext(content(), cursor_position());
     return true;
   }
 
   size_t CursorColumn() {
-    int& cursor_position = option_->cursor_position();
-    size_t iter = cursor_position;
+    size_t iter = cursor_position();
     int width = 0;
     while (true) {
       if (iter == 0) {
         break;
       }
-      iter = GlyphPrevious(content_(), iter);
-      if (content_()[iter] == '\n') {
+      iter = GlyphPrevious(content(), iter);
+      if (content()[iter] == '\n') {
         break;
       }
-      width += GlyphWidth(content_(), iter);
+      width += GlyphWidth(content(), iter);
     }
     return width;
   }
 
   // Move the cursor `columns` on the right, if possible.
   void MoveCursorColumn(int columns) {
-    int& cursor_position = option_->cursor_position();
     while (columns > 0) {
-      if (cursor_position == (int)content_().size() ||
-          content_()[cursor_position] == '\n') {
+      if (cursor_position() == (int)content().size() ||
+          content()[cursor_position()] == '\n') {
         return;
       }
 
-      columns -= GlyphWidth(content_(), cursor_position);
-      cursor_position = GlyphNext(content_(), cursor_position);
+      columns -= GlyphWidth(content(), cursor_position());
+      cursor_position() = GlyphNext(content(), cursor_position());
     }
   }
 
   bool HandleArrowUp() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == 0) {
+    if (cursor_position() == 0) {
       return false;
     }
 
-    size_t columns = CursorColumn();
+    const size_t columns = CursorColumn();
 
     // Move cursor at the beginning of 2 lines above.
     while (true) {
-      if (cursor_position == 0) {
+      if (cursor_position() == 0) {
         return true;
       }
-      size_t previous = GlyphPrevious(content_(), cursor_position);
-      if (content_()[previous] == '\n') {
+      const size_t previous = GlyphPrevious(content(), cursor_position());
+      if (content()[previous] == '\n') {
         break;
       }
-      cursor_position = previous;
+      cursor_position() = previous;
     }
-    cursor_position = GlyphPrevious(content_(), cursor_position);
+    cursor_position() = GlyphPrevious(content(), cursor_position());
     while (true) {
-      if (cursor_position == 0) {
+      if (cursor_position() == 0) {
         break;
       }
-      size_t previous = GlyphPrevious(content_(), cursor_position);
-      if (content_()[previous] == '\n') {
+      const size_t previous = GlyphPrevious(content(), cursor_position());
+      if (content()[previous] == '\n') {
         break;
       }
-      cursor_position = previous;
+      cursor_position() = previous;
     }
 
     MoveCursorColumn(columns);
@@ -305,61 +298,56 @@ class InputBase : public ComponentBase {
   }
 
   bool HandleArrowDown() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == (int)content_->size()) {
+    if (cursor_position() == (int)content->size()) {
       return false;
     }
 
-    size_t columns = CursorColumn();
+    const size_t columns = CursorColumn();
 
     // Move cursor at the beginning of the next line
     while (true) {
-      if (content_()[cursor_position] == '\n') {
+      if (content()[cursor_position()] == '\n') {
         break;
       }
-      cursor_position = GlyphNext(content_(), cursor_position);
-      if (cursor_position == (int)content_().size()) {
+      cursor_position() = GlyphNext(content(), cursor_position());
+      if (cursor_position() == (int)content().size()) {
         return true;
       }
     }
-    cursor_position = GlyphNext(content_(), cursor_position);
+    cursor_position() = GlyphNext(content(), cursor_position());
 
     MoveCursorColumn(columns);
     return true;
   }
 
   bool HandleHome() {
-    int& cursor_position = option_->cursor_position();
-    cursor_position = 0;
+    cursor_position() = 0;
     return true;
   }
 
   bool HandleEnd() {
-    int& cursor_position = option_->cursor_position();
-    cursor_position = content_->size();
+    cursor_position() = content->size();
     return true;
   }
 
   bool HandleReturn() {
-    if (option_->multiline()) {
+    if (multiline()) {
       HandleCharacter("\n");
     }
-    option_->on_enter();
+    on_enter();
     return true;
   }
 
   bool HandleCharacter(const std::string& character) {
-    int& cursor_position = option_->cursor_position();
-    content_->insert(cursor_position, character);
-    cursor_position += character.size();
-    option_->on_change();
+    content->insert(cursor_position(), character);
+    cursor_position() += character.size();
+    on_change();
 
     return true;
   }
 
   bool OnEvent(Event event) override {
-    int& cursor_position = option_->cursor_position();
-    cursor_position = util::clamp(cursor_position, 0, (int)content_->size());
+    cursor_position() = util::clamp(cursor_position(), 0, (int)content->size());
 
     if (event == Event::Return) {
       return HandleReturn();
@@ -405,50 +393,48 @@ class InputBase : public ComponentBase {
   }
 
   bool HandleLeftCtrl() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == 0) {
+    if (cursor_position() == 0) {
       return false;
     }
 
     // Move left, as long as left it not a word.
-    while (cursor_position) {
-      size_t previous = GlyphPrevious(content_(), cursor_position);
-      if (IsWordCharacter(content_(), previous)) {
+    while (cursor_position()) {
+      const size_t previous = GlyphPrevious(content(), cursor_position());
+      if (IsWordCharacter(content(), previous)) {
         break;
       }
-      cursor_position = previous;
+      cursor_position() = previous;
     }
     // Move left, as long as left is a word character:
-    while (cursor_position) {
-      size_t previous = GlyphPrevious(content_(), cursor_position);
-      if (!IsWordCharacter(content_(), previous)) {
+    while (cursor_position()) {
+      const size_t previous = GlyphPrevious(content(), cursor_position());
+      if (!IsWordCharacter(content(), previous)) {
         break;
       }
-      cursor_position = previous;
+      cursor_position() = previous;
     }
     return true;
   }
 
   bool HandleRightCtrl() {
-    int& cursor_position = option_->cursor_position();
-    if (cursor_position == (int)content_().size()) {
+    if (cursor_position() == (int)content().size()) {
       return false;
     }
 
     // Move right, until entering a word.
-    while (cursor_position < (int)content_().size()) {
-      cursor_position = GlyphNext(content_(), cursor_position);
-      if (IsWordCharacter(content_(), cursor_position)) {
+    while (cursor_position() < (int)content().size()) {
+      cursor_position() = GlyphNext(content(), cursor_position());
+      if (IsWordCharacter(content(), cursor_position())) {
         break;
       }
     }
     // Move right, as long as right is a word character:
-    while (cursor_position < (int)content_().size()) {
-      size_t next = GlyphNext(content_(), cursor_position);
-      if (!IsWordCharacter(content_(), cursor_position)) {
+    while (cursor_position() < (int)content().size()) {
+      const size_t next = GlyphNext(content(), cursor_position());
+      if (!IsWordCharacter(content(), cursor_position())) {
         break;
       }
-      cursor_position = next;
+      cursor_position() = next;
     }
 
     return true;
@@ -469,16 +455,15 @@ class InputBase : public ComponentBase {
 
     TakeFocus();
 
-    if (content_->empty()) {
-      option_->cursor_position() = 0;
+    if (content->empty()) {
+      cursor_position() = 0;
       return true;
     }
 
     // Find the line and index of the cursor.
-    std::vector<std::string> lines = Split(*content_);
-    int& cursor_position = option_->cursor_position();
+    std::vector<std::string> lines = Split(*content);
     int cursor_line = 0;
-    int cursor_char_index = cursor_position;
+    int cursor_char_index = cursor_position();
     for (const auto& line : lines) {
       if (cursor_char_index <= (int)line.size()) {
         break;
@@ -487,7 +472,7 @@ class InputBase : public ComponentBase {
       cursor_char_index -= line.size() + 1;
       cursor_line++;
     }
-    int cursor_column =
+    const int cursor_column =
         string_width(lines[cursor_line].substr(0, cursor_char_index));
 
     int new_cursor_column = cursor_column + event.mouse().x - cursor_box_.x_min;
@@ -496,7 +481,7 @@ class InputBase : public ComponentBase {
     // Fix the new cursor position:
     new_cursor_line = std::max(std::min(new_cursor_line, (int)lines.size()), 0);
 
-    std::string empty_string;
+    const std::string empty_string;
     const std::string& line = new_cursor_line < (int)lines.size()
                                   ? lines[new_cursor_line]
                                   : empty_string;
@@ -508,31 +493,56 @@ class InputBase : public ComponentBase {
     }
 
     // Convert back the new_cursor_{line,column} toward cursor_position:
-    cursor_position = 0;
+    cursor_position() = 0;
     for (int i = 0; i < new_cursor_line; ++i) {
-      cursor_position += lines[i].size() + 1;
+      cursor_position() += lines[i].size() + 1;
     }
     while (new_cursor_column > 0) {
-      new_cursor_column -= GlyphWidth(content_(), cursor_position);
-      cursor_position = GlyphNext(content_(), cursor_position);
+      new_cursor_column -= GlyphWidth(content(), cursor_position());
+      cursor_position() = GlyphNext(content(), cursor_position());
     }
 
-    option_->on_change();
+    on_change();
     return true;
   }
 
   bool Focusable() const final { return true; }
 
   bool hovered_ = false;
-  StringRef content_;
 
   Box box_;
   Box cursor_box_;
-  Ref<InputOption> option_;
 };
 
 }  // namespace
 
+/// @brief An input box for editing text.
+/// @param option Additional optional parameters.
+/// @ingroup component
+/// @see InputBase
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::FitComponent();
+/// std::string content= "";
+/// std::string placeholder = "placeholder";
+/// Component input = Input({
+///   .content = &content,
+///   .placeholder = &placeholder,
+/// })
+/// screen.Loop(input);
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// placeholder
+/// ```
+Component Input(InputOption option) {
+  return Make<InputBase>(std::move(option));
+}
+
 /// @brief An input box for editing text.
 /// @param content The editable content.
 /// @param option Additional optional parameters.
@@ -545,7 +555,10 @@ class InputBase : public ComponentBase {
 /// auto screen = ScreenInteractive::FitComponent();
 /// std::string content= "";
 /// std::string placeholder = "placeholder";
-/// Component input = Input(&content, &placeholder);
+/// Component input = Input(content, {
+///   .placeholder = &placeholder,
+///   .password = true,
+/// })
 /// screen.Loop(input);
 /// ```
 ///
@@ -554,15 +567,36 @@ class InputBase : public ComponentBase {
 /// ```bash
 /// placeholder
 /// ```
-Component Input(StringRef content, Ref<InputOption> option) {
-  return Make<InputBase>(std::move(content), std::move(option));
+Component Input(StringRef content, InputOption option) {
+  option.content = content;
+  return Make<InputBase>(std::move(option));
 }
 
-Component Input(StringRef content,
-                StringRef placeholder,
-                Ref<InputOption> option) {
-  option->placeholder = placeholder;
-  return Make<InputBase>(std::move(content), std::move(option));
+/// @brief An input box for editing text.
+/// @param content The editable content.
+/// @param option Additional optional parameters.
+/// @ingroup component
+/// @see InputBase
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::FitComponent();
+/// std::string content= "";
+/// std::string placeholder = "placeholder";
+/// Component input = Input(content, placeholder);
+/// screen.Loop(input);
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// placeholder
+/// ```
+Component Input(StringRef content, StringRef placeholder, InputOption option) {
+  option.content = content;
+  option.placeholder = placeholder;
+  return Make<InputBase>(std::move(option));
 }
 
 }  // namespace ftxui
diff --git a/src/ftxui/component/input_test.cpp b/src/ftxui/component/input_test.cpp
index 16440590f3d14b1f958a52f1ca8cd28985595f35..175ff751d91c2209b62a942effb5d58e2ce145fd 100644
--- a/src/ftxui/component/input_test.cpp
+++ b/src/ftxui/component/input_test.cpp
@@ -16,32 +16,36 @@ namespace ftxui {
 
 TEST(InputTest, Init) {
   std::string content;
+  int cursor_position = 0;
   auto option = InputOption();
-  Component input = Input(&content, &option);
-  EXPECT_EQ(option.cursor_position(), 0);
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
+  EXPECT_EQ(cursor_position, 0);
 }
 
 TEST(InputTest, Type) {
   std::string content;
-  std::string placeholder;
-  auto option = InputOption();
-  Component input = Input(&content, &option);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
 
   input->OnEvent(Event::Character("a"));
   EXPECT_EQ(content, "a");
-  EXPECT_EQ(option.cursor_position(), 1);
+  EXPECT_EQ(cursor_position, 1);
 
   input->OnEvent(Event::Character('b'));
   EXPECT_EQ(content, "ab");
-  EXPECT_EQ(option.cursor_position(), 2);
+  EXPECT_EQ(cursor_position, 2);
 
   input->OnEvent(Event::Return);
   EXPECT_EQ(content, "ab\n");
-  EXPECT_EQ(option.cursor_position(), 3);
+  EXPECT_EQ(cursor_position, 3);
 
   input->OnEvent(Event::Character('c'));
   EXPECT_EQ(content, "ab\nc");
-  EXPECT_EQ(option.cursor_position(), 4);
+  EXPECT_EQ(cursor_position, 4);
 
   auto document = input->Render();
 
@@ -55,57 +59,59 @@ TEST(InputTest, Type) {
 
 TEST(InputTest, ArrowLeftRight) {
   std::string content = "abc测测a测\na测\n";
-  auto option = InputOption();
-  auto input = Input(&content, &option);
-  EXPECT_EQ(option.cursor_position(), 0);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowLeft));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 1);
+  EXPECT_EQ(cursor_position, 1);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 1);
+  EXPECT_EQ(cursor_position, 1);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 2);
+  EXPECT_EQ(cursor_position, 2);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 3);
+  EXPECT_EQ(cursor_position, 3);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 6);
+  EXPECT_EQ(cursor_position, 6);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 9);
+  EXPECT_EQ(cursor_position, 9);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 10);
+  EXPECT_EQ(cursor_position, 10);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 13);
+  EXPECT_EQ(cursor_position, 13);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 14);
+  EXPECT_EQ(cursor_position, 14);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 15);
+  EXPECT_EQ(cursor_position, 15);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 18);
+  EXPECT_EQ(cursor_position, 18);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 19);
+  EXPECT_EQ(cursor_position, 19);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 19);
+  EXPECT_EQ(cursor_position, 19);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
-  EXPECT_EQ(option.cursor_position(), 18);
+  EXPECT_EQ(cursor_position, 18);
 }
 
 TEST(InputTest, ArrowUpDown) {
@@ -117,70 +123,75 @@ TEST(InputTest, ArrowUpDown) {
       "00\n"
       "0\n"
       "";
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 4);
+  EXPECT_EQ(cursor_position, 4);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 11);
+  EXPECT_EQ(cursor_position, 11);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 21);
+  EXPECT_EQ(cursor_position, 21);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 29);
+  EXPECT_EQ(cursor_position, 29);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 36);
+  EXPECT_EQ(cursor_position, 36);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 40);
+  EXPECT_EQ(cursor_position, 40);
   EXPECT_FALSE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 40);
+  EXPECT_EQ(cursor_position, 40);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 36);
+  EXPECT_EQ(cursor_position, 36);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 29);
+  EXPECT_EQ(cursor_position, 29);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 21);
+  EXPECT_EQ(cursor_position, 21);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 11);
+  EXPECT_EQ(cursor_position, 11);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 4);
+  EXPECT_EQ(cursor_position, 4);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
   EXPECT_FALSE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
-  EXPECT_EQ(option.cursor_position(), 3);
+  EXPECT_EQ(cursor_position, 3);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 7);
+  EXPECT_EQ(cursor_position, 7);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 14);
+  EXPECT_EQ(cursor_position, 14);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 24);
+  EXPECT_EQ(cursor_position, 24);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 32);
+  EXPECT_EQ(cursor_position, 32);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 39);
+  EXPECT_EQ(cursor_position, 39);
   EXPECT_TRUE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 40);
+  EXPECT_EQ(cursor_position, 40);
   EXPECT_FALSE(input->OnEvent(Event::ArrowDown));
-  EXPECT_EQ(option.cursor_position(), 40);
+  EXPECT_EQ(cursor_position, 40);
 
-  option.cursor_position() = 39;
+  cursor_position = 39;
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 32);
+  EXPECT_EQ(cursor_position, 32);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 24);
+  EXPECT_EQ(cursor_position, 24);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 14);
+  EXPECT_EQ(cursor_position, 14);
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
-  EXPECT_EQ(option.cursor_position(), 7);
+  EXPECT_EQ(cursor_position, 7);
 }
 
 TEST(InputTest, Insert) {
   std::string content;
-  Component input = Input(&content);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
 
   EXPECT_TRUE(input->OnEvent(Event::Character('a')));
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
@@ -213,8 +224,10 @@ TEST(InputTest, Insert) {
 
 TEST(InputTest, Home) {
   std::string content;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
 
   EXPECT_TRUE(input->OnEvent(Event::Character('a')));
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
@@ -224,21 +237,22 @@ TEST(InputTest, Home) {
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
   EXPECT_TRUE(input->OnEvent(Event::Character('c')));
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 
   EXPECT_TRUE(input->OnEvent(Event::Home));
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 
   EXPECT_TRUE(input->OnEvent(Event::Character('-')));
-  EXPECT_EQ(option.cursor_position(), 1u);
+  EXPECT_EQ(cursor_position, 1u);
   EXPECT_EQ(content, "-abc\n测bc");
 }
 
 TEST(InputTest, End) {
   std::string content;
-  std::string placeholder;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  Component input = Input(&content, {
+                                        .cursor_position = &cursor_position,
+                                    });
 
   EXPECT_TRUE(input->OnEvent(Event::Character('a')));
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
@@ -250,17 +264,18 @@ TEST(InputTest, End) {
   EXPECT_TRUE(input->OnEvent(Event::ArrowUp));
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 2u);
+  EXPECT_EQ(cursor_position, 2u);
 
   input->OnEvent(Event::End);
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 }
 
 TEST(InputTest, Delete) {
   std::string content;
-  std::string placeholder;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  auto input = Input(&content, {
+                                   .cursor_position = &cursor_position,
+                               });
 
   EXPECT_TRUE(input->OnEvent(Event::Character('a')));
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
@@ -271,38 +286,38 @@ TEST(InputTest, Delete) {
   EXPECT_TRUE(input->OnEvent(Event::Character('c')));
 
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 
   EXPECT_FALSE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 8u);
+  EXPECT_EQ(cursor_position, 8u);
 
   EXPECT_TRUE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abc\n测b");
-  EXPECT_EQ(option.cursor_position(), 8u);
+  EXPECT_EQ(cursor_position, 8u);
 
   EXPECT_FALSE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abc\n测b");
-  EXPECT_EQ(option.cursor_position(), 8u);
+  EXPECT_EQ(cursor_position, 8u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_TRUE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abc\nb");
-  EXPECT_EQ(option.cursor_position(), 4u);
+  EXPECT_EQ(cursor_position, 4u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_TRUE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abcb");
-  EXPECT_EQ(option.cursor_position(), 3u);
+  EXPECT_EQ(cursor_position, 3u);
 
   EXPECT_TRUE(input->OnEvent(Event::Delete));
   EXPECT_EQ(content, "abc");
-  EXPECT_EQ(option.cursor_position(), 3u);
+  EXPECT_EQ(cursor_position, 3u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
@@ -318,9 +333,10 @@ TEST(InputTest, Delete) {
 
 TEST(InputTest, Backspace) {
   std::string content;
-  std::string placeholder;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  auto input = Input(&content, {
+                                   .cursor_position = &cursor_position,
+                               });
 
   EXPECT_TRUE(input->OnEvent(Event::Character('a')));
   EXPECT_TRUE(input->OnEvent(Event::Character('b')));
@@ -331,45 +347,45 @@ TEST(InputTest, Backspace) {
   EXPECT_TRUE(input->OnEvent(Event::Character('c')));
 
   EXPECT_EQ(content, "abc\n测bc");
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "abc\n测b");
-  EXPECT_EQ(option.cursor_position(), 8u);
+  EXPECT_EQ(cursor_position, 8u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeft));
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "abc\nb");
-  EXPECT_EQ(option.cursor_position(), 4u);
+  EXPECT_EQ(cursor_position, 4u);
 
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "abcb");
-  EXPECT_EQ(option.cursor_position(), 3u);
+  EXPECT_EQ(cursor_position, 3u);
 
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "abb");
-  EXPECT_EQ(option.cursor_position(), 2u);
+  EXPECT_EQ(cursor_position, 2u);
 
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "ab");
-  EXPECT_EQ(option.cursor_position(), 1u);
+  EXPECT_EQ(cursor_position, 1u);
 
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "b");
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 
   EXPECT_FALSE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "b");
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRight));
   EXPECT_TRUE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "");
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 
   EXPECT_FALSE(input->OnEvent(Event::Backspace));
   EXPECT_EQ(content, "");
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 }
 
 TEST(InputTest, CtrlArrow) {
@@ -377,192 +393,193 @@ TEST(InputTest, CtrlArrow) {
       "word word 测ord wo测d word\n"
       "coucou    coucou coucou\n"
       "coucou coucou coucou\n";
-  std::string placeholder;
-  auto option = InputOption();
-  option.cursor_position = 1000;
-  auto input = Input(&content, &option);
+  int cursor_position = 1000;
+  auto input = Input(&content, {
+                                   .cursor_position = &cursor_position,
+                               });
 
   // Use CTRL+Left several time
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 67);
+  EXPECT_EQ(cursor_position, 67);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 60);
+  EXPECT_EQ(cursor_position, 60);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 53);
+  EXPECT_EQ(cursor_position, 53);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 46);
+  EXPECT_EQ(cursor_position, 46);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 39);
+  EXPECT_EQ(cursor_position, 39);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 29);
+  EXPECT_EQ(cursor_position, 29);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 24);
+  EXPECT_EQ(cursor_position, 24);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 17);
+  EXPECT_EQ(cursor_position, 17);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 10);
+  EXPECT_EQ(cursor_position, 10);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 5);
+  EXPECT_EQ(cursor_position, 5);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 4);
+  EXPECT_EQ(cursor_position, 4);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 9);
+  EXPECT_EQ(cursor_position, 9);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 16);
+  EXPECT_EQ(cursor_position, 16);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 23);
+  EXPECT_EQ(cursor_position, 23);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 28);
+  EXPECT_EQ(cursor_position, 28);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 35);
+  EXPECT_EQ(cursor_position, 35);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 45);
+  EXPECT_EQ(cursor_position, 45);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 52);
+  EXPECT_EQ(cursor_position, 52);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 59);
+  EXPECT_EQ(cursor_position, 59);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 66);
+  EXPECT_EQ(cursor_position, 66);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 73);
+  EXPECT_EQ(cursor_position, 73);
 }
 
 TEST(InputTest, CtrlArrowLeft2) {
   std::string content = "   word  word  测ord  wo测d  word   ";
-  auto option = InputOption();
-  option.cursor_position = 33;
-  auto input = Input(&content, &option);
+  int cursor_position = 33;
+  auto input = Input(&content, {
+                                   .cursor_position = &cursor_position,
+                               });
 
   // Use CTRL+Left several time
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 31);
+  EXPECT_EQ(cursor_position, 31);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 23);
+  EXPECT_EQ(cursor_position, 23);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 15);
+  EXPECT_EQ(cursor_position, 15);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 9);
+  EXPECT_EQ(cursor_position, 9);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 3);
+  EXPECT_EQ(cursor_position, 3);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowLeftCtrl));
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 }
 
 TEST(InputTest, CtrlArrowRight) {
   std::string content =
       "word word 测ord wo测d word\n"
       "coucou dfqdsf jmlkjm";
-
-  auto option = InputOption();
-  option.cursor_position = 2;
-  auto input = Input(&content, &option);
+  int cursor_position = 2;
+  auto input = Input(&content, {.cursor_position = &cursor_position});
 
   // Use CTRL+Left several time
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 4);
+  EXPECT_EQ(cursor_position, 4);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 9);
+  EXPECT_EQ(cursor_position, 9);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 16);
+  EXPECT_EQ(cursor_position, 16);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 23);
+  EXPECT_EQ(cursor_position, 23);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 28);
+  EXPECT_EQ(cursor_position, 28);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 35);
+  EXPECT_EQ(cursor_position, 35);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 42);
+  EXPECT_EQ(cursor_position, 42);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 49);
+  EXPECT_EQ(cursor_position, 49);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 49);
+  EXPECT_EQ(cursor_position, 49);
 }
 
 TEST(InputTest, CtrlArrowRight2) {
   std::string content = "   word  word  测ord  wo测d  word   ";
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  auto input = Input(&content, {.cursor_position = &cursor_position});
 
   // Use CTRL+Left several time
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 7);
+  EXPECT_EQ(cursor_position, 7);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 13);
+  EXPECT_EQ(cursor_position, 13);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 21);
+  EXPECT_EQ(cursor_position, 21);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 29);
+  EXPECT_EQ(cursor_position, 29);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 35);
+  EXPECT_EQ(cursor_position, 35);
 
   EXPECT_TRUE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 38);
+  EXPECT_EQ(cursor_position, 38);
 
   EXPECT_FALSE(input->OnEvent(Event::ArrowRightCtrl));
-  EXPECT_EQ(option.cursor_position(), 38);
+  EXPECT_EQ(cursor_position, 38);
 }
 
 TEST(InputTest, TypePassword) {
   std::string content;
   std::string placeholder;
-  auto option = InputOption();
-  option.cursor_position = 0;
-  option.password = true;
-  Component input = Input(&content, &placeholder, &option);
+  int cursor_position = 0;
+  Component input = Input(&content, &placeholder,
+                          {
+                              .password = true,
+                              .cursor_position = &cursor_position,
+                          });
 
   input->OnEvent(Event::Character('a'));
   EXPECT_EQ(content, "a");
-  EXPECT_EQ(option.cursor_position(), 1u);
+  EXPECT_EQ(cursor_position, 1u);
 
   input->OnEvent(Event::Character('b'));
   EXPECT_EQ(content, "ab");
-  EXPECT_EQ(option.cursor_position(), 2u);
+  EXPECT_EQ(cursor_position, 2u);
 
   auto document = input->Render();
   auto screen = Screen::Create(Dimension::Fit(document));
@@ -573,8 +590,8 @@ TEST(InputTest, TypePassword) {
 
 TEST(InputTest, MouseClick) {
   std::string content;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  auto input = Input(&content, {.cursor_position = &cursor_position});
 
   input->OnEvent(Event::Character("a"));
   input->OnEvent(Event::Character("b"));
@@ -588,7 +605,7 @@ TEST(InputTest, MouseClick) {
   input->OnEvent(Event::Return);
 
   EXPECT_EQ(content, "abcd\nabcd\n");
-  EXPECT_EQ(option.cursor_position(), 10u);
+  EXPECT_EQ(cursor_position, 10u);
 
   auto render = [&] {
     auto document = input->Render();
@@ -596,7 +613,7 @@ TEST(InputTest, MouseClick) {
     Render(screen, document);
   };
   render();
-  EXPECT_EQ(option.cursor_position(), 10u);
+  EXPECT_EQ(cursor_position, 10u);
 
   Mouse mouse;
   mouse.button = Mouse::Button::Left;
@@ -609,67 +626,67 @@ TEST(InputTest, MouseClick) {
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 0u);
+  EXPECT_EQ(cursor_position, 0u);
 
   mouse.x = 2;
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 2u);
+  EXPECT_EQ(cursor_position, 2u);
 
   mouse.x = 2;
   mouse.y = 0;
   EXPECT_FALSE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 2u);
+  EXPECT_EQ(cursor_position, 2u);
 
   mouse.x = 1;
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 1u);
+  EXPECT_EQ(cursor_position, 1u);
 
   mouse.x = 3;
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 3u);
+  EXPECT_EQ(cursor_position, 3u);
 
   mouse.x = 4;
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 4u);
+  EXPECT_EQ(cursor_position, 4u);
 
   mouse.x = 5;
   mouse.y = 0;
   EXPECT_FALSE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 4u);
+  EXPECT_EQ(cursor_position, 4u);
 
   mouse.x = 5;
   mouse.y = 1;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 9u);
+  EXPECT_EQ(cursor_position, 9u);
 
   mouse.x = 1;
   mouse.y = 1;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 6u);
+  EXPECT_EQ(cursor_position, 6u);
 
   mouse.x = 4;
   mouse.y = 2;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 10u);
+  EXPECT_EQ(cursor_position, 10u);
 }
 
 TEST(InputTest, MouseClickComplex) {
   std::string content;
-  auto option = InputOption();
-  auto input = Input(&content, &option);
+  int cursor_position = 0;
+  auto input = Input(&content, {.cursor_position = &cursor_position});
 
   input->OnEvent(Event::Character("测"));
   input->OnEvent(Event::Character("试"));
@@ -681,7 +698,7 @@ TEST(InputTest, MouseClickComplex) {
   input->OnEvent(Event::Character("a⃒"));
   input->OnEvent(Event::Character("ā"));
 
-  EXPECT_EQ(option.cursor_position(), 27u);
+  EXPECT_EQ(cursor_position, 27u);
 
   auto render = [&] {
     auto document = input->Render();
@@ -701,25 +718,25 @@ TEST(InputTest, MouseClickComplex) {
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 0);
+  EXPECT_EQ(cursor_position, 0);
 
   mouse.x = 0;
   mouse.y = 1;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 14);
+  EXPECT_EQ(cursor_position, 14);
 
   mouse.x = 1;
   mouse.y = 0;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 3);
+  EXPECT_EQ(cursor_position, 3);
 
   mouse.x = 1;
   mouse.y = 1;
   EXPECT_TRUE(input->OnEvent(Event::Mouse("", mouse)));
   render();
-  EXPECT_EQ(option.cursor_position(), 17);
+  EXPECT_EQ(cursor_position, 17);
 }
 
 TEST(InputTest, OnEnter) {
@@ -727,7 +744,7 @@ TEST(InputTest, OnEnter) {
   auto option = InputOption();
   bool on_enter_called = false;
   option.on_enter = [&] { on_enter_called = true; };
-  Component input = Input(&content, &option);
+  Component input = Input(&content, option);
 
   EXPECT_FALSE(on_enter_called);
   EXPECT_TRUE(input->OnEvent(Event::Return));
diff --git a/src/ftxui/component/menu.cpp b/src/ftxui/component/menu.cpp
index 1b693b42e2878004a5029296ddd81c73ccfec72d..f182ea324f31dd00424f62e2af1615d7ace133c8 100644
--- a/src/ftxui/component/menu.cpp
+++ b/src/ftxui/component/menu.cpp
@@ -65,30 +65,29 @@ bool IsHorizontal(Direction direction) {
 
 /// @brief A list of items. The user can navigate through them.
 /// @ingroup component
-class MenuBase : public ComponentBase {
+class MenuBase : public ComponentBase, public MenuOption {
  public:
-  MenuBase(ConstStringListRef entries, int* selected, Ref<MenuOption> option)
-      : entries_(entries), selected_(selected), option_(std::move(option)) {}
+  explicit MenuBase(MenuOption option) : MenuOption(std::move(option)) {}
 
-  bool IsHorizontal() { return ftxui::IsHorizontal(option_->direction); }
+  bool IsHorizontal() { return ftxui::IsHorizontal(direction); }
   void OnChange() {
-    if (option_->on_change) {
-      option_->on_change();
+    if (on_change) {
+      on_change();
     }
   }
 
   void OnEnter() {
-    if (option_->on_enter) {
-      option_->on_enter();
+    if (on_enter) {
+      on_enter();
     }
   }
 
   void Clamp() {
-    if (*selected_ != selected_previous_) {
+    if (selected() != selected_previous_) {
       SelectedTakeFocus();
     }
     boxes_.resize(size());
-    *selected_ = util::clamp(*selected_, 0, size() - 1);
+    selected() = util::clamp(selected(), 0, size() - 1);
     selected_previous_ = util::clamp(selected_previous_, 0, size() - 1);
     selected_focus_ = util::clamp(selected_focus_, 0, size() - 1);
     focused_entry() = util::clamp(focused_entry(), 0, size() - 1);
@@ -111,19 +110,19 @@ class MenuBase : public ComponentBase {
 
     Elements elements;
     const bool is_menu_focused = Focused();
-    if (option_->elements_prefix) {
-      elements.push_back(option_->elements_prefix());
+    if (elements_prefix) {
+      elements.push_back(elements_prefix());
     }
     elements.reserve(size());
     for (int i = 0; i < size(); ++i) {
-      if (i != 0 && option_->elements_infix) {
-        elements.push_back(option_->elements_infix());
+      if (i != 0 && elements_infix) {
+        elements.push_back(elements_infix());
       }
       const bool is_focused = (focused_entry() == i) && is_menu_focused;
-      const bool is_selected = (*selected_ == i);
+      const bool is_selected = (selected() == i);
 
       const EntryState state = {
-          entries_[i],
+          entries[i],
           false,
           is_selected,
           is_focused,
@@ -133,24 +132,24 @@ class MenuBase : public ComponentBase {
           is_menu_focused && (selected_focus_ == i) ? focus : nothing;
 
       const Element element =
-          (option_->entries.transform ? option_->entries.transform
-                                      : DefaultOptionTransform)  //
+          (entries_option.transform ? entries_option.transform
+                                    : DefaultOptionTransform)  //
           (state);
       elements.push_back(element | AnimatedColorStyle(i) | reflect(boxes_[i]) |
                          focus_management);
     }
-    if (option_->elements_postfix) {
-      elements.push_back(option_->elements_postfix());
+    if (elements_postfix) {
+      elements.push_back(elements_postfix());
     }
 
-    if (IsInverted(option_->direction)) {
+    if (IsInverted(direction)) {
       std::reverse(elements.begin(), elements.end());
     }
 
     const Element bar =
         IsHorizontal() ? hbox(std::move(elements)) : vbox(std::move(elements));
 
-    if (!option_->underline.enabled) {
+    if (!underline.enabled) {
       return bar | reflect(box_);
     }
 
@@ -158,15 +157,15 @@ class MenuBase : public ComponentBase {
       return vbox({
                  bar | xflex,
                  separatorHSelector(first_, second_,  //
-                                    option_->underline.color_active,
-                                    option_->underline.color_inactive),
+                                    underline.color_active,
+                                    underline.color_inactive),
              }) |
              reflect(box_);
     } else {
       return hbox({
                  separatorVSelector(first_, second_,  //
-                                    option_->underline.color_active,
-                                    option_->underline.color_inactive),
+                                    underline.color_active,
+                                    underline.color_inactive),
                  bar | yflex,
              }) |
              reflect(box_);
@@ -174,17 +173,17 @@ class MenuBase : public ComponentBase {
   }
 
   void SelectedTakeFocus() {
-    selected_previous_ = *selected_;
-    selected_focus_ = *selected_;
+    selected_previous_ = selected();
+    selected_focus_ = selected();
   }
 
   void OnUp() {
-    switch (option_->direction) {
+    switch (direction) {
       case Direction::Up:
-        (*selected_)++;
+        selected()++;
         break;
       case Direction::Down:
-        (*selected_)--;
+        selected()--;
         break;
       case Direction::Left:
       case Direction::Right:
@@ -193,12 +192,12 @@ class MenuBase : public ComponentBase {
   }
 
   void OnDown() {
-    switch (option_->direction) {
+    switch (direction) {
       case Direction::Up:
-        (*selected_)--;
+        selected()--;
         break;
       case Direction::Down:
-        (*selected_)++;
+        selected()++;
         break;
       case Direction::Left:
       case Direction::Right:
@@ -207,12 +206,12 @@ class MenuBase : public ComponentBase {
   }
 
   void OnLeft() {
-    switch (option_->direction) {
+    switch (direction) {
       case Direction::Left:
-        (*selected_)++;
+        selected()++;
         break;
       case Direction::Right:
-        (*selected_)--;
+        selected()--;
         break;
       case Direction::Down:
       case Direction::Up:
@@ -221,12 +220,12 @@ class MenuBase : public ComponentBase {
   }
 
   void OnRight() {
-    switch (option_->direction) {
+    switch (direction) {
       case Direction::Left:
-        (*selected_)--;
+        selected()--;
         break;
       case Direction::Right:
-        (*selected_)++;
+        selected()++;
         break;
       case Direction::Down:
       case Direction::Up:
@@ -246,7 +245,7 @@ class MenuBase : public ComponentBase {
     }
 
     if (Focused()) {
-      const int old_selected = *selected_;
+      const int old_selected = selected();
       if (event == Event::ArrowUp || event == Event::Character('k')) {
         OnUp();
       }
@@ -260,28 +259,28 @@ class MenuBase : public ComponentBase {
         OnRight();
       }
       if (event == Event::PageUp) {
-        (*selected_) -= box_.y_max - box_.y_min;
+        selected() -= box_.y_max - box_.y_min;
       }
       if (event == Event::PageDown) {
-        (*selected_) += box_.y_max - box_.y_min;
+        selected() += box_.y_max - box_.y_min;
       }
       if (event == Event::Home) {
-        (*selected_) = 0;
+        selected() = 0;
       }
       if (event == Event::End) {
-        (*selected_) = size() - 1;
+        selected() = size() - 1;
       }
       if (event == Event::Tab && size()) {
-        *selected_ = (*selected_ + 1) % size();
+        selected() = (selected() + 1) % size();
       }
       if (event == Event::TabReverse && size()) {
-        *selected_ = (*selected_ + size() - 1) % size();
+        selected() = (selected() + size() - 1) % size();
       }
 
-      *selected_ = util::clamp(*selected_, 0, size() - 1);
+      selected() = util::clamp(selected(), 0, size() - 1);
 
-      if (*selected_ != old_selected) {
-        focused_entry() = *selected_;
+      if (selected() != old_selected) {
+        focused_entry() = selected();
         SelectedTakeFocus();
         OnChange();
         return true;
@@ -318,9 +317,9 @@ class MenuBase : public ComponentBase {
       focused_entry() = i;
       if (event.mouse().button == Mouse::Left &&
           event.mouse().motion == Mouse::Released) {
-        if (*selected_ != i) {
-          *selected_ = i;
-          selected_previous_ = *selected_;
+        if (selected() != i) {
+          selected() = i;
+          selected_previous_ = selected();
           OnChange();
         }
         return true;
@@ -333,18 +332,18 @@ class MenuBase : public ComponentBase {
     if (!box_.Contain(event.mouse().x, event.mouse().y)) {
       return false;
     }
-    const int old_selected = *selected_;
+    const int old_selected = selected();
 
     if (event.mouse().button == Mouse::WheelUp) {
-      (*selected_)--;
+      selected()--;
     }
     if (event.mouse().button == Mouse::WheelDown) {
-      (*selected_)++;
+      selected()++;
     }
 
-    *selected_ = util::clamp(*selected_, 0, size() - 1);
+    selected() = util::clamp(selected(), 0, size() - 1);
 
-    if (*selected_ != old_selected) {
+    if (selected() != old_selected) {
       SelectedTakeFocus();
       OnChange();
     }
@@ -381,41 +380,41 @@ class MenuBase : public ComponentBase {
     const bool is_menu_focused = Focused();
     for (int i = 0; i < size(); ++i) {
       const bool is_focused = (focused_entry() == i) && is_menu_focused;
-      const bool is_selected = (*selected_ == i);
+      const bool is_selected = (selected() == i);
       float target = is_selected ? 1.F : is_focused ? 0.5F : 0.F;  // NOLINT
       if (animator_background_[i].to() != target) {
         animator_background_[i] = animation::Animator(
             &animation_background_[i], target,
-            option_->entries.animated_colors.background.duration,
-            option_->entries.animated_colors.background.function);
+            entries_option.animated_colors.background.duration,
+            entries_option.animated_colors.background.function);
         animator_foreground_[i] = animation::Animator(
             &animation_foreground_[i], target,
-            option_->entries.animated_colors.foreground.duration,
-            option_->entries.animated_colors.foreground.function);
+            entries_option.animated_colors.foreground.duration,
+            entries_option.animated_colors.foreground.function);
       }
     }
   }
 
   Decorator AnimatedColorStyle(int i) {
     Decorator style = nothing;
-    if (option_->entries.animated_colors.foreground.enabled) {
+    if (entries_option.animated_colors.foreground.enabled) {
       style = style | color(Color::Interpolate(
                           animation_foreground_[i],
-                          option_->entries.animated_colors.foreground.inactive,
-                          option_->entries.animated_colors.foreground.active));
+                          entries_option.animated_colors.foreground.inactive,
+                          entries_option.animated_colors.foreground.active));
     }
 
-    if (option_->entries.animated_colors.background.enabled) {
+    if (entries_option.animated_colors.background.enabled) {
       style = style | bgcolor(Color::Interpolate(
                           animation_background_[i],
-                          option_->entries.animated_colors.background.inactive,
-                          option_->entries.animated_colors.background.active));
+                          entries_option.animated_colors.background.inactive,
+                          entries_option.animated_colors.background.active));
     }
     return style;
   }
 
   void UpdateUnderlineTarget() {
-    if (!option_->underline.enabled) {
+    if (!underline.enabled) {
       return;
     }
 
@@ -426,66 +425,93 @@ class MenuBase : public ComponentBase {
 
     if (FirstTarget() >= animator_first_.to()) {
       animator_first_ = animation::Animator(
-          &first_, FirstTarget(), option_->underline.follower_duration,
-          option_->underline.follower_function,
-          option_->underline.follower_delay);
+          &first_, FirstTarget(), underline.follower_duration,
+          underline.follower_function, underline.follower_delay);
 
       animator_second_ = animation::Animator(
-          &second_, SecondTarget(), option_->underline.leader_duration,
-          option_->underline.leader_function, option_->underline.leader_delay);
+          &second_, SecondTarget(), underline.leader_duration,
+          underline.leader_function, underline.leader_delay);
     } else {
       animator_first_ = animation::Animator(
-          &first_, FirstTarget(), option_->underline.leader_duration,
-          option_->underline.leader_function, option_->underline.leader_delay);
+          &first_, FirstTarget(), underline.leader_duration,
+          underline.leader_function, underline.leader_delay);
 
       animator_second_ = animation::Animator(
-          &second_, SecondTarget(), option_->underline.follower_duration,
-          option_->underline.follower_function,
-          option_->underline.follower_delay);
+          &second_, SecondTarget(), underline.follower_duration,
+          underline.follower_function, underline.follower_delay);
     }
   }
 
-  bool Focusable() const final { return entries_.size(); }
-  int& focused_entry() { return option_->focused_entry(); }
-  int size() const { return int(entries_.size()); }
+  bool Focusable() const final { return entries.size(); }
+  int size() const { return int(entries.size()); }
   float FirstTarget() {
     if (boxes_.empty()) {
       return 0.F;
     }
-    const int value = IsHorizontal() ? boxes_[*selected_].x_min - box_.x_min
-                                     : boxes_[*selected_].y_min - box_.y_min;
+    const int value = IsHorizontal() ? boxes_[selected()].x_min - box_.x_min
+                                     : boxes_[selected()].y_min - box_.y_min;
     return float(value);
   }
   float SecondTarget() {
     if (boxes_.empty()) {
       return 0.F;
     }
-    const int value = IsHorizontal() ? boxes_[*selected_].x_max - box_.x_min
-                                     : boxes_[*selected_].y_max - box_.y_min;
+    const int value = IsHorizontal() ? boxes_[selected()].x_max - box_.x_min
+                                     : boxes_[selected()].y_max - box_.y_min;
     return float(value);
   }
 
  protected:
-  ConstStringListRef entries_;
-  int* selected_;
-  int selected_previous_ = *selected_;
-  int selected_focus_ = *selected_;
-  Ref<MenuOption> option_;
+  int selected_previous_ = selected();
+  int selected_focus_ = selected();
 
+  // Mouse click support:
   std::vector<Box> boxes_;
   Box box_;
 
+  // Animation support:
   float first_ = 0.F;
   float second_ = 0.F;
   animation::Animator animator_first_ = animation::Animator(&first_, 0.F);
   animation::Animator animator_second_ = animation::Animator(&second_, 0.F);
-
   std::vector<animation::Animator> animator_background_;
   std::vector<animation::Animator> animator_foreground_;
   std::vector<float> animation_background_;
   std::vector<float> animation_foreground_;
 };
 
+/// @brief A list of text. The focused element is selected.
+/// @param option a structure containing all the paramters.
+/// @ingroup component
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::TerminalOutput();
+/// std::vector<std::string> entries = {
+///     "entry 1",
+///     "entry 2",
+///     "entry 3",
+/// };
+/// int selected = 0;
+/// auto menu = Menu({
+///   .entries = &entries,
+///   .selected = &selected,
+/// });
+/// screen.Loop(menu);
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// > entry 1
+///   entry 2
+///   entry 3
+/// ```
+Component Menu(MenuOption option) {
+  return Make<MenuBase>(std::move(option));
+}
+
 /// @brief A list of text. The focused element is selected.
 /// @param entries The list of entries in the menu.
 /// @param selected The index of the currently selected element.
@@ -513,10 +539,10 @@ class MenuBase : public ComponentBase {
 ///   entry 2
 ///   entry 3
 /// ```
-Component Menu(ConstStringListRef entries,
-               int* selected,
-               Ref<MenuOption> option) {
-  return Make<MenuBase>(entries, selected, std::move(option));
+Component Menu(ConstStringListRef entries, int* selected, MenuOption option) {
+  option.entries = entries;
+  option.selected = selected;
+  return Menu(std::move(option));
 }
 
 /// @brief An horizontal list of elements. The user can navigate through them.
@@ -554,11 +580,41 @@ Component Toggle(ConstStringListRef entries, int* selected) {
 ///   entry 2
 ///   entry 3
 /// ```
-Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
-  class Impl : public ComponentBase {
+Component MenuEntry(ConstStringRef label, MenuEntryOption option) {
+  option.label = label;
+  return MenuEntry(std::move(option));
+}
+
+/// @brief A specific menu entry. They can be put into a Container::Vertical to
+/// form a menu.
+/// @param option The parameters.
+/// @ingroup component
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::TerminalOutput();
+/// int selected = 0;
+/// auto menu = Container::Vertical({
+///    MenuEntry({.label = "entry 1"}),
+///    MenuEntry({.label = "entry 2"}),
+///    MenuEntry({.label = "entry 3"}),
+/// }, &selected);
+/// screen.Loop(menu);
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// > entry 1
+///   entry 2
+///   entry 3
+/// ```
+Component MenuEntry(MenuEntryOption option) {
+  class Impl : public ComponentBase, public MenuEntryOption {
    public:
-    Impl(ConstStringRef label, Ref<MenuEntryOption> option)
-        : label_(std::move(label)), option_(std::move(option)) {}
+    explicit Impl(MenuEntryOption option)
+        : MenuEntryOption(std::move(option)) {}
 
    private:
     Element Render() override {
@@ -566,14 +622,14 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
       UpdateAnimationTarget();
 
       const EntryState state = {
-          *label_,
+          label(),
           false,
           hovered_,
           focused,
       };
 
       const Element element =
-          (option_->transform ? option_->transform : DefaultOptionTransform)  //
+          (transform ? transform : DefaultOptionTransform)  //
           (state);
 
       auto focus_management = focused ? select : nothing;
@@ -586,30 +642,28 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
       if (target == animator_background_.to()) {
         return;
       }
-      animator_background_ =
-          animation::Animator(&animation_background_, target,
-                              option_->animated_colors.background.duration,
-                              option_->animated_colors.background.function);
-      animator_foreground_ =
-          animation::Animator(&animation_foreground_, target,
-                              option_->animated_colors.foreground.duration,
-                              option_->animated_colors.foreground.function);
+      animator_background_ = animation::Animator(
+          &animation_background_, target, animated_colors.background.duration,
+          animated_colors.background.function);
+      animator_foreground_ = animation::Animator(
+          &animation_foreground_, target, animated_colors.foreground.duration,
+          animated_colors.foreground.function);
     }
 
     Decorator AnimatedColorStyle() {
       Decorator style = nothing;
-      if (option_->animated_colors.foreground.enabled) {
-        style = style | color(Color::Interpolate(
-                            animation_foreground_,
-                            option_->animated_colors.foreground.inactive,
-                            option_->animated_colors.foreground.active));
+      if (animated_colors.foreground.enabled) {
+        style = style |
+                color(Color::Interpolate(animation_foreground_,
+                                         animated_colors.foreground.inactive,
+                                         animated_colors.foreground.active));
       }
 
-      if (option_->animated_colors.background.enabled) {
-        style = style | bgcolor(Color::Interpolate(
-                            animation_background_,
-                            option_->animated_colors.background.inactive,
-                            option_->animated_colors.background.active));
+      if (animated_colors.background.enabled) {
+        style = style |
+                bgcolor(Color::Interpolate(animation_background_,
+                                           animated_colors.background.inactive,
+                                           animated_colors.background.active));
       }
       return style;
     }
@@ -640,8 +694,7 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
       animator_foreground_.OnAnimation(params);
     }
 
-    ConstStringRef label_;
-    Ref<MenuEntryOption> option_;
+    MenuEntryOption option_;
     Box box_;
     bool hovered_ = false;
 
@@ -653,7 +706,7 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
         animation::Animator(&animation_foreground_, 0.F);
   };
 
-  return Make<Impl>(std::move(label), std::move(option));
+  return Make<Impl>(std::move(option));
 }
 
 }  // namespace ftxui
diff --git a/src/ftxui/component/menu_test.cpp b/src/ftxui/component/menu_test.cpp
index 4eda9909ebc502a8970a8a765126f33fb8cccd23..910948fb4bd9f89672dbb83df3b6307c7219aad1 100644
--- a/src/ftxui/component/menu_test.cpp
+++ b/src/ftxui/component/menu_test.cpp
@@ -23,9 +23,11 @@ TEST(MenuTest, RemoveEntries) {
   int focused_entry = 0;
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  MenuOption option;
-  option.focused_entry = &focused_entry;
-  auto menu = Menu(&entries, &selected, option);
+  auto menu = Menu({
+      .entries = &entries,
+      .selected = &selected,
+      .focused_entry = &focused_entry,
+  });
 
   EXPECT_EQ(selected, 0);
   EXPECT_EQ(focused_entry, 0);
@@ -52,10 +54,8 @@ TEST(MenuTest, DirectionDown) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
   MenuOption option;
-  auto menu = Menu(&entries, &selected, &option);
+  auto menu = Menu(&entries, &selected, {.direction = Direction::Down});
 
-  selected = 0;
-  option.direction = Direction::Down;
   Screen screen(4, 3);
   Render(screen, menu->Render());
   EXPECT_EQ(screen.ToString(),
@@ -80,9 +80,7 @@ TEST(MenuTest, DirectionDown) {
 TEST(MenuTest, DirectionsUp) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  MenuOption option;
-  auto menu = Menu(&entries, &selected, &option);
-  option.direction = Direction::Up;
+  auto menu = Menu(&entries, &selected, {.direction = Direction::Up});
   Screen screen(4, 3);
   Render(screen, menu->Render());
   EXPECT_EQ(screen.ToString(),
@@ -106,9 +104,7 @@ TEST(MenuTest, DirectionsUp) {
 TEST(MenuTest, DirectionsRight) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  MenuOption option;
-  auto menu = Menu(&entries, &selected, &option);
-  option.direction = Direction::Right;
+  auto menu = Menu(&entries, &selected, {.direction = Direction::Right});
   Screen screen(10, 1);
   Render(screen, menu->Render());
   EXPECT_EQ(screen.ToString(),
@@ -132,9 +128,7 @@ TEST(MenuTest, DirectionsRight) {
 TEST(MenuTest, DirectionsLeft) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  MenuOption option;
-  auto menu = Menu(&entries, &selected, &option);
-  option.direction = Direction::Left;
+  auto menu = Menu(&entries, &selected, {.direction = Direction::Left});
   Screen screen(10, 1);
   Render(screen, menu->Render());
   EXPECT_EQ(screen.ToString(),
@@ -158,8 +152,7 @@ TEST(MenuTest, DirectionsLeft) {
 TEST(MenuTest, AnimationsHorizontal) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  auto option = MenuOption::HorizontalAnimated();
-  auto menu = Menu(&entries, &selected, &option);
+  auto menu = Menu(&entries, &selected, MenuOption::HorizontalAnimated());
   {
     Screen screen(4, 3);
     Render(screen, menu->Render());
@@ -195,8 +188,7 @@ TEST(MenuTest, AnimationsHorizontal) {
 TEST(MenuTest, AnimationsVertical) {
   int selected = 0;
   std::vector<std::string> entries = {"1", "2", "3"};
-  auto option = MenuOption::VerticalAnimated();
-  auto menu = Menu(&entries, &selected, &option);
+  auto menu = Menu(&entries, &selected, MenuOption::VerticalAnimated());
   {
     Screen screen(10, 3);
     Render(screen, menu->Render());
diff --git a/src/ftxui/component/radiobox.cpp b/src/ftxui/component/radiobox.cpp
index 10f4bf054cf67d23582d4f1fdef6d049204233d3..00ac7024f25913111d7ad3d2dbafabf7adf31d65 100644
--- a/src/ftxui/component/radiobox.cpp
+++ b/src/ftxui/component/radiobox.cpp
@@ -21,12 +21,9 @@ namespace {
 /// @brief A list of selectable element. One and only one can be selected at
 /// the same time.
 /// @ingroup component
-class RadioboxBase : public ComponentBase {
+class RadioboxBase : public ComponentBase, public RadioboxOption {
  public:
-  RadioboxBase(ConstStringListRef entries,
-               int* selected,
-               Ref<RadioboxOption> option)
-      : entries_(entries), selected_(selected), option_(std::move(option)) {}
+  explicit RadioboxBase(RadioboxOption option) : RadioboxOption(option) {}
 
  private:
   Element Render() override {
@@ -41,14 +38,13 @@ class RadioboxBase : public ComponentBase {
                               : is_menu_focused ? focus
                                                 : select;
       auto state = EntryState{
-          entries_[i],
-          *selected_ == i,
+          entries[i],
+          selected() == i,
           is_selected,
           is_focused,
       };
       auto element =
-          (option_->transform ? option_->transform
-                              : RadioboxOption::Simple().transform)(state);
+          (transform ? transform : RadioboxOption::Simple().transform)(state);
 
       elements.push_back(element | focus_management | reflect(boxes_[i]));
     }
@@ -97,14 +93,14 @@ class RadioboxBase : public ComponentBase {
 
       if (hovered_ != old_hovered) {
         focused_entry() = hovered_;
-        option_->on_change();
+        on_change();
         return true;
       }
     }
 
     if (event == Event::Character(' ') || event == Event::Return) {
-      *selected_ = hovered_;
-      option_->on_change();
+      selected() = hovered_;
+      on_change();
       return true;
     }
 
@@ -126,9 +122,9 @@ class RadioboxBase : public ComponentBase {
       focused_entry() = i;
       if (event.mouse().button == Mouse::Left &&
           event.mouse().motion == Mouse::Released) {
-        if (*selected_ != i) {
-          *selected_ = i;
-          option_->on_change();
+        if (selected() != i) {
+          selected() = i;
+          on_change();
         }
 
         return true;
@@ -154,7 +150,7 @@ class RadioboxBase : public ComponentBase {
     hovered_ = util::clamp(hovered_, 0, size() - 1);
 
     if (hovered_ != old_hovered) {
-      option_->on_change();
+      on_change();
     }
 
     return true;
@@ -162,25 +158,54 @@ class RadioboxBase : public ComponentBase {
 
   void Clamp() {
     boxes_.resize(size());
-    *selected_ = util::clamp(*selected_, 0, size() - 1);
+    selected() = util::clamp(selected(), 0, size() - 1);
     focused_entry() = util::clamp(focused_entry(), 0, size() - 1);
     hovered_ = util::clamp(hovered_, 0, size() - 1);
   }
 
-  bool Focusable() const final { return entries_.size(); }
-  int& focused_entry() { return option_->focused_entry(); }
-  int size() const { return int(entries_.size()); }
+  bool Focusable() const final { return entries.size(); }
+  int size() const { return int(entries.size()); }
 
-  ConstStringListRef entries_;
-  int* selected_;
-  int hovered_ = *selected_;
+  int hovered_ = selected();
   std::vector<Box> boxes_;
   Box box_;
-  Ref<RadioboxOption> option_;
 };
 
 }  // namespace
 
+/// @brief A list of element, where only one can be selected.
+/// @param option The parameters
+/// @ingroup component
+/// @see RadioboxBase
+///
+/// ### Example
+///
+/// ```cpp
+/// auto screen = ScreenInteractive::TerminalOutput();
+/// std::vector<std::string> entries = {
+///     "entry 1",
+///     "entry 2",
+///     "entry 3",
+/// };
+/// int selected = 0;
+/// auto menu = Radiobox({
+///   .entries = entries,
+///   .selected = &selected,
+/// });
+/// screen.Loop(menu);
+/// ```
+///
+/// ### Output
+///
+/// ```bash
+/// ◉ entry 1
+/// ○ entry 2
+/// ○ entry 3
+/// ```
+Component Radiobox(RadioboxOption option) {
+  return Make<RadioboxBase>(std::move(option));
+}
+
 /// @brief A list of element, where only one can be selected.
 /// @param entries The list of entries in the list.
 /// @param selected The index of the currently selected element.
@@ -211,8 +236,10 @@ class RadioboxBase : public ComponentBase {
 /// ```
 Component Radiobox(ConstStringListRef entries,
                    int* selected,
-                   Ref<RadioboxOption> option) {
-  return Make<RadioboxBase>(entries, selected, std::move(option));
+                   RadioboxOption option) {
+  option.entries = entries;
+  option.selected = selected;
+  return Make<RadioboxBase>(std::move(option));
 }
 
 }  // namespace ftxui
diff --git a/src/ftxui/component/slider.cpp b/src/ftxui/component/slider.cpp
index dc901484763bd7b77ab6387c288ec9c8c1fdc705..59199a899710353d2f998975a641128f2fd0680a 100644
--- a/src/ftxui/component/slider.cpp
+++ b/src/ftxui/component/slider.cpp
@@ -35,24 +35,24 @@ Decorator flexDirection(Direction direction) {
 template <class T>
 class SliderBase : public ComponentBase {
  public:
-  explicit SliderBase(Ref<SliderOption<T>> options)
-      : value_(options->value),
-        min_(options->min),
-        max_(options->max),
-        increment_(options->increment),
+  explicit SliderBase(SliderOption<T> options)
+      : value_(options.value),
+        min_(options.min),
+        max_(options.max),
+        increment_(options.increment),
         options_(options) {}
 
   Element Render() override {
-    auto gauge_color = Focused() ? color(options_->color_active)
-                                 : color(options_->color_inactive);
+    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_) |
+    return gaugeDirection(percent, options_.direction) |
+           flexDirection(options_.direction) | reflect(gauge_box_) |
            gauge_color;
   }
 
   void OnLeft() {
-    switch (options_->direction) {
+    switch (options_.direction) {
       case Direction::Right:
         value_() -= increment_();
         break;
@@ -66,7 +66,7 @@ class SliderBase : public ComponentBase {
   }
 
   void OnRight() {
-    switch (options_->direction) {
+    switch (options_.direction) {
       case Direction::Right:
         value_() += increment_();
         break;
@@ -80,7 +80,7 @@ class SliderBase : public ComponentBase {
   }
 
   void OnUp() {
-    switch (options_->direction) {
+    switch (options_.direction) {
       case Direction::Up:
         value_() -= increment_();
         break;
@@ -94,7 +94,7 @@ class SliderBase : public ComponentBase {
   }
 
   void OnDown() {
-    switch (options_->direction) {
+    switch (options_.direction) {
       case Direction::Down:
         value_() -= increment_();
         break;
@@ -153,7 +153,7 @@ class SliderBase : public ComponentBase {
     }
 
     if (captured_mouse_) {
-      switch (options_->direction) {
+      switch (options_.direction) {
         case Direction::Right: {
           value_() = min_() + (event.mouse().x - gauge_box_.x_min) *
                                   (max_() - min_()) /
@@ -192,15 +192,14 @@ class SliderBase : public ComponentBase {
   ConstRef<T> min_;
   ConstRef<T> max_;
   ConstRef<T> increment_;
-  Ref<SliderOption<T>> options_;
+  SliderOption<T> options_;
   Box gauge_box_;
   CapturedMouse captured_mouse_;
 };
 
 class SliderWithLabel : public ComponentBase {
  public:
-  SliderWithLabel(ConstStringRef label, Component inner)
-      : label_(std::move(label)) {
+  SliderWithLabel(ConstStringRef label, Component inner) : label_(label) {
     Add(std::move(inner));
     SetActiveChild(ChildAt(0));
   }
diff --git a/src/ftxui/component/toggle_test.cpp b/src/ftxui/component/toggle_test.cpp
index b3dd5b056fcf56fa5751df0645c452d7f2106a05..722a27cc1d4e4c11b346080d8a80cdc882b810ad 100644
--- a/src/ftxui/component/toggle_test.cpp
+++ b/src/ftxui/component/toggle_test.cpp
@@ -91,7 +91,7 @@ TEST(ToggleTest, OnChange) {
   auto option = MenuOption::Toggle();
   option.on_change = [&] { counter++; };
 
-  auto toggle = Menu(&entries, &selected, &option);
+  auto toggle = Menu(&entries, &selected, option);
 
   EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft));  // Reached far left.
   EXPECT_EQ(counter, 0);
@@ -120,7 +120,7 @@ TEST(ToggleTest, OnEnter) {
 
   auto option = MenuOption::Toggle();
   option.on_enter = [&] { counter++; };
-  auto toggle = Menu(&entries, &selected, &option);
+  auto toggle = Menu(&entries, &selected, option);
 
   EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft));  // Reached far left.
   EXPECT_TRUE(toggle->OnEvent(Event::Return));
diff --git a/src/ftxui/dom/canvas.cpp b/src/ftxui/dom/canvas.cpp
index 5270ad950fa6ac891a01f4a672cc04571a14edef..58ca4e3d2169c66d33b20f3cf4bcc467b469ddd2 100644
--- a/src/ftxui/dom/canvas.cpp
+++ b/src/ftxui/dom/canvas.cpp
@@ -845,9 +845,11 @@ class CanvasNodeBase : public Node {
 }  // namespace
 
 /// @brief Produce an element from a Canvas, or a reference to a Canvas.
+// NOLINTNEXTLINE
 Element canvas(ConstRef<Canvas> canvas) {
   class Impl : public CanvasNodeBase {
    public:
+    // NOLINTNEXTLINE
     explicit Impl(ConstRef<Canvas> canvas) : canvas_(std::move(canvas)) {
       requirement_.min_x = (canvas_->width() + 1) / 2;
       requirement_.min_y = (canvas_->height() + 3) / 4;
diff --git a/src/ftxui/dom/hyperlink.cpp b/src/ftxui/dom/hyperlink.cpp
index 6ce8a7ad8afbbab4f0b9ec58b6804975f4c7a2f4..4d2dd05f9cfe20fca51f5e90eda662cdbccdb091 100644
--- a/src/ftxui/dom/hyperlink.cpp
+++ b/src/ftxui/dom/hyperlink.cpp
@@ -13,10 +13,10 @@ namespace ftxui {
 class Hyperlink : public NodeDecorator {
  public:
   Hyperlink(Element child, std::string link)
-      : NodeDecorator(std::move(child)), link_(link) {}
+      : NodeDecorator(std::move(child)), link_(std::move(link)) {}
 
   void Render(Screen& screen) override {
-    uint8_t hyperlink_id = screen.RegisterHyperlink(link_);
+    const uint8_t hyperlink_id = screen.RegisterHyperlink(link_);
     for (int y = box_.y_min; y <= box_.y_max; ++y) {
       for (int x = box_.x_min; x <= box_.x_max; ++x) {
         screen.PixelAt(x, y).hyperlink = hyperlink_id;
@@ -44,7 +44,7 @@ class Hyperlink : public NodeDecorator {
 ///   hyperlink("https://github.com/ArthurSonzogni/FTXUI", "link");
 /// ```
 Element hyperlink(std::string link, Element child) {
-  return std::make_shared<Hyperlink>(std::move(child), link);
+  return std::make_shared<Hyperlink>(std::move(child), std::move(link));
 }
 
 /// @brief Decorate using an hyperlink.
@@ -61,6 +61,7 @@ Element hyperlink(std::string link, Element child) {
 /// Element document =
 ///   text("red") | hyperlink("https://github.com/Arthursonzogni/FTXUI");
 /// ```
+// NOLINTNEXTLINE
 Decorator hyperlink(std::string link) {
   return [link](Element child) { return hyperlink(link, std::move(child)); };
 }
diff --git a/src/ftxui/screen/screen.cpp b/src/ftxui/screen/screen.cpp
index 0f2e3772e00bc0742e8f92ce5ea7418be2f3e1cb..dd0570f48d52ab116608b2d11b6d35d2075fffd2 100644
--- a/src/ftxui/screen/screen.cpp
+++ b/src/ftxui/screen/screen.cpp
@@ -1,5 +1,6 @@
 #include <cstdint>  // for size_t
 #include <iostream>  // for operator<<, stringstream, basic_ostream, flush, cout, ostream
+#include <limits>
 #include <map>      // for _Rb_tree_const_iterator, map, operator!=, operator==
 #include <memory>   // for allocator, allocator_traits<>::value_type
 #include <sstream>  // IWYU pragma: keep
@@ -553,13 +554,13 @@ void Screen::ApplyShader() {
 }
 // clang-format on
 
-uint8_t Screen::RegisterHyperlink(std::string link) {
+uint8_t Screen::RegisterHyperlink(const std::string& link) {
   for (size_t i = 0; i < hyperlinks_.size(); ++i) {
     if (hyperlinks_[i] == link) {
       return i;
     }
   }
-  if (hyperlinks_.size() == 255) {
+  if (hyperlinks_.size() == std::numeric_limits<uint8_t>::max()) {
     return 0;
   }
   hyperlinks_.push_back(link);
diff --git a/src/ftxui/screen/string.cpp b/src/ftxui/screen/string.cpp
index 37305e7de146a611e6bde56705c3a78fa49686c7..b477acb18626d5ae508bd2fabe72787bcd41ac21 100644
--- a/src/ftxui/screen/string.cpp
+++ b/src/ftxui/screen/string.cpp
@@ -7,22 +7,17 @@
 
 #include "ftxui/screen/string.hpp"
 
-#include <stddef.h>  // for size_t
-#include <array>     // for array
-#include <cstdint>   // for uint32_t, uint8_t, uint16_t, int32_t
-#include <string>    // for string, basic_string, wstring
-#include <tuple>     // for _Swallow_assign, ignore
+#include <array>    // for array
+#include <cstddef>  // for size_t
+#include <cstdint>  // for uint32_t, uint8_t, uint16_t, int32_t
+#include <string>   // for string, basic_string, wstring
+#include <tuple>    // for _Swallow_assign, ignore
 
 #include "ftxui/screen/deprecated.hpp"       // for wchar_width, wstring_width
 #include "ftxui/screen/string_internal.hpp"  // for WordBreakProperty, EatCodePoint, CodepointToWordBreakProperty, GlyphCount, GlyphIterate, GlyphNext, GlyphPrevious, IsCombining, IsControl, IsFullWidth, Utf8ToWordBreakProperty
 
 namespace {
 
-using ftxui::EatCodePoint;
-using ftxui::IsCombining;
-using ftxui::IsControl;
-using ftxui::IsFullWidth;
-
 struct Interval {
   uint32_t first;
   uint32_t last;
@@ -1565,8 +1560,9 @@ bool IsControl(uint32_t ucs) {
   if (ucs == 0) {
     return true;
   }
-  if (ucs < 32) {      // NOLINT
-    return ucs != 10;  // 10 => Line feed.
+  if (ucs < 32) {  // NOLINT
+    const uint32_t LINE_FEED = 10;
+    return ucs != LINE_FEED;
   }
   if (ucs >= 0x7f && ucs < 0xa0) {  // NOLINT
     return true;