diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs
index 7168504309..ed1de591f6 100644
--- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs
@@ -19,12 +19,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup
     {
         public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
 
-        private LabelledSliderBar<float> keyCountSlider { get; set; } = null!;
-        private LabelledSwitchButton specialStyle { get; set; } = null!;
-        private LabelledSliderBar<float> healthDrainSlider { get; set; } = null!;
-        private LabelledSliderBar<float> overallDifficultySlider { get; set; } = null!;
-        private LabelledSliderBar<double> baseVelocitySlider { get; set; } = null!;
-        private LabelledSliderBar<double> tickRateSlider { get; set; } = null!;
+        private FormSliderBar<float> keyCountSlider { get; set; } = null!;
+        private FormCheckBox specialStyle { get; set; } = null!;
+        private FormSliderBar<float> healthDrainSlider { get; set; } = null!;
+        private FormSliderBar<float> overallDifficultySlider { get; set; } = null!;
+        private FormSliderBar<double> baseVelocitySlider { get; set; } = null!;
+        private FormSliderBar<double> tickRateSlider { get; set; } = null!;
 
         [Resolved]
         private Editor? editor { get; set; }
@@ -37,77 +37,76 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup
         {
             Children = new Drawable[]
             {
-                keyCountSlider = new LabelledSliderBar<float>
+                keyCountSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsCsMania,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = "The number of columns in the beatmap",
+                    Caption = BeatmapsetsStrings.ShowStatsCsMania,
+                    HintText = "The number of columns in the beatmap",
                     Current = new BindableFloat(Beatmap.Difficulty.CircleSize)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 1,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                specialStyle = new LabelledSwitchButton
+                specialStyle = new FormCheckBox
                 {
-                    Label = "Use special (N+1) style",
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6K (5+1) or 8K (7+1) configurations.",
+                    Caption = "Use special (N+1) style",
+                    HintText = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6K (5+1) or 8K (7+1) configurations.",
                     Current = { Value = Beatmap.BeatmapInfo.SpecialStyle }
                 },
-                healthDrainSlider = new LabelledSliderBar<float>
+                healthDrainSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsDrain,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.DrainRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsDrain,
+                    HintText = EditorSetupStrings.DrainRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.DrainRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                overallDifficultySlider = new LabelledSliderBar<float>
+                overallDifficultySlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAccuracy,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.OverallDifficultyDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAccuracy,
+                    HintText = EditorSetupStrings.OverallDifficultyDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.OverallDifficulty)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                baseVelocitySlider = new LabelledSliderBar<double>
+                baseVelocitySlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.BaseVelocity,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.BaseVelocityDescription,
+                    Caption = EditorSetupStrings.BaseVelocity,
+                    HintText = EditorSetupStrings.BaseVelocityDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier)
                     {
                         Default = 1.4,
                         MinValue = 0.4,
                         MaxValue = 3.6,
                         Precision = 0.01f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                tickRateSlider = new LabelledSliderBar<double>
+                tickRateSlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.TickRate,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.TickRateDescription,
+                    Caption = EditorSetupStrings.TickRate,
+                    HintText = EditorSetupStrings.TickRateDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate)
                     {
                         Default = 1,
                         MinValue = 1,
                         MaxValue = 4,
                         Precision = 1,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
             };
 
diff --git a/osu.Game.Rulesets.Osu/Edit/Setup/OsuDifficultySection.cs b/osu.Game.Rulesets.Osu/Edit/Setup/OsuDifficultySection.cs
index b61faa0ae9..7008c87d41 100644
--- a/osu.Game.Rulesets.Osu/Edit/Setup/OsuDifficultySection.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Setup/OsuDifficultySection.cs
@@ -16,13 +16,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Setup
 {
     public partial class OsuDifficultySection : SetupSection
     {
-        private LabelledSliderBar<float> circleSizeSlider { get; set; } = null!;
-        private LabelledSliderBar<float> healthDrainSlider { get; set; } = null!;
-        private LabelledSliderBar<float> approachRateSlider { get; set; } = null!;
-        private LabelledSliderBar<float> overallDifficultySlider { get; set; } = null!;
-        private LabelledSliderBar<double> baseVelocitySlider { get; set; } = null!;
-        private LabelledSliderBar<double> tickRateSlider { get; set; } = null!;
-        private LabelledSliderBar<float> stackLeniency { get; set; } = null!;
+        private FormSliderBar<float> circleSizeSlider { get; set; } = null!;
+        private FormSliderBar<float> healthDrainSlider { get; set; } = null!;
+        private FormSliderBar<float> approachRateSlider { get; set; } = null!;
+        private FormSliderBar<float> overallDifficultySlider { get; set; } = null!;
+        private FormSliderBar<double> baseVelocitySlider { get; set; } = null!;
+        private FormSliderBar<double> tickRateSlider { get; set; } = null!;
+        private FormSliderBar<float> stackLeniency { get; set; } = null!;
 
         public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
 
@@ -31,103 +31,103 @@ namespace osu.Game.Rulesets.Osu.Edit.Setup
         {
             Children = new Drawable[]
             {
-                circleSizeSlider = new LabelledSliderBar<float>
+                circleSizeSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsCs,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.CircleSizeDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsCs,
+                    HintText = EditorSetupStrings.CircleSizeDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.CircleSize)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                healthDrainSlider = new LabelledSliderBar<float>
+                healthDrainSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsDrain,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.DrainRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsDrain,
+                    HintText = EditorSetupStrings.DrainRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.DrainRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                approachRateSlider = new LabelledSliderBar<float>
+                approachRateSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAr,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.ApproachRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAr,
+                    HintText = EditorSetupStrings.ApproachRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.ApproachRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                overallDifficultySlider = new LabelledSliderBar<float>
+                overallDifficultySlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAccuracy,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.OverallDifficultyDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAccuracy,
+                    HintText = EditorSetupStrings.OverallDifficultyDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.OverallDifficulty)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                baseVelocitySlider = new LabelledSliderBar<double>
+                baseVelocitySlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.BaseVelocity,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.BaseVelocityDescription,
+                    Caption = EditorSetupStrings.BaseVelocity,
+                    HintText = EditorSetupStrings.BaseVelocityDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier)
                     {
                         Default = 1.4,
                         MinValue = 0.4,
                         MaxValue = 3.6,
                         Precision = 0.01f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                tickRateSlider = new LabelledSliderBar<double>
+                tickRateSlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.TickRate,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.TickRateDescription,
+                    Caption = EditorSetupStrings.TickRate,
+                    HintText = EditorSetupStrings.TickRateDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate)
                     {
                         Default = 1,
                         MinValue = 1,
                         MaxValue = 4,
                         Precision = 1,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                stackLeniency = new LabelledSliderBar<float>
+                stackLeniency = new FormSliderBar<float>
                 {
-                    Label = "Stack Leniency",
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = "In play mode, osu! automatically stacks notes which occur at the same location. Increasing this value means it is more likely to snap notes of further time-distance.",
+                    Caption = "Stack Leniency",
+                    HintText = "In play mode, osu! automatically stacks notes which occur at the same location. Increasing this value means it is more likely to snap notes of further time-distance.",
                     Current = new BindableFloat(Beatmap.BeatmapInfo.StackLeniency)
                     {
                         Default = 0.7f,
                         MinValue = 0,
                         MaxValue = 1,
                         Precision = 0.1f
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
             };
 
-            foreach (var item in Children.OfType<LabelledSliderBar<float>>())
+            foreach (var item in Children.OfType<FormSliderBar<float>>())
                 item.Current.ValueChanged += _ => updateValues();
 
-            foreach (var item in Children.OfType<LabelledSliderBar<double>>())
+            foreach (var item in Children.OfType<FormSliderBar<double>>())
                 item.Current.ValueChanged += _ => updateValues();
         }
 
diff --git a/osu.Game.Rulesets.Taiko/Edit/Setup/TaikoDifficultySection.cs b/osu.Game.Rulesets.Taiko/Edit/Setup/TaikoDifficultySection.cs
index 2aaa16ee0b..e191169929 100644
--- a/osu.Game.Rulesets.Taiko/Edit/Setup/TaikoDifficultySection.cs
+++ b/osu.Game.Rulesets.Taiko/Edit/Setup/TaikoDifficultySection.cs
@@ -16,10 +16,10 @@ namespace osu.Game.Rulesets.Taiko.Edit.Setup
 {
     public partial class TaikoDifficultySection : SetupSection
     {
-        private LabelledSliderBar<float> healthDrainSlider { get; set; } = null!;
-        private LabelledSliderBar<float> overallDifficultySlider { get; set; } = null!;
-        private LabelledSliderBar<double> baseVelocitySlider { get; set; } = null!;
-        private LabelledSliderBar<double> tickRateSlider { get; set; } = null!;
+        private FormSliderBar<float> healthDrainSlider { get; set; } = null!;
+        private FormSliderBar<float> overallDifficultySlider { get; set; } = null!;
+        private FormSliderBar<double> baseVelocitySlider { get; set; } = null!;
+        private FormSliderBar<double> tickRateSlider { get; set; } = null!;
 
         public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
 
@@ -28,64 +28,64 @@ namespace osu.Game.Rulesets.Taiko.Edit.Setup
         {
             Children = new Drawable[]
             {
-                healthDrainSlider = new LabelledSliderBar<float>
+                healthDrainSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsDrain,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.DrainRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsDrain,
+                    HintText = EditorSetupStrings.DrainRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.DrainRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                overallDifficultySlider = new LabelledSliderBar<float>
+                overallDifficultySlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAccuracy,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.OverallDifficultyDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAccuracy,
+                    HintText = EditorSetupStrings.OverallDifficultyDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.OverallDifficulty)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                baseVelocitySlider = new LabelledSliderBar<double>
+                baseVelocitySlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.BaseVelocity,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.BaseVelocityDescription,
+                    Caption = EditorSetupStrings.BaseVelocity,
+                    HintText = EditorSetupStrings.BaseVelocityDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier)
                     {
                         Default = 1.4,
                         MinValue = 0.4,
                         MaxValue = 3.6,
                         Precision = 0.01f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                tickRateSlider = new LabelledSliderBar<double>
+                tickRateSlider = new FormSliderBar<double>()
                 {
-                    Label = EditorSetupStrings.TickRate,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.TickRateDescription,
+                    Caption = EditorSetupStrings.TickRate,
+                    HintText = EditorSetupStrings.TickRateDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate)
                     {
                         Default = 1,
                         MinValue = 1,
                         MaxValue = 4,
                         Precision = 1,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
             };
 
-            foreach (var item in Children.OfType<LabelledSliderBar<float>>())
+            foreach (var item in Children.OfType<FormSliderBar<float>>())
                 item.Current.ValueChanged += _ => updateValues();
 
-            foreach (var item in Children.OfType<LabelledSliderBar<double>>())
+            foreach (var item in Children.OfType<FormSliderBar<double>>())
                 item.Current.ValueChanged += _ => updateValues();
         }
 
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs
index 9a66e1676d..143547dfc9 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs
@@ -99,11 +99,11 @@ namespace osu.Game.Tests.Visual.Editing
 
         private partial class TestDesignSection : DesignSection
         {
-            public new LabelledSwitchButton EnableCountdown => base.EnableCountdown;
+            public new FormCheckBox EnableCountdown => base.EnableCountdown;
 
             public new FillFlowContainer CountdownSettings => base.CountdownSettings;
-            public new LabelledEnumDropdown<CountdownType> CountdownSpeed => base.CountdownSpeed;
-            public new LabelledNumberBox CountdownOffset => base.CountdownOffset;
+            public new FormEnumDropdown<CountdownType> CountdownSpeed => base.CountdownSpeed;
+            public new FormTextBox CountdownOffset => base.CountdownOffset;
         }
     }
 }
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs
index 8b6f31d599..653e3e7ff9 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs
@@ -212,7 +212,7 @@ namespace osu.Game.Tests.Visual.Editing
         private void assertRomanisedArtist(string expected, bool editable)
         {
             AddAssert($"romanised artist is {expected}", () => metadataSection.RomanisedArtistTextBox.Current.Value, () => Is.EqualTo(expected));
-            AddAssert($"romanised artist is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedArtistTextBox.ReadOnly == !editable);
+            AddAssert($"romanised artist is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedArtistTextBox.Current.Disabled == !editable);
         }
 
         private void assertTitle(string expected)
@@ -221,16 +221,16 @@ namespace osu.Game.Tests.Visual.Editing
         private void assertRomanisedTitle(string expected, bool editable)
         {
             AddAssert($"romanised title is {expected}", () => metadataSection.RomanisedTitleTextBox.Current.Value, () => Is.EqualTo(expected));
-            AddAssert($"romanised title is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedTitleTextBox.ReadOnly == !editable);
+            AddAssert($"romanised title is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedTitleTextBox.Current.Disabled == !editable);
         }
 
         private partial class TestMetadataSection : MetadataSection
         {
-            public new LabelledTextBox ArtistTextBox => base.ArtistTextBox;
-            public new LabelledTextBox RomanisedArtistTextBox => base.RomanisedArtistTextBox;
+            public new FormTextBox ArtistTextBox => base.ArtistTextBox;
+            public new FormTextBox RomanisedArtistTextBox => base.RomanisedArtistTextBox;
 
-            public new LabelledTextBox TitleTextBox => base.TitleTextBox;
-            public new LabelledTextBox RomanisedTitleTextBox => base.RomanisedTitleTextBox;
+            public new FormTextBox TitleTextBox => base.TitleTextBox;
+            public new FormTextBox RomanisedTitleTextBox => base.RomanisedTitleTextBox;
         }
     }
 }
diff --git a/osu.Game/Graphics/UserInterfaceV2/FormColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/FormColourPalette.cs
index a2c1c1622e..672df1d0a5 100644
--- a/osu.Game/Graphics/UserInterfaceV2/FormColourPalette.cs
+++ b/osu.Game/Graphics/UserInterfaceV2/FormColourPalette.cs
@@ -133,7 +133,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
                 int colourIndex = i;
                 var colourButton = new ColourButton { Current = { Value = Colours[colourIndex] } };
                 colourButton.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue);
-                colourButton.DeleteRequested = () => Colours.RemoveAt(flow.IndexOf(colourButton));
+                colourButton.DeleteRequested = () => Colours.RemoveAt(colourIndex);
                 flow.Add(colourButton);
             }
         }
diff --git a/osu.Game/Graphics/UserInterfaceV2/FormFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/FormFileSelector.cs
index 42bf9c7b9f..f5b6cb3e64 100644
--- a/osu.Game/Graphics/UserInterfaceV2/FormFileSelector.cs
+++ b/osu.Game/Graphics/UserInterfaceV2/FormFileSelector.cs
@@ -148,12 +148,12 @@ namespace osu.Game.Graphics.UserInterfaceV2
             base.LoadComplete();
 
             popoverState.BindValueChanged(_ => updateState());
+            current.BindDisabledChanged(_ => updateState());
             current.BindValueChanged(_ =>
             {
                 updateState();
                 onFileSelected();
-            });
-            current.BindDisabledChanged(_ => updateState(), true);
+            }, true);
             game.RegisterImportHandler(this);
         }
 
