diff --git a/src/common/settings.h b/src/common/settings.h
index 4407c1e6da6445af648974b226b2b5552cbafd01..6d44fc6260cf9e8de6f0d705d9a0d3e02e9f3f19 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -379,7 +379,13 @@ struct Values {
 
     Setting<s32> current_user{linkage, 0, "current_user", Category::System};
 
-    SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
+    SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
+                                                   ConsoleMode::Docked,
+                                                   "use_docked_mode",
+                                                   Category::System,
+                                                   Specialization::Radio,
+                                                   true,
+                                                   true};
 
     // Controls
     InputSetting<std::array<PlayerInput, 10>> players;
diff --git a/src/common/settings_common.h b/src/common/settings_common.h
index 2efb329b0733cf7f5e38d2ff029f91531e983475..3082e0ce1a58ed6c79f83c9543f894ae33132db5 100644
--- a/src/common/settings_common.h
+++ b/src/common/settings_common.h
@@ -56,6 +56,7 @@ enum Specialization : u8 {
     Scalar = 5,      // Values are continuous
     Countable = 6,   // Can be stepped through
     Paired = 7,      // Another setting is associated with this setting
+    Radio = 8,       // Setting should be presented in a radio group
 
     Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage
 };
diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h
index e7cb59ea5bce432e5c06d1fba769660b48fd2c97..815cafe15e4652abc0db27873ae47d77e52eb284 100644
--- a/src/common/settings_enums.h
+++ b/src/common/settings_enums.h
@@ -146,6 +146,8 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
 
 ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
 
+ENUM(ConsoleMode, Handheld, Docked);
+
 template <typename Type>
 inline std::string CanonicalizeEnum(Type id) {
     const auto group = EnumMetadata<Type>::Canonicalizations();
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 3300d4f79790257acb39fb66237ffaff2f825328..4c0c5434cbeff8eb368ad1b0f626a1cc79db0c35 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -3,6 +3,7 @@
 
 #include "common/assert.h"
 #include "common/logging/log.h"
+#include "common/settings_enums.h"
 #include "core/frontend/applets/controller.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -62,7 +63,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
                 controller->Connect(true);
             }
         } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
-                   !Settings::values.use_docked_mode.GetValue()) {
+                   Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Handheld) {
             // We should *never* reach here under any normal circumstances.
             controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
             controller->Connect(true);
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index b4081fc394754dfeb8cd9af84bff86bbe6bf40fa..ae0a44f1239c16c72ae7dae07f9f983312e1d11c 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -5,6 +5,7 @@
 
 #include "common/assert.h"
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/frontend/framebuffer_layout.h"
 
 namespace Layout {
@@ -49,7 +50,8 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
 }
 
 FramebufferLayout FrameLayoutFromResolutionScale(f32 res_scale) {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
+    const bool is_docked =
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
     const u32 screen_width = is_docked ? ScreenDocked::Width : ScreenUndocked::Width;
     const u32 screen_height = is_docked ? ScreenDocked::Height : ScreenUndocked::Height;
 
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 8d057b3a8f6d87ab7e8140d8fffecea1709b82ec..81df91a2d7c92a644076f950fb3d1200134956c5 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -6,6 +6,7 @@
 #include <cinttypes>
 #include <cstring>
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
@@ -833,7 +834,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(ResultSuccess);
 
-    if (Settings::values.use_docked_mode.GetValue()) {
+    if (Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked) {
         rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
         rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
     } else {
@@ -921,7 +922,8 @@ void IStorage::Open(HLERequestContext& ctx) {
 }
 
 void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
-    const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
+    const bool use_docked_mode{Settings::values.use_docked_mode.GetValue() ==
+                               Settings::ConsoleMode::Docked};
     LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
 
     IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/apm/apm_controller.cpp b/src/core/hle/service/apm/apm_controller.cpp
index 227fdd0cfb04441eb52fb1702a16893a916852f8..1656b2e730b641e6f4c104c16f4e7dedd8da8faf 100644
--- a/src/core/hle/service/apm/apm_controller.cpp
+++ b/src/core/hle/service/apm/apm_controller.cpp
@@ -7,6 +7,7 @@
 
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/core_timing.h"
 #include "core/hle/service/apm/apm_controller.h"
 
@@ -67,8 +68,9 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
 }
 
 PerformanceMode Controller::GetCurrentPerformanceMode() const {
-    return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Boost
-                                                       : PerformanceMode::Normal;
+    return Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked
+               ? PerformanceMode::Boost
+               : PerformanceMode::Normal;
 }
 
 PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 03432f7cb6b9576bbbe3b6013bfeed21ae626539..47d4c08fcc0727b815d6a4e77116b93e89bd9acc 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -331,7 +331,7 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties()
         };
 
         // Hack: There is no touch in docked but games still allow it
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked) {
             gesture.points[id] = {
                 .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width),
                 .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height),
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 28818c813d4806faec09a1a1b0da3bff110dd4a7..ba752d4721a5d88ea5c54512c84995f857e4fae7 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -1518,7 +1518,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
             return false;
         }
         // Handheld shouldn't be supported in docked mode
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked) {
             return false;
         }
 
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 6bb02393c1d5c5d77c88d90a265b3aa38174d69a..6b5f3a17a42f840c9208bb060d6f481d71bf7169 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -217,7 +217,7 @@ private:
         IPC::ResponseBuilder rb{ctx, 6};
         rb.Push(ResultSuccess);
 
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked) {
             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
         } else {
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 62b3f66361ec12fe22e354e11543ed64a230f96e..8a1cd24b0e13943349125ab5439658140667e6cb 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -14,6 +14,7 @@
 #include "common/logging/log.h"
 
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
 #include "core/loader/loader.h"
@@ -275,7 +276,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
              static_cast<u32>(Settings::values.shader_backend.GetValue()));
     AddField(field_type, "Renderer_UseAsynchronousShaders",
              Settings::values.use_asynchronous_shaders.GetValue());
