diff --git a/loader/include/Geode/loader/SettingV3.hpp b/loader/include/Geode/loader/SettingV3.hpp
index 9f83cf1fc..ca1ec573b 100644
--- a/loader/include/Geode/loader/SettingV3.hpp
+++ b/loader/include/Geode/loader/SettingV3.hpp
@@ -78,7 +78,7 @@ namespace geode {
         void parseEnableIf(JsonExpectedValue& json);
         /**
          * Parses the `"requires-restart"` key from the setting's definition in 
-         * `mod.json` (if they exist), so `requiresRestart` works.
+         * `mod.json` (if it exists), so `requiresRestart` works.
          * @param json The current JSON checking instance being used. This 
          * should be the JSON object that defines the setting
          * @warning In most cases, you should be using `parseBaseProperties` 
@@ -87,6 +87,17 @@ namespace geode {
          * `init` before calling these parsing functions!
          */
         void parseValueProperties(JsonExpectedValue& json);
+        /**
+         * Parses the `"scroll-desc"` key from the setting's definition in 
+         * `mod.json` (if it exists), so `scrollableDescription` works.
+         * @param json The current JSON checking instance being used. This 
+         * should be the JSON object that defines the setting
+         * @warning In most cases, you should be using `parseBaseProperties` 
+         * instead to do all of this in one go! 
+         * If you do need the fine-grained control however, make sure to call 
+         * `init` before calling these parsing functions!
+         */
+        void parseScrollableDescription(JsonExpectedValue& json);
 
         /**
          * Parse all of the base properties such as `"name"` and `"description"` 
@@ -163,6 +174,10 @@ namespace geode {
          * Whether this setting requires a restart on change
          */
         bool requiresRestart() const;
+        /**
+         * Whether this setting wants its description to be scrollable
+         */
+        bool getScrollableDescription() const;
         /**
          * Get the platforms this setting is available on
          */
diff --git a/loader/src/loader/SettingNodeV3.cpp b/loader/src/loader/SettingNodeV3.cpp
index 23d42fb99..fab93e3fa 100644
--- a/loader/src/loader/SettingNodeV3.cpp
+++ b/loader/src/loader/SettingNodeV3.cpp
@@ -142,13 +142,23 @@ void SettingNodeV3::updateState(CCNode* invoker) {
 
 void SettingNodeV3::onDescription(CCObject*) {
     auto title = m_impl->setting->getDisplayName();
-    FLAlertLayer::create(
-        nullptr,
-        title.c_str(),
-        m_impl->setting->getDescription().value_or("No description provided"),
-        "OK", nullptr,
-        clamp(title.size() * 16, 300, 400)
-    )->show();
+    if (!m_impl->setting->getScrollableDescription()) {
+        FLAlertLayer::create(
+            nullptr,
+            title.c_str(),
+            m_impl->setting->getDescription().value_or("No description provided"),
+            "OK", nullptr,
+            clamp(title.size() * 16, 300, 400)
+        )->show();
+    } else {
+        FLAlertLayer::create(
+            nullptr,
+            title.c_str(),
+            m_impl->setting->getDescription().value_or("No description provided"),
+            "OK", nullptr,
+            420.f, true, 320.f, 1.0f // params in order: width, scrollable bool, height, textScale
+        )->show();
+    }
 }
 void SettingNodeV3::onReset(CCObject*) {
     createQuickPopup(
diff --git a/loader/src/loader/SettingV3.cpp b/loader/src/loader/SettingV3.cpp
index b469c336c..b44f5b5aa 100644
--- a/loader/src/loader/SettingV3.cpp
+++ b/loader/src/loader/SettingV3.cpp
@@ -477,6 +477,7 @@ class SettingV3::GeodeImpl {
     std::unique_ptr<enable_if_parsing::Component> enableIfTree;
     std::optional<std::string> enableIfDescription;
     bool requiresRestart = false;
+    bool scrollableDescription = false;
 };
 
 SettingV3::SettingV3() : m_impl(std::make_shared<GeodeImpl>()) {}
@@ -514,6 +515,9 @@ void SettingV3::parseEnableIf(JsonExpectedValue& json) {
 void SettingV3::parseValueProperties(JsonExpectedValue& json) {
     json.has("requires-restart").into(m_impl->requiresRestart);
 }
+void SettingV3::parseScrollableDescription(JsonExpectedValue& json) {
+    json.has("scroll-desc").into(m_impl->scrollableDescription);
+}
 
 Result<> SettingV3::parseBaseProperties(std::string const& key, std::string const& modID, matjson::Value const& value) {
     auto json = checkJson(value, "SettingV3");
@@ -525,6 +529,7 @@ void SettingV3::parseBaseProperties(std::string const& key, std::string const& m
     this->parseNameAndDescription(json);
     this->parseValueProperties(json);
     this->parseEnableIf(json);
+    this->parseScrollableDescription(json);
 }
 
 std::string SettingV3::getKey() const {
@@ -567,6 +572,9 @@ std::optional<std::string> SettingV3::getEnableIfDescription() const {
 bool SettingV3::requiresRestart() const {
     return m_impl->requiresRestart;
 }
+bool SettingV3::getScrollableDescription() const {
+    return m_impl->scrollableDescription;
+}
 std::vector<PlatformID> SettingV3::getPlatforms() const {
     return m_impl->platforms;
 }