diff --git a/au4/src/appshell/qml/ProjectPage/ProjectPage.qml b/au4/src/appshell/qml/ProjectPage/ProjectPage.qml
index 1ee9c98c8cc56a1d56fe4bda39d3ba4c0d16c40f..637fc97b96c54176aea76174199ef15a031e4cd5 100644
--- a/au4/src/appshell/qml/ProjectPage/ProjectPage.qml
+++ b/au4/src/appshell/qml/ProjectPage/ProjectPage.qml
@@ -148,7 +148,6 @@ DockPage {
             ]
 
             PlaybackToolBar {
-                orientation: playbackToolBar.orientation
                 floating: playbackToolBar.floating
 
                 maximumWidth: playbackToolBar.width
diff --git a/au4/src/playback/CMakeLists.txt b/au4/src/playback/CMakeLists.txt
index fa21a273bc4644274fbb16254b4564f0a09dbeae..72dc27b16f76495852803944c49542c7875a2978 100644
--- a/au4/src/playback/CMakeLists.txt
+++ b/au4/src/playback/CMakeLists.txt
@@ -22,10 +22,15 @@ set(MODULE_SRC
 
     ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarmodel.cpp
     ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarmodel.h
-    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomisemodel.h
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarabstractitem.cpp
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarabstractitem.h
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarlevelitem.cpp
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarlevelitem.h
+
     ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomisemodel.cpp
-    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomiseitem.h
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomisemodel.h
     ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomiseitem.cpp
+    ${CMAKE_CURRENT_LIST_DIR}/view/toolbars/playbacktoolbarcustomiseitem.h
 
     )
 
diff --git a/au4/src/playback/internal/playbackcontroller.cpp b/au4/src/playback/internal/playbackcontroller.cpp
index 6a0ea48263052b385ba56752a534d06b0c51ef22..b32fedac43f0ef78aaee5cb0e436101193f3a188 100644
--- a/au4/src/playback/internal/playbackcontroller.cpp
+++ b/au4/src/playback/internal/playbackcontroller.cpp
@@ -13,7 +13,7 @@ using namespace muse::actions;
 
 static const ActionCode PLAY_CODE("play");
 static const ActionCode STOP_CODE("stop");
-static const ActionCode REWIND_CODE("rewind");
+static const ActionCode REWIND_START_CODE("rewind-start");
 static const ActionCode LOOP_CODE("loop");
 static const ActionCode LOOP_IN_CODE("loop-in");
 static const ActionCode LOOP_OUT_CODE("loop-out");
@@ -31,7 +31,7 @@ void PlaybackController::init()
 {
     dispatcher()->reg(this, PLAY_CODE, this, &PlaybackController::togglePlay);
     dispatcher()->reg(this, STOP_CODE, this, &PlaybackController::pause);
-    dispatcher()->reg(this, REWIND_CODE, this, &PlaybackController::rewind);
+    dispatcher()->reg(this, REWIND_START_CODE, this, &PlaybackController::rewindToStart);
     dispatcher()->reg(this, LOOP_CODE, this, &PlaybackController::toggleLoopPlayback);
     // dispatcher()->reg(this, LOOP_IN_CODE, [this]() { addLoopBoundary(LoopBoundaryType::LoopIn); });
     // dispatcher()->reg(this, LOOP_OUT_CODE, [this]() { addLoopBoundary(LoopBoundaryType::LoopOut); });
@@ -187,7 +187,7 @@ void PlaybackController::play()
     setCurrentPlaybackStatus(PlaybackStatus::Running);
 }
 
-void PlaybackController::rewind(const ActionData& args)
+void PlaybackController::rewindToStart(const ActionData& args)
 {
     //! NOTE: In Audacity 3 we can't rewind while playing
     stop();
diff --git a/au4/src/playback/internal/playbackcontroller.h b/au4/src/playback/internal/playbackcontroller.h
index c132abd12294cefa8fbbb5402256fb84c6792708..740b5612c2e40e4a0b2b1e2e294ed39e07e615e9 100644
--- a/au4/src/playback/internal/playbackcontroller.h
+++ b/au4/src/playback/internal/playbackcontroller.h
@@ -70,7 +70,7 @@ private:
     void seekRangeSelection();
 
     void togglePlay();
-    void rewind(const muse::actions::ActionData& args);
+    void rewindToStart(const muse::actions::ActionData& args);
     void play();
     void pause();
     void stop();
diff --git a/au4/src/playback/playbackmodule.cpp b/au4/src/playback/playbackmodule.cpp
index 1a0c12ae529fb513c9969e1d921e3ff71f875ec5..92f49c7ed164b5215a4caaf631449edc8eb86e01 100644
--- a/au4/src/playback/playbackmodule.cpp
+++ b/au4/src/playback/playbackmodule.cpp
@@ -14,6 +14,7 @@
 #include "internal/playbackuiactions.h"
 
 #include "view/toolbars/playbacktoolbarmodel.h"
+#include "view/toolbars/playbacktoolbarabstractitem.h"
 #include "view/toolbars/playbacktoolbarcustomisemodel.h"
 #include "view/toolbars/playbacktoolbarcustomiseitem.h"
 
@@ -58,6 +59,7 @@ void PlaybackModule::registerUiTypes()
 {
     // toolbars
     qmlRegisterType<PlaybackToolBarModel>("Audacity.Playback", 1, 0, "PlaybackToolBarModel");
+    qmlRegisterUncreatableType<PlaybackToolBarAbstractItem>("Muse.Ui", 1, 0, "PlaybackToolBarItem", "Cannot create an PlaybackToolBarItem");
     qmlRegisterType<PlaybackToolBarCustomiseModel>("Audacity.Playback", 1, 0, "PlaybackToolBarCustomiseModel");
     qmlRegisterUncreatableType<PlaybackToolBarCustomiseItem>("Audacity.Playback", 1, 0, "PlaybackToolBarCustomiseItem",
                                                              "Cannot create");
diff --git a/au4/src/playback/qml/Audacity/Playback/PlaybackToolBar.qml b/au4/src/playback/qml/Audacity/Playback/PlaybackToolBar.qml
index bebe85ddcd268c323611357148748da280e36466..fac3914e542f274a489b753494343a33ead714d8 100644
--- a/au4/src/playback/qml/Audacity/Playback/PlaybackToolBar.qml
+++ b/au4/src/playback/qml/Audacity/Playback/PlaybackToolBar.qml
@@ -13,15 +13,13 @@ import "internal"
 Item {
     id: root
 
-    property alias orientation: gridView.orientation
-
     property bool floating: false
 
     property int maximumWidth: 0
     property int maximumHeight: 0
 
-    width: gridView.isHorizontal ? childrenRect.width : 76
-    height: !gridView.isHorizontal ? childrenRect.height : 40
+    width: gridView.width + /*spacing*/ 4 + customizeButton.width
+    height: gridView.height
 
     property NavigationPanel navigationPanel: NavigationPanel {
         name: "PlaybackToolBar"
@@ -33,178 +31,202 @@ Item {
         id: toolbarModel
     }
 
-    QtObject {
-        id: prv
-
-        function resolveHorizontalGridViewWidth() {
-            if (root.floating) {
-                return gridView.contentWidth
-            }
-
-            var requiredFreeSpace = gridView.cellWidth * 3 + gridView.rowSpacing * 4
-
-            if (root.maximumWidth - gridView.contentWidth < requiredFreeSpace) {
-                return gridView.contentWidth - requiredFreeSpace
-            }
-
-            return gridView.contentWidth
-        }
-
-        function resolveVerticalGridViewHeight() {
-            if (root.floating) {
-                return gridView.contentHeight
-            }
-
-            var requiredFreeSpace = gridView.cellHeight * 3 + gridView.rowSpacing * 4
-
-            if (root.maximumHeight - gridView.contentHeight < requiredFreeSpace) {
-                return gridView.contentHeight - requiredFreeSpace
-            }
-
-            return gridView.contentHeight
-        }
-    }
-
     Component.onCompleted: {
         toolbarModel.load()
     }
 
-    GridViewSectional {
+    Flow {
         id: gridView
 
-        sectionRole: "section"
-
-        rowSpacing: 4
-        columnSpacing: 4
-
-        cellWidth: 32
-        cellHeight: cellWidth
-
         clip: true
 
-        model: toolbarModel
+        spacing: 4
 
-        sectionDelegate: SeparatorLine {
-            orientation: gridView.orientation
-            visible: itemIndex !== 0
-        }
-
-        itemDelegate: FlatButton {
-            id: btn
-
-            property var item: Boolean(itemModel) ? itemModel.itemRole : null
-            property var hasMenu: Boolean(item) && item.subitems.length !== 0
+        Repeater {
+            model: toolbarModel
 
-            width: gridView.cellWidth
-            height: gridView.cellWidth
+            Loader {
+                id: loader
 
-            accentButton: (Boolean(item) && item.checked) || menuLoader.isMenuOpened
-            transparent: !accentButton
+                property var itemData: Boolean(model) ? model.item : null
+                property var itemOrder: Boolean(model) ? model.order : 0
+                property var itemIsMenuSecondary: Boolean(model) ? model.isMenuSecondary : false
 
-            icon: Boolean(item) ? item.icon : IconCode.NONE
-            iconFont: ui.theme.toolbarIconsFont
-
-            toolTipTitle: Boolean(item) ? item.title : ""
-            toolTipDescription: Boolean(item) ? item.description : ""
-            toolTipShortcut: Boolean(item) ? item.shortcuts : ""
-
-            navigation.panel: root.navigationPanel
-            navigation.name: Boolean(item) ? item.id : ""
-            navigation.order: Boolean(itemModel) ? itemModel.order : 0
-            isClickOnKeyNavTriggered: false
-            navigation.onTriggered: {
-                if (menuLoader.isMenuOpened || hasMenu) {
-                    toggleMenuOpened()
-                } else {
-                    handleMenuItem()
-                }
-            }
-
-            mouseArea.acceptedButtons: hasMenu && itemModel.isMenuSecondary
-                                       ? Qt.LeftButton | Qt.RightButton
-                                       : Qt.LeftButton
-
-            function toggleMenuOpened() {
-                menuLoader.toggleOpened(item.subitems)
-            }
-
-            function handleMenuItem() {
-                Qt.callLater(toolbarModel.handleMenuItem, item.id)
-            }
+                property var itemSize: {
+                    if (!Boolean(loader.itemData)) {
+                        return null
+                    }
 
-            onClicked: function(mouse) {
-                if (menuLoader.isMenuOpened // If already menu open, close it
-                        || (hasMenu // Or if can open menu
-                            && (!itemModel.isMenuSecondary // And _should_ open menu
-                                || mouse.button === Qt.RightButton))) {
-                    toggleMenuOpened()
-                    return
-                }
+                    switch(loader.itemData.type) {
+                    case PlaybackToolBarItem.SECTION: return Qt.size(1, 32)
+                    case PlaybackToolBarItem.ACTION: return Qt.size(32, 32)
+                    case PlaybackToolBarItem.PLAYBACK_LEVEL: return Qt.size(128, 32)
+                    }
 
-                if (mouse.button === Qt.LeftButton) {
-                    handleMenuItem()
+                    return null
                 }
-            }
 
-            Connections {
-                target: btn.mouseArea
+                width: Boolean(item) ? item.width : 0
+                height: 32
 
-                // Make sure we only connect to `pressAndHold` if necessary
-                // See https://github.com/musescore/MuseScore/issues/16012
-                enabled: btn.hasMenu && !menuLoader.isMenuOpened
+                sourceComponent: {
+                    if (!Boolean(loader.itemData)) {
+                        return null
+                    }
 
-                function onPressAndHold() {
-                    if (menuLoader.isMenuOpened || !btn.hasMenu) {
-                        return
+                    switch(loader.itemData.type) {
+                    case PlaybackToolBarItem.SECTION: return sectionComp
+                    case PlaybackToolBarItem.ACTION: return actionComp
+                    case PlaybackToolBarItem.PLAYBACK_LEVEL: return playbackLevelComp
                     }
 
-                    btn.toggleMenuOpened()
+                    return null
                 }
-            }
 
-            Canvas {
-                visible: Boolean(itemModel) && itemModel.isMenuSecondary
+                Component {
+                    id: sectionComp
 
-                property color fillColor: ui.theme.fontPrimaryColor
-                onFillColorChanged: {
-                    requestPaint()
+                    SeparatorLine {
+                        orientation: Qt.Vertical
+                    }
                 }
 
-                width: 4
-                height: 4
-
-                anchors.margins: 2
-                anchors.right: parent.right
-                anchors.bottom: parent.bottom
-
-                onPaint: {
-                    const ctx = getContext("2d");
-                    ctx.fillStyle = fillColor;
-                    ctx.moveTo(width, 0);
-                    ctx.lineTo(width, height);
-                    ctx.lineTo(0, height);
-                    ctx.closePath();
-                    ctx.fill();
+                Component {
+                    id: actionComp
+
+                    FlatButton {
+                        id: btn
+
+                        property var item: loader.itemData
+                        property int order: loader.itemOrder
+                        property var isMenuSecondary: loader.itemIsMenuSecondary
+
+                        property var hasMenu: Boolean(item) && item.subitems.length !== 0
+
+                        width: 32
+                        height: width
+
+                        accentButton: item.checked || menuLoader.isMenuOpened
+                        transparent: !accentButton
+
+                        icon: item.icon
+                        iconFont: ui.theme.toolbarIconsFont
+
+                        toolTipTitle: item.title
+                        toolTipDescription: item.description
+                        toolTipShortcut: item.shortcuts
+
+                        navigation.panel: root.navigationPanel
+                        navigation.name: item.id
+                        navigation.order: order
+                        isClickOnKeyNavTriggered: false
+                        navigation.onTriggered: {
+                            if (menuLoader.isMenuOpened || hasMenu) {
+                                toggleMenuOpened()
+                            } else {
+                                handleMenuItem()
+                            }
+                        }
+
+                        mouseArea.acceptedButtons: hasMenu && isMenuSecondary
+                                                   ? Qt.LeftButton | Qt.RightButton
+                                                   : Qt.LeftButton
+
+                        function toggleMenuOpened() {
+                            menuLoader.toggleOpened(item.subitems)
+                        }
+
+                        function handleMenuItem() {
+                            Qt.callLater(toolbarModel.handleMenuItem, item.id)
+                        }
+
+                        onClicked: function(mouse) {
+                            if (menuLoader.isMenuOpened // If already menu open, close it
+                                    || (hasMenu // Or if can open menu
+                                        && (!isMenuSecondary // And _should_ open menu
+                                            || mouse.button === Qt.RightButton))) {
+                                toggleMenuOpened()
+                                return
+                            }
+
+                            if (mouse.button === Qt.LeftButton) {
+                                handleMenuItem()
+                            }
+                        }
+
+                        Connections {
+                            target: btn.mouseArea
+
+                            // Make sure we only connect to `pressAndHold` if necessary
+                            // See https://github.com/musescore/MuseScore/issues/16012
+                            enabled: btn.hasMenu && !menuLoader.isMenuOpened
+
+                            function onPressAndHold() {
+                                if (menuLoader.isMenuOpened || !btn.hasMenu) {
+                                    return
+                                }
+
+                                btn.toggleMenuOpened()
+                            }
+                        }
+
+                        Canvas {
+                            visible: isMenuSecondary
+
+                            property color fillColor: ui.theme.fontPrimaryColor
+                            onFillColorChanged: {
+                                requestPaint()
+                            }
+
+                            width: 4
+                            height: 4
+
+                            anchors.margins: 2
+                            anchors.right: parent.right
+                            anchors.bottom: parent.bottom
+
+                            onPaint: {
+                                const ctx = getContext("2d");
+                                ctx.fillStyle = fillColor;
+                                ctx.moveTo(width, 0);
+                                ctx.lineTo(width, height);
+                                ctx.lineTo(0, height);
+                                ctx.closePath();
+                                ctx.fill();
+                            }
+                        }
+
+                        StyledMenuLoader {
+                            id: menuLoader
+
+                            onHandleMenuItem: function(itemId) {
+                                toolbarModel.handleMenuItem(itemId)
+                            }
+                        }
+                    }
                 }
-            }
 
-            StyledMenuLoader {
-                id: menuLoader
+                Component {
+                    id: playbackLevelComp
 
-                onHandleMenuItem: function(itemId) {
-                    toolbarModel.handleMenuItem(itemId)
+                    PlaybackLevel {
+                        width: 128
+                    }
                 }
             }
         }
+
     }
 
     FlatButton {
         id: customizeButton
 
         anchors.margins: 4
+        anchors.left: gridView.right
+        anchors.verticalCenter: root.verticalCenter
 
-        width: gridView.cellWidth
-        height: gridView.cellHeight
+        width: 32
+        height: width
 
         icon: IconCode.SETTINGS_COG
         iconFont: ui.theme.toolbarIconsFont
@@ -226,45 +248,4 @@ Item {
             anchorItem: !root.floating ? ui.rootItem : null
         }
     }
-
-    states: [
-        State {
-            when: gridView.isHorizontal
-
-            PropertyChanges {
-                target: gridView
-                width: prv.resolveHorizontalGridViewWidth()
-                height: root.height
-                sectionWidth: 1
-                sectionHeight: root.height
-                rows: 1
-                columns: gridView.noLimit
-            }
-
-            AnchorChanges {
-                target: customizeButton
-                anchors.left: gridView.right
-                anchors.verticalCenter: root.verticalCenter
-            }
-        },
-        State {
-            when: !gridView.isHorizontal
-
-            PropertyChanges {
-                target: gridView
-                width: root.width
-                height: prv.resolveVerticalGridViewHeight()
-                sectionWidth: root.width
-                sectionHeight: 1
-                rows: gridView.noLimit
-                columns: 2
-            }
-
-            AnchorChanges {
-                target: customizeButton
-                anchors.top: gridView.bottom
-                anchors.right: parent.right
-            }
-        }
-    ]
 }
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.cpp b/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0981491528bee15f84da10bd8f4061989fbb3182
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.cpp
@@ -0,0 +1,32 @@
+/*
+* Audacity: A Digital Audio Editor
+*/
+#include "playbacktoolbarabstractitem.h"
+
+using namespace au::playback;
+using namespace muse::uicomponents;
+
+PlaybackToolBarAbstractItem::PlaybackToolBarAbstractItem(const muse::ui::UiAction& action, const ItemType& type, QObject* parent)
+    : muse::uicomponents::MenuItem(action, parent), m_type(type)
+{
+}
+
+PlaybackToolBarAbstractItem::ItemType PlaybackToolBarAbstractItem::type() const
+{
+    return m_type;
+}
+
+void PlaybackToolBarAbstractItem::setType(ItemType type)
+{
+    if (m_type == type) {
+        return;
+    }
+
+    m_type = type;
+    emit typeChanged();
+}
+
+int PlaybackToolBarAbstractItem::type_property() const
+{
+    return static_cast<int>(m_type);
+}
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.h b/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9e9dafb9016e7611f3e7efff5e1d3bb3bf0bfe6
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbarabstractitem.h
@@ -0,0 +1,42 @@
+/*
+* Audacity: A Digital Audio Editor
+*/
+#ifndef AU_PLAYBACK_PLAYBACKTOOLBARABSTRACTITEM_H
+#define AU_PLAYBACK_PLAYBACKTOOLBARABSTRACTITEM_H
+
+#include <QString>
+
+#include "uicomponents/view/menuitem.h"
+
+namespace au::playback {
+class PlaybackToolBarAbstractItem : public muse::uicomponents::MenuItem
+{
+    Q_OBJECT
+
+    Q_PROPERTY(int type READ type_property NOTIFY typeChanged FINAL)
+
+public:
+    enum ItemType {
+        UNDEFINED = -1,
+        SECTION,
+        ACTION,
+        PLAYBACK_LEVEL
+    };
+    Q_ENUM(ItemType)
+
+    explicit PlaybackToolBarAbstractItem(const muse::ui::UiAction& action, const ItemType& type, QObject* parent = nullptr);
+
+    ItemType type() const;
+    void setType(ItemType type);
+
+signals:
+    void typeChanged();
+
+private:
+    int type_property() const;
+
+    ItemType m_type = ItemType::UNDEFINED;
+};
+}
+
+#endif // AU_PLAYBACK_PLAYBACKTOOLBARABSTRACTITEM_H
diff --git a/au4/src/playback/view/toolbars/playbacktoolbaractionitem.cpp b/au4/src/playback/view/toolbars/playbacktoolbaractionitem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d379457a6a0363afe263f893b14a430c21431577
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbaractionitem.cpp
@@ -0,0 +1,72 @@
+/*
+* Audacity: A Digital Audio Editor
+*/
+#include "playbacktoolbarcustomiseitem.h"
+
+using namespace au::playback;
+using namespace muse::uicomponents;
+
+PlaybackToolBarCustomiseItem::PlaybackToolBarCustomiseItem(const ItemType& type, QObject* parent)
+    : SelectableItemListModel::Item(parent), m_type(type)
+{
+}
+
+QString PlaybackToolBarCustomiseItem::id() const
+{
+    return m_id;
+}
+
+QString PlaybackToolBarCustomiseItem::title() const
+{
+    return m_title;
+}
+
+PlaybackToolBarCustomiseItem::ItemType PlaybackToolBarCustomiseItem::type() const
+{
+    return m_type;
+}
+
+void PlaybackToolBarCustomiseItem::setTitle(QString title)
+{
+    if (m_title == title) {
+        return;
+    }
+
+    m_title = title;
+    emit titleChanged();
+}
+
+void PlaybackToolBarCustomiseItem::setId(const QString& id)
+{
+    m_id = id;
+}
+
+int PlaybackToolBarCustomiseItem::icon() const
+{
+    return static_cast<int>(m_icon);
+}
+
+bool PlaybackToolBarCustomiseItem::checked() const
+{
+    return m_checked;
+}
+
+void PlaybackToolBarCustomiseItem::setIcon(muse::ui::IconCode::Code icon)
+{
+    if (m_icon == icon) {
+        return;
+    }
+
+    m_icon = icon;
+    emit iconChanged();
+}
+
+void PlaybackToolBarCustomiseItem::setChecked(bool checked)
+{
+    if (m_checked == checked) {
+        return;
+    }
+
+    m_checked = checked;
+    emit checkedChanged(m_checked);
+}
diff --git a/au4/src/playback/view/toolbars/playbacktoolbaractionitem.h b/au4/src/playback/view/toolbars/playbacktoolbaractionitem.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7146785527e0de6dfbda7430d76d048e8f1f655
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbaractionitem.h
@@ -0,0 +1,60 @@
+/*
+* Audacity: A Digital Audio Editor
+*/
+#ifndef AU_PROJECTSCENE_PLAYBACKTOOLBARCUSTOMISEITEM_H
+#define AU_PROJECTSCENE_PLAYBACKTOOLBARCUSTOMISEITEM_H
+
+#include <QString>
+
+#include "ui/view/iconcodes.h"
+#include "uicomponents/view/selectableitemlistmodel.h"
+
+namespace au::playback {
+class PlaybackToolBarCustomiseItem : public muse::uicomponents::SelectableItemListModel::Item
+{
+    Q_OBJECT
+
+    Q_PROPERTY(ItemType type READ type CONSTANT)
+    Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
+    Q_PROPERTY(int icon READ icon NOTIFY iconChanged)
+    Q_PROPERTY(bool checked READ checked WRITE setChecked NOTIFY checkedChanged)
+
+public:
+    enum ItemType {
+        UNDEFINED = -1,
+        ACTION,
+        SEPARATOR
+    };
+    Q_ENUM(ItemType)
+
+    explicit PlaybackToolBarCustomiseItem(const ItemType& type, QObject* parent = nullptr);
+
+    ItemType type() const;
+    QString title() const;
+    int icon() const;
+    bool checked() const;
+
+    Q_INVOKABLE QString id() const;
+    void setId(const QString& id);
+
+public slots:
+    void setTitle(QString title);
+    void setIcon(muse::ui::IconCode::Code icon);
+    void setChecked(bool checked);
+
+signals:
+    void titleChanged();
+    void iconChanged();
+    void checkedChanged(bool checked);
+
+private:
+
+    QString m_id;
+    ItemType m_type = ItemType::UNDEFINED;
+    QString m_title;
+    muse::ui::IconCode::Code m_icon = muse::ui::IconCode::Code::NONE;
+    bool m_checked = false;
+};
+}
+
+#endif // AU_PROJECTSCENE_PLAYBACKTOOLBARCUSTOMISEITEM_H
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.cpp b/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ae7102a222dc351787ed08f8e1dcc6cf4df61d4
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.cpp
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2021 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "playbacktoolbarlevelitem.h"
+
+#include <QVariantMap>
+
+using namespace au::playback;
+
+PlaybackToolBarLevelItem::PlaybackToolBarLevelItem(const muse::ui::UiAction& action, const ItemType& type, QObject* parent)
+    : PlaybackToolBarAbstractItem(action, type, parent)
+{
+}
+
+int PlaybackToolBarLevelItem::level() const
+{
+    return m_level;
+}
+
+void PlaybackToolBarLevelItem::setLevel(int newLevel)
+{
+    if (m_level == newLevel) {
+        return;
+    }
+
+    m_level = newLevel;
+    emit levelChanged();
+}
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.h b/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.h
new file mode 100644
index 0000000000000000000000000000000000000000..8fe2453a809b7cd97963705985f7f4249b768f42
--- /dev/null
+++ b/au4/src/playback/view/toolbars/playbacktoolbarlevelitem.h
@@ -0,0 +1,32 @@
+/*
+* Audacity: A Digital Audio Editor
+*/
+#ifndef AU_PLAYBACK_PLAYBACKTOOLBARLEVELITEM_H
+#define AU_PLAYBACK_PLAYBACKTOOLBARLEVELITEM_H
+
+#include <QString>
+
+#include "playbacktoolbarabstractitem.h"
+
+namespace au::playback {
+class PlaybackToolBarLevelItem : public PlaybackToolBarAbstractItem
+{
+    Q_OBJECT
+
+    Q_PROPERTY(int level READ level WRITE setLevel NOTIFY levelChanged FINAL)
+
+public:
+    explicit PlaybackToolBarLevelItem(const muse::ui::UiAction& action, const ItemType& type, QObject* parent = nullptr);
+
+    int level() const;
+    void setLevel(int newLevel);
+
+signals:
+    void levelChanged();
+
+private:
+    int m_level = 0;
+};
+}
+
+#endif // AU_PLAYBACK_PLAYBACKTOOLBARLEVELITEM_H
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarmodel.cpp b/au4/src/playback/view/toolbars/playbacktoolbarmodel.cpp
index 8447a4430c53b7fdaea7742ed4f8b2db88348aba..a4a2d43383c78aaeb48d7dbfadb8e9b3fe4a1260 100644
--- a/au4/src/playback/view/toolbars/playbacktoolbarmodel.cpp
+++ b/au4/src/playback/view/toolbars/playbacktoolbarmodel.cpp
@@ -5,7 +5,7 @@
 
 #include "internal/playbackuiactions.h"
 
-#include "log.h"
+#include "view/toolbars/playbacktoolbarabstractitem.h"
 
 using namespace muse::uicomponents;
 using namespace muse::ui;
@@ -14,10 +14,29 @@ using namespace au::playback;
 
 static const QString TOOLBAR_NAME("playbackToolBar");
 
+static const ActionCode SECTION_CODE("");
 static const ActionCode PLAY_ACTION_CODE("play");
+static const ActionCode PLAYBACK_LEVEL("playback-level");
+
+static PlaybackToolBarAbstractItem::ItemType itemType(const ActionCode& actionCode)
+{
+    if (actionCode == SECTION_CODE) {
+        return PlaybackToolBarAbstractItem::ItemType::SECTION;
+    }
+
+    if (actionCode == PLAYBACK_LEVEL) {
+        return PlaybackToolBarAbstractItem::ItemType::PLAYBACK_LEVEL;
+    }
+
+    return PlaybackToolBarAbstractItem::ItemType::ACTION;
+}
 
 PlaybackToolBarModel::PlaybackToolBarModel(QObject* parent)
-    : AbstractMenuModel(parent)
+    : QAbstractListModel(parent)
+{
+}
+
+void PlaybackToolBarModel::load()
 {
     uiConfiguration()->toolConfigChanged(TOOLBAR_NAME).onNotify(this, [this]() {
         load();
@@ -26,37 +45,59 @@ PlaybackToolBarModel::PlaybackToolBarModel(QObject* parent)
     context()->currentProjectChanged().onNotify(this, [this]() {
         onProjectChanged();
     });
-}
 
-void PlaybackToolBarModel::load()
-{
-    AbstractMenuModel::load();
     updateActions();
     setupConnections();
 }
 
+void PlaybackToolBarModel::handleMenuItem(const QString& itemId)
+{
+    PlaybackToolBarAbstractItem* item = findItem(itemId.toStdString());
+    dispatcher()->dispatch(item->action().code, item->args());
+}
+
+QVariantMap PlaybackToolBarModel::get(int index)
+{
+    QVariantMap result;
+
+    QHash<int, QByteArray> names = roleNames();
+    QHashIterator<int, QByteArray> i(names);
+    while (i.hasNext()) {
+        i.next();
+        QModelIndex idx = this->index(index, 0);
+        QVariant data = idx.data(i.key());
+        result[i.value()] = data;
+    }
+
+    return result;
+}
+
 QVariant PlaybackToolBarModel::data(const QModelIndex& index, int role) const
 {
     TRACEFUNC;
 
     int row = index.row();
 
-    if (!isIndexValid(row)) {
+    if (!index.isValid() || row >= rowCount()) {
         return QVariant();
     }
 
-    const MenuItem* item = items()[row];
+    const PlaybackToolBarAbstractItem* item = m_items[row];
+    const ActionCode actionCode = item->action().code;
+
     switch (role) {
-    case IsMenuSecondaryRole: return isMenuSecondary(item->action().code);
+    case ItemRole: return QVariant::fromValue(item);
+    case IsMenuSecondaryRole: return isMenuSecondary(actionCode);
     case OrderRole: return row;
     case SectionRole: return item->section();
-    default: return AbstractMenuModel::data(index, role);
+    default: return QVariant();
     }
 }
 
 QHash<int, QByteArray> PlaybackToolBarModel::roleNames() const
 {
-    QHash<int, QByteArray> roles = AbstractMenuModel::roleNames();
+    QHash<int, QByteArray> roles;
+    roles[ItemRole] = "item";
     roles[IsMenuSecondaryRole] = "isMenuSecondary";
     roles[OrderRole] = "order";
     roles[SectionRole] = "section";
@@ -64,13 +105,27 @@ QHash<int, QByteArray> PlaybackToolBarModel::roleNames() const
     return roles;
 }
 
-void PlaybackToolBarModel::onActionsStateChanges(const muse::actions::ActionCodeList& codes)
+int PlaybackToolBarModel::rowCount(const QModelIndex&) const
+{
+    return m_items.size();
+}
+
+PlaybackToolBarAbstractItem* PlaybackToolBarModel::findItem(const muse::actions::ActionCode& actionCode)
 {
-    AbstractMenuModel::onActionsStateChanges(codes);
+    for (PlaybackToolBarAbstractItem* item : m_items) {
+        if (item->action().code == actionCode) {
+            return item;
+        }
+    }
+
+    return nullptr;
+}
 
+void PlaybackToolBarModel::onActionsStateChanges(const muse::actions::ActionCodeList& codes)
+{
     if (containsAction(codes, PLAY_ACTION_CODE)) {
-        MenuItem& item = findItem(PLAY_ACTION_CODE);
-        item.setAction(playAction());
+        PlaybackToolBarAbstractItem* item = findItem(PLAY_ACTION_CODE);
+        item->setAction(playAction());
     }
 }
 
@@ -83,12 +138,13 @@ void PlaybackToolBarModel::setupConnections()
 
 void PlaybackToolBarModel::onProjectChanged()
 {
-    updateState();
 }
 
 void PlaybackToolBarModel::updateActions()
 {
-    MenuItemList items;
+    m_items.clear();
+
+    beginResetModel();
 
     muse::ui::ToolConfig playbackConfig
         = uiConfiguration()->toolConfig(TOOLBAR_NAME, PlaybackUiActions::defaultPlaybackToolConfig());
@@ -99,31 +155,18 @@ void PlaybackToolBarModel::updateActions()
             continue;
         }
 
-        if (citem.action.empty()) {
-            section++;
-            continue;
-        }
-
-        MenuItem* item = makeActionItem(uiActionsRegister()->action(citem.action), QString::number(section));
+        PlaybackToolBarAbstractItem* item = makeItem(uiActionsRegister()->action(citem.action), QString::number(section));
 
         if (citem.action == PLAY_ACTION_CODE) {
             item->setAction(playAction());
         }
 
-        items << item;
+        m_items << item;
     }
 
-    setItems(items);
-}
+    endResetModel();
 
-void PlaybackToolBarModel::updateState()
-{
-    for (int i = 0; i < rowCount(); ++i) {
-        MenuItem& item = this->item(i);
-        muse::ui::UiActionState state = item.state();
-        state.checked = false;
-        item.setState(state);
-    }
+    emit itemsChanged();
 }
 
 bool PlaybackToolBarModel::isMenuSecondary(const muse::actions::ActionCode& actionCode) const
@@ -133,12 +176,10 @@ bool PlaybackToolBarModel::isMenuSecondary(const muse::actions::ActionCode& acti
     return false;
 }
 
-MenuItem* PlaybackToolBarModel::makeActionItem(const muse::ui::UiAction& action, const QString& section,
-                                               const muse::uicomponents::MenuItemList& subitems)
+PlaybackToolBarAbstractItem* PlaybackToolBarModel::makeItem(const muse::ui::UiAction& action, const QString& section)
 {
-    MenuItem* item = new MenuItem(action, this);
+    PlaybackToolBarAbstractItem* item = new PlaybackToolBarAbstractItem(action, itemType(action.code), this);
     item->setSection(section);
-    item->setSubitems(subitems);
     return item;
 }
 
diff --git a/au4/src/playback/view/toolbars/playbacktoolbarmodel.h b/au4/src/playback/view/toolbars/playbacktoolbarmodel.h
index 8da212a22a4da83e74b4ef2d4c560e66e4b78de1..b3a7a12e3d2c3d05373ded945ec9df499a0dd1a8 100644
--- a/au4/src/playback/view/toolbars/playbacktoolbarmodel.h
+++ b/au4/src/playback/view/toolbars/playbacktoolbarmodel.h
@@ -5,54 +5,70 @@
 #define AU_PROJECTSCENE_PLAYBACKTOOLBARMODEL_H
 
 #include <QHash>
+#include <QAbstractListModel>
+
+#include "async/asyncable.h"
 
 #include "modularity/ioc.h"
 #include "context/iglobalcontext.h"
 #include "ui/iuiactionsregister.h"
 #include "ui/iuiconfiguration.h"
+#include "actions/iactionsdispatcher.h"
 #include "playback/iplaybackcontroller.h"
 
-#include "uicomponents/view/abstractmenumodel.h"
-
 namespace au::playback {
-class PlaybackToolBarModel : public muse::uicomponents::AbstractMenuModel
+class PlaybackToolBarAbstractItem;
+class PlaybackToolBarModel : public QAbstractListModel, public muse::async::Asyncable
 {
     Q_OBJECT
 
-    muse::Inject<au::context::IGlobalContext> context;
     muse::Inject<muse::ui::IUiActionsRegister> actionsRegister;
     muse::Inject<muse::ui::IUiConfiguration> uiConfiguration;
+    muse::Inject<muse::ui::IUiActionsRegister> uiActionsRegister;
+    muse::Inject<muse::actions::IActionsDispatcher> dispatcher;
+    muse::Inject<au::context::IGlobalContext> context;
     muse::Inject<au::playback::IPlaybackController> controller;
 
+    Q_PROPERTY(int length READ rowCount NOTIFY itemsChanged)
+
 public:
     explicit PlaybackToolBarModel(QObject* parent = nullptr);
 
-    Q_INVOKABLE void load() override;
+    Q_INVOKABLE void load();
+    Q_INVOKABLE void handleMenuItem(const QString& itemId);
+    Q_INVOKABLE QVariantMap get(int index);
 
     QVariant data(const QModelIndex& index, int role) const override;
     QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+
+signals:
+    void itemsChanged();
 
 private:
     enum InputRoles {
-        IsMenuSecondaryRole = AbstractMenuModel::Roles::UserRole + 1,
+        ItemRole = Qt::UserRole + 1,
+        IsMenuSecondaryRole,
         OrderRole,
-        SectionRole
+        SectionRole,
     };
 
-    void onActionsStateChanges(const muse::actions::ActionCodeList& codes) override;
+    PlaybackToolBarAbstractItem* findItem(const muse::actions::ActionCode& actionCode);
+
+    void onActionsStateChanges(const muse::actions::ActionCodeList& codes);
 
     void setupConnections();
     void onProjectChanged();
 
     void updateActions();
-    void updateState();
 
     bool isMenuSecondary(const muse::actions::ActionCode& actionCode) const;
 
-    muse::uicomponents::MenuItem* makeActionItem(const muse::ui::UiAction& action, const QString& section,
-                                                 const muse::uicomponents::MenuItemList& subitems = {});
+    PlaybackToolBarAbstractItem* makeItem(const muse::ui::UiAction& action, const QString& section);
 
     muse::ui::UiAction playAction() const;
+
+    QList<PlaybackToolBarAbstractItem*> m_items;
 };
 }
 
diff --git a/au4/src/projectscene/internal/projectsceneuiactions.cpp b/au4/src/projectscene/internal/projectsceneuiactions.cpp
index 619f5136e08443616efa5d9078399e6b335365e9..8daaecc45e3349bbf17ffe6ef1c6082dc458a089 100644
--- a/au4/src/projectscene/internal/projectsceneuiactions.cpp
+++ b/au4/src/projectscene/internal/projectsceneuiactions.cpp
@@ -28,7 +28,7 @@ const UiActionList ProjectSceneUiActions::m_actions = {
              au::context::CTX_ANY,
              TranslatableString("action", "Zoom"),
              TranslatableString("action", "Zoom"),
-             IconCode::Code::ZOOM
+             IconCode::Code::ZOOM_TOGGLE
              ),
     UiAction("zoomin",
              au::context::UiCtxNotationOpened,