-    AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
+    AddField(field_type, "System_UseDockedMode",
+             Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked);
 }
 
 bool TelemetrySession::SubmitTestcase() {
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 00aafb8f8f3aa0b69813b5b2d7f2e315025c78a3..c783325fb49734344ffa0bfb24dcdcf5e9b689c9 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -5,6 +5,7 @@
 #include <thread>
 
 #include "common/assert.h"
+#include "common/settings_enums.h"
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/hid/emulated_controller.h"
@@ -226,9 +227,14 @@ int QtControllerSelectorDialog::exec() {
 }
 
 void QtControllerSelectorDialog::ApplyConfiguration() {
-    const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
-    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
-    OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
+    const bool pre_docked_mode =
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
+    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()
+                                                  ? Settings::ConsoleMode::Docked
+                                                  : Settings::ConsoleMode::Handheld);
+    OnDockedModeChanged(
+        pre_docked_mode,
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked, system);
 
     Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
     Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@@ -616,8 +622,10 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
     ui->radioDocked->setEnabled(!is_handheld);
     ui->radioUndocked->setEnabled(!is_handheld);
 
-    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
-    ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
+    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue() ==
+                                Settings::ConsoleMode::Docked);
+    ui->radioUndocked->setChecked(Settings::values.use_docked_mode.GetValue() ==
+                                  Settings::ConsoleMode::Handheld);
 
     // Also force into undocked mode if the controller type is handheld.
     if (is_handheld) {
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 407988b8f5acbe761ae331c9e2fa2b2078919f40..37753b47e90ac9be96014ee599169b08d95b470a 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -928,8 +928,9 @@ void GRenderWindow::CaptureScreenshot(const QString& screenshot_path) {
     const Layout::FramebufferLayout layout{[]() {
         u32 height = UISettings::values.screenshot_height.GetValue();
         if (height == 0) {
-            height = Settings::values.use_docked_mode.GetValue() ? Layout::ScreenDocked::Height
-                                                                 : Layout::ScreenUndocked::Height;
+            height = Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked
+                         ? Layout::ScreenDocked::Height
+                         : Layout::ScreenUndocked::Height;
             height *= Settings::values.resolution_info.up_factor;
         }
         const u32 width =
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index b22c833032ac68d27c2824c8791e9ec0c75428ef..1de093447f0ac6e24e138dae5d32d7d593dd32db 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -9,6 +9,7 @@
 #include "common/fs/path_util.h"
 #include "common/settings.h"
 #include "common/settings_common.h"
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/hid/controllers/npad.h"
@@ -85,9 +86,9 @@ const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_ma
     {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
 };
 
-const std::map<bool, QString> Config::use_docked_mode_texts_map = {
-    {true, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
-    {false, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
+const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = {
+    {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
+    {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
 };
 
 const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = {
@@ -376,7 +377,7 @@ void Config::ReadControlValues() {
     const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
     if (controller_type == Settings::ControllerType::Handheld) {
         Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
-        Settings::values.use_docked_mode.SetValue(false);
+        Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
     }
 
     if (IsCustomConfig()) {
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 0ac74c8e7232560e3793e20831dab8628b86048e..727feebfb2987d6b7d0580c6d29f432c84221f0a 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -9,6 +9,7 @@
 #include <QMetaType>
 #include <QVariant>
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "yuzu/uisettings.h"
 
 class QSettings;
@@ -51,7 +52,7 @@ public:
 
     static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
     static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;
-    static const std::map<bool, QString> use_docked_mode_texts_map;
+    static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map;
     static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map;
     static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
     static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 7fce85bca7e92b3077932fe93ba85726fc2bb88c..78ed8c61071773331c920fa567a299dbfb5495e1 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -4,6 +4,7 @@
 #include <memory>
 #include <thread>
 
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -197,9 +198,14 @@ void ConfigureInput::ApplyConfiguration() {
 
     advanced->ApplyConfiguration();
 
-    const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
-    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
-    OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
+    const bool pre_docked_mode =
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
+    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()
+                                                  ? Settings::ConsoleMode::Docked
+                                                  : Settings::ConsoleMode::Handheld);
+    OnDockedModeChanged(
+        pre_docked_mode,
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked, system);
 
     Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
     Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@@ -267,8 +273,10 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
     ui->radioDocked->setEnabled(!is_handheld);
     ui->radioUndocked->setEnabled(!is_handheld);
 
-    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
-    ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
+    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue() ==
+                                Settings::ConsoleMode::Docked);
+    ui->radioUndocked->setChecked(Settings::values.use_docked_mode.GetValue() ==
+                                  Settings::ConsoleMode::Handheld);
 
     // Also force into undocked mode if the controller type is handheld.
     if (is_handheld) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a9d035f3dd5105119be7724f46056800942d1ad5..8ab4e73b18dde1a21669be9f4599861aff312c7c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1158,9 +1158,9 @@ void GMainWindow::InitializeWidgets() {
             [this](const QPoint& menu_location) {
                 QMenu context_menu;
 
-                for (auto const& docked_mode_pair : Config::use_docked_mode_texts_map) {
-                    context_menu.addAction(docked_mode_pair.second, [this, docked_mode_pair] {
-                        if (docked_mode_pair.first != Settings::values.use_docked_mode.GetValue()) {
+                for (auto const& [value, text] : Config::use_docked_mode_texts_map) {
+                    context_menu.addAction(text, [this, value] {
+                        if (value != Settings::values.use_docked_mode.GetValue()) {
                             OnToggleDockedMode();
                         }
                     });
@@ -3636,7 +3636,8 @@ void GMainWindow::OnTasReset() {
 }
 
 void GMainWindow::OnToggleDockedMode() {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
+    const bool is_docked =
+        Settings::values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
     auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
     auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
 
@@ -3650,7 +3651,8 @@ void GMainWindow::OnToggleDockedMode() {
         controller_dialog->refreshConfiguration();
     }
 
-    Settings::values.use_docked_mode.SetValue(!is_docked);
+    Settings::values.use_docked_mode.SetValue(is_docked ? Settings::ConsoleMode::Docked
+                                                        : Settings::ConsoleMode::Handheld);
     UpdateDockedButton();
     OnDockedModeChanged(is_docked, !is_docked, *system);
 }
@@ -4080,8 +4082,8 @@ void GMainWindow::UpdateGPUAccuracyButton() {
 }
 
 void GMainWindow::UpdateDockedButton() {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
-    dock_status_button->setChecked(is_docked);
+    const auto is_docked = Settings::values.use_docked_mode.GetValue();
+    dock_status_button->setChecked(is_docked == Settings::ConsoleMode::Docked);
     dock_status_button->setText(
         Config::use_docked_mode_texts_map.find(is_docked)->second.toUpper());
 }