@@ -189,7 +189,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
         private void updateState()
         {
             caption.Colour = Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content2;
-            filenameText.Colour = Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
+            filenameText.Colour = Current.Disabled || Current.Value == null ? colourProvider.Foreground1 : colourProvider.Content1;
 
             if (!Current.Disabled)
             {
diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs
index a5d79b5b52..01ca114e4f 100644
--- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs
+++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs
@@ -13,18 +13,16 @@ namespace osu.Game.Screens.Edit.Setup
     {
         public override LocalisableString Title => EditorSetupStrings.ColoursHeader;
 
-        private LabelledColourPalette comboColours = null!;
+        private FormColourPalette comboColours = null!;
 
         [BackgroundDependencyLoader]
         private void load()
         {
             Children = new Drawable[]
             {
-                comboColours = new LabelledColourPalette
+                comboColours = new FormColourPalette
                 {
-                    Label = EditorSetupStrings.HitCircleSliderCombos,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    ColourNamePrefix = EditorSetupStrings.ComboColourPrefix
+                    Caption = EditorSetupStrings.HitCircleSliderCombos,
                 }
             };
 
diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs
index b05a073146..e3c01fc9bf 100644
--- a/osu.Game/Screens/Edit/Setup/DesignSection.cs
+++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs
@@ -17,75 +17,75 @@ namespace osu.Game.Screens.Edit.Setup
 {
     internal partial class DesignSection : SetupSection
     {
-        protected LabelledSwitchButton EnableCountdown = null!;
+        protected FormCheckBox EnableCountdown = null!;
 
         protected FillFlowContainer CountdownSettings = null!;
-        protected LabelledEnumDropdown<CountdownType> CountdownSpeed = null!;
-        protected LabelledNumberBox CountdownOffset = null!;
+        protected FormEnumDropdown<CountdownType> CountdownSpeed = null!;
+        protected FormNumberBox CountdownOffset = null!;
 
-        private LabelledSwitchButton widescreenSupport = null!;
-        private LabelledSwitchButton epilepsyWarning = null!;
-        private LabelledSwitchButton letterboxDuringBreaks = null!;
-        private LabelledSwitchButton samplesMatchPlaybackRate = null!;
+        private FormCheckBox widescreenSupport = null!;
+        private FormCheckBox epilepsyWarning = null!;
+        private FormCheckBox letterboxDuringBreaks = null!;
+        private FormCheckBox samplesMatchPlaybackRate = null!;
 
         public override LocalisableString Title => EditorSetupStrings.DesignHeader;
 
         [BackgroundDependencyLoader]
         private void load()
         {
-            Children = new[]
+            Children = new Drawable[]
             {
-                EnableCountdown = new LabelledSwitchButton
+                EnableCountdown = new FormCheckBox
                 {
-                    Label = EditorSetupStrings.EnableCountdown,
+                    Caption = EditorSetupStrings.EnableCountdown,
+                    HintText = EditorSetupStrings.CountdownDescription,
                     Current = { Value = Beatmap.BeatmapInfo.Countdown != CountdownType.None },
-                    Description = EditorSetupStrings.CountdownDescription
                 },
                 CountdownSettings = new FillFlowContainer
                 {
                     RelativeSizeAxes = Axes.X,
                     AutoSizeAxes = Axes.Y,
-                    Spacing = new Vector2(10),
+                    Spacing = new Vector2(5),
                     Direction = FillDirection.Vertical,
                     Children = new Drawable[]
                     {
-                        CountdownSpeed = new LabelledEnumDropdown<CountdownType>
+                        CountdownSpeed = new FormEnumDropdown<CountdownType>
                         {
-                            Label = EditorSetupStrings.CountdownSpeed,
+                            Caption = EditorSetupStrings.CountdownSpeed,
                             Current = { Value = Beatmap.BeatmapInfo.Countdown != CountdownType.None ? Beatmap.BeatmapInfo.Countdown : CountdownType.Normal },
                             Items = Enum.GetValues<CountdownType>().Where(type => type != CountdownType.None)
                         },
-                        CountdownOffset = new LabelledNumberBox
+                        CountdownOffset = new FormNumberBox
                         {
-                            Label = EditorSetupStrings.CountdownOffset,
+                            Caption = EditorSetupStrings.CountdownOffset,
+                            HintText = EditorSetupStrings.CountdownOffsetDescription,
                             Current = { Value = Beatmap.BeatmapInfo.CountdownOffset.ToString() },
-                            Description = EditorSetupStrings.CountdownOffsetDescription,
+                            TabbableContentContainer = this,
                         }
                     }
                 },
-                Empty(),
-                widescreenSupport = new LabelledSwitchButton
+                widescreenSupport = new FormCheckBox
                 {
-                    Label = EditorSetupStrings.WidescreenSupport,
-                    Description = EditorSetupStrings.WidescreenSupportDescription,
+                    Caption = EditorSetupStrings.WidescreenSupport,
+                    HintText = EditorSetupStrings.WidescreenSupportDescription,
                     Current = { Value = Beatmap.BeatmapInfo.WidescreenStoryboard }
                 },
-                epilepsyWarning = new LabelledSwitchButton
+                epilepsyWarning = new FormCheckBox
                 {
-                    Label = EditorSetupStrings.EpilepsyWarning,
-                    Description = EditorSetupStrings.EpilepsyWarningDescription,
+                    Caption = EditorSetupStrings.EpilepsyWarning,
+                    HintText = EditorSetupStrings.EpilepsyWarningDescription,
                     Current = { Value = Beatmap.BeatmapInfo.EpilepsyWarning }
                 },
-                letterboxDuringBreaks = new LabelledSwitchButton
+                letterboxDuringBreaks = new FormCheckBox
                 {
-                    Label = EditorSetupStrings.LetterboxDuringBreaks,
-                    Description = EditorSetupStrings.LetterboxDuringBreaksDescription,
+                    Caption = EditorSetupStrings.LetterboxDuringBreaks,
+                    HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
                     Current = { Value = Beatmap.BeatmapInfo.LetterboxInBreaks }
                 },
-                samplesMatchPlaybackRate = new LabelledSwitchButton
+                samplesMatchPlaybackRate = new FormCheckBox
                 {
-                    Label = EditorSetupStrings.SamplesMatchPlaybackRate,
-                    Description = EditorSetupStrings.SamplesMatchPlaybackRateDescription,
+                    Caption = EditorSetupStrings.SamplesMatchPlaybackRate,
+                    HintText = EditorSetupStrings.SamplesMatchPlaybackRateDescription,
                     Current = { Value = Beatmap.BeatmapInfo.SamplesMatchPlaybackRate }
                 }
             };
diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
index b9ba2d9cb7..a27a7258c7 100644
--- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs
+++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
@@ -15,12 +15,12 @@ namespace osu.Game.Screens.Edit.Setup
 {
     public partial class DifficultySection : SetupSection
     {
-        private LabelledSliderBar<float> circleSizeSlider { get; set; } = null!;
-        private LabelledSliderBar<float> healthDrainSlider { get; set; } = null!;
-        private LabelledSliderBar<float> approachRateSlider { get; set; } = null!;
-        private LabelledSliderBar<float> overallDifficultySlider { get; set; } = null!;
-        private LabelledSliderBar<double> baseVelocitySlider { get; set; } = null!;
-        private LabelledSliderBar<double> tickRateSlider { get; set; } = null!;
+        private FormSliderBar<float> circleSizeSlider { get; set; } = null!;
+        private FormSliderBar<float> healthDrainSlider { get; set; } = null!;
+        private FormSliderBar<float> approachRateSlider { get; set; } = null!;
+        private FormSliderBar<float> overallDifficultySlider { get; set; } = null!;
+        private FormSliderBar<double> baseVelocitySlider { get; set; } = null!;
+        private FormSliderBar<double> tickRateSlider { get; set; } = null!;
 
         public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
 
@@ -29,90 +29,90 @@ namespace osu.Game.Screens.Edit.Setup
         {
             Children = new Drawable[]
             {
-                circleSizeSlider = new LabelledSliderBar<float>
+                circleSizeSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsCs,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.CircleSizeDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsCs,
+                    HintText = EditorSetupStrings.CircleSizeDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.CircleSize)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                healthDrainSlider = new LabelledSliderBar<float>
+                healthDrainSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsDrain,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.DrainRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsDrain,
+                    HintText = EditorSetupStrings.DrainRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.DrainRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                approachRateSlider = new LabelledSliderBar<float>
+                approachRateSlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAr,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.ApproachRateDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAr,
+                    HintText = EditorSetupStrings.ApproachRateDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.ApproachRate)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                overallDifficultySlider = new LabelledSliderBar<float>
+                overallDifficultySlider = new FormSliderBar<float>
                 {
-                    Label = BeatmapsetsStrings.ShowStatsAccuracy,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.OverallDifficultyDescription,
+                    Caption = BeatmapsetsStrings.ShowStatsAccuracy,
+                    HintText = EditorSetupStrings.OverallDifficultyDescription,
                     Current = new BindableFloat(Beatmap.Difficulty.OverallDifficulty)
                     {
                         Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
                         MinValue = 0,
                         MaxValue = 10,
                         Precision = 0.1f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                baseVelocitySlider = new LabelledSliderBar<double>
+                baseVelocitySlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.BaseVelocity,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.BaseVelocityDescription,
+                    Caption = EditorSetupStrings.BaseVelocity,
+                    HintText = EditorSetupStrings.BaseVelocityDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier)
                     {
                         Default = 1.4,
                         MinValue = 0.4,
                         MaxValue = 3.6,
                         Precision = 0.01f,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
-                tickRateSlider = new LabelledSliderBar<double>
+                tickRateSlider = new FormSliderBar<double>
                 {
-                    Label = EditorSetupStrings.TickRate,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    Description = EditorSetupStrings.TickRateDescription,
+                    Caption = EditorSetupStrings.TickRate,
+                    HintText = EditorSetupStrings.TickRateDescription,
                     Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate)
                     {
                         Default = 1,
                         MinValue = 1,
                         MaxValue = 4,
                         Precision = 1,
-                    }
+                    },
+                    TabbableContentContainer = this,
                 },
             };
 
-            foreach (var item in Children.OfType<LabelledSliderBar<float>>())
+            foreach (var item in Children.OfType<FormSliderBar<float>>())
                 item.Current.ValueChanged += _ => updateValues();
 
-            foreach (var item in Children.OfType<LabelledSliderBar<double>>())
+            foreach (var item in Children.OfType<FormSliderBar<double>>())
                 item.Current.ValueChanged += _ => updateValues();
         }
 
diff --git a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs b/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs
deleted file mode 100644
index 85c697bf14..0000000000
--- a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using osu.Game.Beatmaps;
-using osu.Game.Graphics.UserInterface;
-using osu.Game.Graphics.UserInterfaceV2;
-
-namespace osu.Game.Screens.Edit.Setup
-{
-    internal partial class LabelledRomanisedTextBox : LabelledTextBox
-    {
-        protected override OsuTextBox CreateTextBox() => new RomanisedTextBox();
-
-        private partial class RomanisedTextBox : OsuTextBox
-        {
-            protected override bool AllowIme => false;
-
-            protected override bool CanAddCharacter(char character)
-                => MetadataUtils.IsRomanised(character);
-        }
-    }
-}
diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs
index 19071dc806..20c0a74d84 100644
--- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs
+++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs
@@ -14,16 +14,16 @@ namespace osu.Game.Screens.Edit.Setup
 {
     public partial class MetadataSection : SetupSection
     {
-        protected LabelledTextBox ArtistTextBox = null!;
-        protected LabelledTextBox RomanisedArtistTextBox = null!;
+        protected FormTextBox ArtistTextBox = null!;
+        protected FormTextBox RomanisedArtistTextBox = null!;
 
-        protected LabelledTextBox TitleTextBox = null!;
-        protected LabelledTextBox RomanisedTitleTextBox = null!;
+        protected FormTextBox TitleTextBox = null!;
+        protected FormTextBox RomanisedTitleTextBox = null!;
 
-        private LabelledTextBox creatorTextBox = null!;
-        private LabelledTextBox difficultyTextBox = null!;
-        private LabelledTextBox sourceTextBox = null!;
-        private LabelledTextBox tagsTextBox = null!;
+        private FormTextBox creatorTextBox = null!;
+        private FormTextBox difficultyTextBox = null!;
+        private FormTextBox sourceTextBox = null!;
+        private FormTextBox tagsTextBox = null!;
 
         public override LocalisableString Title => EditorSetupStrings.MetadataHeader;
 
@@ -34,33 +34,26 @@ namespace osu.Game.Screens.Edit.Setup
 
             Children = new[]
             {
-                ArtistTextBox = createTextBox<LabelledTextBox>(EditorSetupStrings.Artist,
+                ArtistTextBox = createTextBox<FormTextBox>(EditorSetupStrings.Artist,
                     !string.IsNullOrEmpty(metadata.ArtistUnicode) ? metadata.ArtistUnicode : metadata.Artist),
-                RomanisedArtistTextBox = createTextBox<LabelledRomanisedTextBox>(EditorSetupStrings.RomanisedArtist,
+                RomanisedArtistTextBox = createTextBox<FormRomanisedTextBox>(EditorSetupStrings.RomanisedArtist,
                     !string.IsNullOrEmpty(metadata.Artist) ? metadata.Artist : MetadataUtils.StripNonRomanisedCharacters(metadata.ArtistUnicode)),
-
-                Empty(),
-
-                TitleTextBox = createTextBox<LabelledTextBox>(EditorSetupStrings.Title,
+                TitleTextBox = createTextBox<FormTextBox>(EditorSetupStrings.Title,
                     !string.IsNullOrEmpty(metadata.TitleUnicode) ? metadata.TitleUnicode : metadata.Title),
-                RomanisedTitleTextBox = createTextBox<LabelledRomanisedTextBox>(EditorSetupStrings.RomanisedTitle,
+                RomanisedTitleTextBox = createTextBox<FormRomanisedTextBox>(EditorSetupStrings.RomanisedTitle,
                     !string.IsNullOrEmpty(metadata.Title) ? metadata.Title : MetadataUtils.StripNonRomanisedCharacters(metadata.ArtistUnicode)),
-
-                Empty(),
-
-                creatorTextBox = createTextBox<LabelledTextBox>(EditorSetupStrings.Creator, metadata.Author.Username),
-                difficultyTextBox = createTextBox<LabelledTextBox>(EditorSetupStrings.DifficultyName, Beatmap.BeatmapInfo.DifficultyName),
-                sourceTextBox = createTextBox<LabelledTextBox>(BeatmapsetsStrings.ShowInfoSource, metadata.Source),
-                tagsTextBox = createTextBox<LabelledTextBox>(BeatmapsetsStrings.ShowInfoTags, metadata.Tags)
+                creatorTextBox = createTextBox<FormTextBox>(EditorSetupStrings.Creator, metadata.Author.Username),
+                difficultyTextBox = createTextBox<FormTextBox>(EditorSetupStrings.DifficultyName, Beatmap.BeatmapInfo.DifficultyName),
+                sourceTextBox = createTextBox<FormTextBox>(BeatmapsetsStrings.ShowInfoSource, metadata.Source),
+                tagsTextBox = createTextBox<FormTextBox>(BeatmapsetsStrings.ShowInfoTags, metadata.Tags)
             };
         }
 
         private TTextBox createTextBox<TTextBox>(LocalisableString label, string initialValue)
-            where TTextBox : LabelledTextBox, new()
+            where TTextBox : FormTextBox, new()
             => new TTextBox
             {
-                Label = label,
-                FixedLabelWidth = LABEL_WIDTH,
+                Caption = label,
                 Current = { Value = initialValue },
                 TabbableContentContainer = this
             };
@@ -75,13 +68,13 @@ namespace osu.Game.Screens.Edit.Setup
             ArtistTextBox.Current.BindValueChanged(artist => transferIfRomanised(artist.NewValue, RomanisedArtistTextBox));
             TitleTextBox.Current.BindValueChanged(title => transferIfRomanised(title.NewValue, RomanisedTitleTextBox));
 
-            foreach (var item in Children.OfType<LabelledTextBox>())
+            foreach (var item in Children.OfType<FormTextBox>())
                 item.OnCommit += onCommit;
 
             updateReadOnlyState();
         }
 
-        private void transferIfRomanised(string value, LabelledTextBox target)
+        private void transferIfRomanised(string value, FormTextBox target)
         {
             if (MetadataUtils.IsRomanised(value))
                 target.Current.Value = value;
@@ -119,5 +112,18 @@ namespace osu.Game.Screens.Edit.Setup
 
             Beatmap.SaveState();
         }
+
+        private partial class FormRomanisedTextBox : FormTextBox
+        {
+            internal override InnerTextBox CreateTextBox() => new RomanisedTextBox();
+
+            private partial class RomanisedTextBox : InnerTextBox
+            {
+                protected override bool AllowIme => false;
+
+                protected override bool CanAddCharacter(char character)
+                    => MetadataUtils.IsRomanised(character);
+            }
+        }
     }
 }
diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
index f6d20319cb..3ce9f01b2b 100644
--- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
+++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
@@ -7,6 +7,7 @@ using osu.Framework.Bindables;
 using osu.Framework.Graphics;
 using osu.Framework.Localisation;
 using osu.Game.Beatmaps;
+using osu.Game.Graphics.UserInterfaceV2;
 using osu.Game.Overlays;
 using osu.Game.Localisation;
 
@@ -14,8 +15,8 @@ namespace osu.Game.Screens.Edit.Setup
 {
     internal partial class ResourcesSection : SetupSection
     {
-        private LabelledFileChooser audioTrackChooser = null!;
-        private LabelledFileChooser backgroundChooser = null!;
+        private FormFileSelector audioTrackChooser = null!;
+        private FormFileSelector backgroundChooser = null!;
 
         public override LocalisableString Title => EditorSetupStrings.ResourcesHeader;
 
@@ -35,24 +36,22 @@ namespace osu.Game.Screens.Edit.Setup
         private Editor? editor { get; set; }
 
         [Resolved]
-        private SetupScreenHeader header { get; set; } = null!;
+        private SetupScreenHeaderBackground headerBackground { get; set; } = null!;
 
         [BackgroundDependencyLoader]
         private void load()
         {
             Children = new Drawable[]
             {
-                backgroundChooser = new LabelledFileChooser(".jpg", ".jpeg", ".png")
+                backgroundChooser = new FormFileSelector(".jpg", ".jpeg", ".png")
                 {
-                    Label = GameplaySettingsStrings.BackgroundHeader,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    TabbableContentContainer = this
+                    Caption = GameplaySettingsStrings.BackgroundHeader,
+                    PlaceholderText = EditorSetupStrings.ClickToSelectBackground,
                 },
-                audioTrackChooser = new LabelledFileChooser(".mp3", ".ogg")
+                audioTrackChooser = new FormFileSelector(".mp3", ".ogg")
                 {
-                    Label = EditorSetupStrings.AudioTrack,
-                    FixedLabelWidth = LABEL_WIDTH,
-                    TabbableContentContainer = this
+                    Caption = EditorSetupStrings.AudioTrack,
+                    PlaceholderText = EditorSetupStrings.ClickToSelectTrack,
                 },
             };
 
@@ -64,8 +63,6 @@ namespace osu.Game.Screens.Edit.Setup
 
             backgroundChooser.Current.BindValueChanged(backgroundChanged);
             audioTrackChooser.Current.BindValueChanged(audioTrackChanged);
-
-            updatePlaceholderText();
         }
 
         public bool ChangeBackgroundImage(FileInfo source)
@@ -92,7 +89,7 @@ namespace osu.Game.Screens.Edit.Setup
             editorBeatmap.SaveState();
 
             working.Value.Metadata.BackgroundFile = destination.Name;
-            header.Background.UpdateBackground();
+            headerBackground.UpdateBackground();
 
             editor?.ApplyToBackground(bg => bg.RefreshBackground());
 
@@ -132,22 +129,12 @@ namespace osu.Game.Screens.Edit.Setup
         {
             if (file.NewValue == null || !ChangeBackgroundImage(file.NewValue))
                 backgroundChooser.Current.Value = file.OldValue;
-
-            updatePlaceholderText();
         }
 
         private void audioTrackChanged(ValueChangedEvent<FileInfo?> file)
         {
             if (file.NewValue == null || !ChangeAudioTrack(file.NewValue))
                 audioTrackChooser.Current.Value = file.OldValue;
-
-            updatePlaceholderText();
-        }
-
-        private void updatePlaceholderText()
-        {
-            audioTrackChooser.Text = audioTrackChooser.Current.Value?.Name ?? EditorSetupStrings.ClickToSelectTrack;
-            backgroundChooser.Text = backgroundChooser.Current.Value?.Name ?? EditorSetupStrings.ClickToSelectBackground;
         }
     }
 }
diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
index 17bbc7daa2..4b9a7a858f 100644
--- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs
+++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
@@ -1,55 +1,97 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.
 
-using System.Collections.Generic;
+using System.Linq;
 using osu.Framework.Allocation;
 using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Screens;
 using osu.Game.Graphics.Containers;
 using osu.Game.Overlays;
+using osuTK;
 
 namespace osu.Game.Screens.Edit.Setup
 {
     public partial class SetupScreen : EditorScreen
     {
-        [Cached]
-        private SectionsContainer<SetupSection> sections { get; } = new SetupScreenSectionsContainer();
-
-        [Cached]
-        private SetupScreenHeader header = new SetupScreenHeader();
-
         public SetupScreen()
             : base(EditorScreenMode.SongSetup)
         {
         }
 
+        [Cached]
+        private SetupScreenHeaderBackground background = new SetupScreenHeaderBackground { RelativeSizeAxes = Axes.Both, };
+
         [BackgroundDependencyLoader]
         private void load(EditorBeatmap beatmap, OverlayColourProvider colourProvider)
         {
             var ruleset = beatmap.BeatmapInfo.Ruleset.CreateInstance();
 
-            List<SetupSection> sectionsEnumerable =
-            [
-                new ResourcesSection(),
-                new MetadataSection()
-            ];
-
-            sectionsEnumerable.AddRange(ruleset.CreateEditorSetupSections());
-            sectionsEnumerable.Add(new DesignSection());
-
-            Add(new Box
+            Children = new Drawable[]
             {
-                Colour = colourProvider.Background3,
-                RelativeSizeAxes = Axes.Both,
-            });
-
-            Add(sections.With(s =>
-            {
-                s.RelativeSizeAxes = Axes.Both;
-                s.ChildrenEnumerable = sectionsEnumerable;
-                s.FixedHeader = header;
-            }));
+                new Box
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    Colour = colourProvider.Background3,
+                },
+                new GridContainer
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    RowDimensions =
+                    [
+                        new Dimension(GridSizeMode.Absolute, 110),
+                        new Dimension()
+                    ],
+                    Content = new[]
+                    {
+                        new Drawable[]
+                        {
+                            background,
+                        },
+                        new Drawable[]
+                        {
+                            new OsuScrollContainer
+                            {
+                                RelativeSizeAxes = Axes.Both,
+                                Padding = new MarginPadding(15),
+                                Child = new FillFlowContainer
+                                {
+                                    RelativeSizeAxes = Axes.X,
+                                    AutoSizeAxes = Axes.Y,
+                                    Direction = FillDirection.Full,
+                                    Spacing = new Vector2(28),
+                                    Children = new Drawable[]
+                                    {
+                                        new FillFlowContainer
+                                        {
+                                            Width = 450,
+                                            AutoSizeAxes = Axes.Y,
+                                            Anchor = Anchor.TopCentre,
+                                            Origin = Anchor.TopCentre,
+                                            Spacing = new Vector2(25),
+                                            Children = new Drawable[]
+                                            {
+                                                new ResourcesSection(),
+                                                new MetadataSection(),
+                                            }
+                                        },
+                                        new FillFlowContainer
+                                        {
+                                            Width = 450,
+                                            AutoSizeAxes = Axes.Y,
+                                            Anchor = Anchor.TopCentre,
+                                            Origin = Anchor.TopCentre,
+                                            Spacing = new Vector2(25),
+                                            ChildrenEnumerable = ruleset.CreateEditorSetupSections().Append(new DesignSection()),
+                                        },
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            };
         }
 
         public override void OnExiting(ScreenExitEvent e)
@@ -62,19 +104,5 @@ namespace osu.Game.Screens.Edit.Setup
             // (and potentially block the exit procedure for save).
             GetContainingFocusManager()?.TriggerFocusContention(this);
         }
-
-        private partial class SetupScreenSectionsContainer : SectionsContainer<SetupSection>
-        {
-            protected override UserTrackingScrollContainer CreateScrollContainer()
-            {
-                var scrollContainer = base.CreateScrollContainer();
-
-                // Workaround for masking issues (see https://github.com/ppy/osu-framework/issues/1675#issuecomment-910023157)
-                // Note that this actually causes the full scroll range to be reduced by 2px at the bottom, but it's not really noticeable.
-                scrollContainer.Margin = new MarginPadding { Top = 2 };
-
-                return scrollContainer;
-            }
-        }
     }
 }
diff --git a/osu.Game/Screens/Edit/Setup/SetupSection.cs b/osu.Game/Screens/Edit/Setup/SetupSection.cs
index 5f676798f1..d3b231de25 100644
--- a/osu.Game/Screens/Edit/Setup/SetupSection.cs
+++ b/osu.Game/Screens/Edit/Setup/SetupSection.cs
@@ -6,7 +6,7 @@ using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Localisation;
 using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
+using osu.Game.Graphics.UserInterface;
 using osu.Game.Graphics.UserInterfaceV2;
 using osuTK;
 
@@ -37,30 +37,23 @@ namespace osu.Game.Screens.Edit.Setup
             RelativeSizeAxes = Axes.X;
             AutoSizeAxes = Axes.Y;
 
-            Padding = new MarginPadding
-            {
-                Vertical = 10,
-                Horizontal = 100
-            };
-
             InternalChild = new FillFlowContainer
             {
                 RelativeSizeAxes = Axes.X,
                 AutoSizeAxes = Axes.Y,
-                Spacing = new Vector2(20),
+                Spacing = new Vector2(10),
                 Direction = FillDirection.Vertical,
                 Children = new Drawable[]
                 {
-                    new OsuSpriteText
+                    new SectionHeader(Title)
                     {
-                        Font = OsuFont.GetFont(weight: FontWeight.Bold),
-                        Text = Title
+                        Margin = new MarginPadding { Left = 9, },
                     },
                     flow = new FillFlowContainer
                     {
                         RelativeSizeAxes = Axes.X,
                         AutoSizeAxes = Axes.Y,
-                        Spacing = new Vector2(10),
+                        Spacing = new Vector2(5),
                         Direction = FillDirection.Vertical,
                     }
                 }