diff --git a/frontend/src/metabase/visualizations/components/ChartSettings.jsx b/frontend/src/metabase/visualizations/components/ChartSettings.jsx
index 2befb59091455c3069e536f2441e7fb7a9284a9b..bf9491543aa7ee3b4cc0d5a1fbf890d37c0da11e 100644
--- a/frontend/src/metabase/visualizations/components/ChartSettings.jsx
+++ b/frontend/src/metabase/visualizations/components/ChartSettings.jsx
@@ -25,6 +25,7 @@ import {
 
 import { getSettingDefintionsForColumn } from "metabase/visualizations/lib/settings/column";
 import ChartSettingsWidget from "./ChartSettingsWidget";
+import ChartSettingsWidgetList from "./ChartSettingsWidgetList";
 import ChartSettingsWidgetPopover from "./ChartSettingsWidgetPopover";
 import { SectionContainer, SectionWarnings } from "./ChartSettings.styled";
 
@@ -195,16 +196,8 @@ class ChartSettings extends Component {
   }
 
   render() {
-    const {
-      className,
-      question,
-      addField,
-      noPreview,
-      children,
-      setSidebarPropsOverride,
-      dashboard,
-      isDashboard,
-    } = this.props;
+    const { className, question, addField, noPreview, dashboard, isDashboard } =
+      this.props;
     const { currentWidget, popoverRef } = this.state;
 
     const settings = this._getSettings();
@@ -236,7 +229,6 @@ class ChartSettings extends Component {
       "data",
       "display",
       "axes",
-      "labels",
       // include all section names so any forgotten sections are sorted to the end
       ...sectionNames.map(x => x.toLowerCase()),
     ];
@@ -286,32 +278,11 @@ class ChartSettings extends Component {
       </SectionContainer>
     );
 
-    const widgetList = visibleWidgets.map(widget => (
-      <ChartSettingsWidget
-        key={widget.id}
-        {...widget}
-        {...extraWidgetProps}
-        setSidebarPropsOverride={setSidebarPropsOverride}
-      />
-    ));
-
     const onReset =
       !_.isEqual(settings, {}) && (settings || {}).virtual_card == null // resetting virtual cards wipes the text and broke the UI (metabase#14644)
         ? this.handleResetSettings
         : null;
 
-    // custom render prop layout:
-    if (children) {
-      return children({
-        sectionNames,
-        sectionPicker,
-        widgetList,
-        onDone: this.handleDone,
-        onCancel: this.handleCancel,
-        onReset: onReset,
-      });
-    }
-
     const showSectionPicker =
       // don't show section tabs for a single section
       sectionNames.length > 1 &&
@@ -337,7 +308,10 @@ class ChartSettings extends Component {
         )}
         {noPreview ? (
           <div className="full-height relative scroll-y scroll-show pt2 pb4">
-            {widgetList}
+            <ChartSettingsWidgetList
+              widgets={visibleWidgets}
+              extraWidgetProps={extraWidgetProps}
+            />
           </div>
         ) : (
           <div className="Grid flex-full">
@@ -345,7 +319,10 @@ class ChartSettings extends Component {
               className="Grid-cell Cell--1of3 scroll-y scroll-show border-right py4"
               data-testid="chartsettings-sidebar"
             >
-              {widgetList}
+              <ChartSettingsWidgetList
+                widgets={visibleWidgets}
+                extraWidgetProps={extraWidgetProps}
+              />
             </div>
             <div className="Grid-cell flex flex-column pt2">
               <div className="mx4 flex flex-column">
diff --git a/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.styled.tsx b/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..32dcb1b056b4e372abfb914e50632d9e9bd6f5f1
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.styled.tsx
@@ -0,0 +1,21 @@
+import styled from "@emotion/styled";
+
+import { color } from "metabase/lib/colors";
+
+import ChartSettingsWidget from "./ChartSettingsWidget";
+
+export const ChartSettingsWidgetListHeader = styled.h4`
+  margin-left: 2rem;
+  margin-bottom: 1rem;
+  color: ${color("bg-dark")};
+  text-transform: uppercase;
+`;
+
+export const ChartSettingsWidgetListDivider = styled.div`
+  background-color: ${color("border")};
+  height: 1px;
+  display: block;
+  margin-bottom: 1.5rem;
+  margin-left: 2rem;
+  margin-right: 2rem;
+`;
diff --git a/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.tsx b/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..8b152afebc9fdf6d05c0856e23e915a8ecb558bd
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/ChartSettingsWidgetList.tsx
@@ -0,0 +1,60 @@
+import React from "react";
+import _ from "underscore";
+import ChartSettingsWidget from "./ChartSettingsWidget";
+
+import {
+  ChartSettingsWidgetListHeader,
+  ChartSettingsWidgetListDivider,
+} from "./ChartSettingsWidgetList.styled";
+
+interface ChartSettingsWidgetListProps {
+  widgets: { id: string; group?: string }[];
+  extraWidgetProps: Record<string, unknown>;
+}
+
+const ChartSettingsWidgetList = ({
+  widgets,
+  extraWidgetProps,
+}: ChartSettingsWidgetListProps) => {
+  const widgetsAreGrouped = widgets.some(widget => widget.group);
+
+  if (!widgetsAreGrouped) {
+    return widgets.map(widget => (
+      <ChartSettingsWidget key={widget.id} {...widget} {...extraWidgetProps} />
+    ));
+  } else {
+    const groupedWidgets = widgets.reduce<Record<string, any[]>>(
+      (memo, widget) => {
+        const group = widget.group || "";
+        (memo[group] = memo[group] || []).push(widget);
+        return memo;
+      },
+      {},
+    );
+
+    return Object.keys(groupedWidgets).map((group, groupIndex, groups) => {
+      const lastGroup = groupIndex === groups.length - 1;
+      return (
+        <div key={`group-${groupIndex}`}>
+          {group && (
+            <ChartSettingsWidgetListHeader>
+              {group}
+            </ChartSettingsWidgetListHeader>
+          )}
+          <div>
+            {_.sortBy(groupedWidgets[group], "index").map(widget => (
+              <ChartSettingsWidget
+                key={widget.id}
+                {...widget}
+                {...extraWidgetProps}
+              />
+            ))}
+            {!lastGroup && <ChartSettingsWidgetListDivider />}
+          </div>
+        </div>
+      );
+    });
+  }
+};
+
+export default ChartSettingsWidgetList;
diff --git a/frontend/src/metabase/visualizations/lib/settings/graph.js b/frontend/src/metabase/visualizations/lib/settings/graph.js
index d8c6bc668c10537fc5733be35fb8084dc412ed6d..0d3c38707c3be00b396bbd7217493e9593aab2f5 100644
--- a/frontend/src/metabase/visualizations/lib/settings/graph.js
+++ b/frontend/src/metabase/visualizations/lib/settings/graph.js
@@ -479,7 +479,9 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.x_axis.scale": {
     section: t`Axes`,
-    title: t`X-axis scale`,
+    group: t`X-axis`,
+    title: t`Scale`,
+    index: 4,
     widget: "select",
     readDependencies: [
       "graph.x_axis._is_timeseries",
@@ -513,7 +515,9 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.y_axis.scale": {
     section: t`Axes`,
-    title: t`Y-axis scale`,
+    title: t`Scale`,
+    index: 7,
+    group: t`Y-axis`,
     widget: "select",
     default: "linear",
     getProps: (series, vizSettings) => ({
@@ -526,7 +530,9 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.x_axis.axis_enabled": {
     section: t`Axes`,
-    title: t`Show x-axis line and marks`,
+    group: t`X-axis`,
+    title: t`Show lines and marks`,
+    index: 3,
     widget: "select",
     props: {
       options: [
@@ -541,7 +547,9 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.y_axis.axis_enabled": {
     section: t`Axes`,
-    title: t`Show y-axis line and marks`,
+    title: t`Show lines and marks`,
+    index: 8,
+    group: t`Y-axis`,
     widget: "select",
     props: {
       options: [
@@ -553,12 +561,17 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.y_axis.auto_range": {
     section: t`Axes`,
+    group: t`Y-axis`,
+    index: 4,
     title: t`Auto y-axis range`,
+    inline: true,
     widget: "toggle",
     default: true,
   },
   "graph.y_axis.min": {
     section: t`Axes`,
+    group: t`Y-axis`,
+    index: 5,
     title: t`Min`,
     widget: "number",
     default: 0,
@@ -567,6 +580,8 @@ export const GRAPH_AXIS_SETTINGS = {
   },
   "graph.y_axis.max": {
     section: t`Axes`,
+    group: t`Y-axis`,
+    index: 6,
     title: t`Max`,
     widget: "number",
     default: 100,
@@ -597,35 +612,52 @@ export const GRAPH_AXIS_SETTINGS = {
 */
   "graph.y_axis.auto_split": {
     section: t`Axes`,
-    title: t`Use a split y-axis when necessary`,
+    group: t`Y-axis`,
+    index: 3,
+    title: t`Split y-axis when necessary`,
     widget: "toggle",
+    inline: true,
     default: true,
     getHidden: series => series.length < 2,
   },
   "graph.x_axis.labels_enabled": {
-    section: t`Labels`,
-    title: t`Show label on x-axis`,
+    section: t`Axes`,
+    group: t`X-axis`,
+    index: 1,
+    title: t`Show label`,
+    inline: true,
     widget: "toggle",
     default: true,
   },
   "graph.x_axis.title_text": {
-    section: t`Labels`,
-    title: t`X-axis label`,
+    section: t`Axes`,
+    title: t`Label`,
+    index: 2,
+    group: t`X-axis`,
     widget: "input",
     getHidden: (series, vizSettings) =>
       vizSettings["graph.x_axis.labels_enabled"] === false,
     getDefault: (series, vizSettings) =>
-      series.length === 1 ? getFriendlyName(series[0].data.cols[0]) : null,
+      series.length > 1 ? getFriendlyName(series[0].data.cols[0]) : null,
+    getProps: series => ({
+      placeholder:
+        series.length > 1 ? getFriendlyName(series[0].data.cols[0]) : null,
+    }),
   },
   "graph.y_axis.labels_enabled": {
-    section: t`Labels`,
-    title: t`Show label on y-axis`,
+    section: t`Axes`,
+    title: t`Show label`,
+    index: 1,
+    group: t`Y-axis`,
     widget: "toggle",
+    inline: true,
     default: true,
   },
   "graph.y_axis.title_text": {
-    section: t`Labels`,
-    title: t`Y-axis label`,
+    section: t`Axes`,
+    title: t`Label`,
+    index: 2,
+    group: t`Y-axis`,
     widget: "input",
     getHidden: (series, vizSettings) =>
       vizSettings["graph.y_axis.labels_enabled"] === false,