pragma ComponentBehavior: Bound import Quickshell import Quickshell.Widgets import QtQuick import QtQuick.Layouts import ZShell.Config import ZShell import qs.Components Item { id: root readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2 readonly property real nonAnimHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins * 2 required property ScreenState screenState readonly property var dashboardTabs: { const allTabs = [ { component: dashComponent, iconName: "dashboard", text: qsTr("Dashboard"), enabled: true }, { component: weatherComponent, iconName: "cloud", text: qsTr("Weather"), enabled: true }, { component: mediaComponent, iconName: "queue_music", text: qsTr("Media"), enabled: true }, // { // component: testingComponent, // iconName: "speed", // text: qsTr("Testing"), // enabled: true // }, ]; return allTabs.filter(tab => tab.enabled); } implicitWidth: nonAnimWidth implicitHeight: nonAnimHeight Behavior on implicitHeight { Anim {} } Behavior on implicitWidth { Anim {} } Tabs { id: tabs anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.topMargin: ZUtils.clamp(anchors.margins - Config.bar.border, 0, anchors.margins) anchors.margins: Tokens.padding.large nonAnimWidth: root.nonAnimWidth - anchors.margins * 2 screenState: root.screenState tabs: root.dashboardTabs } ClippingRectangle { id: viewWrapper anchors.top: tabs.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: Tokens.padding.small color: "transparent" radius: Tokens.rounding.extraLarge - anchors.margins Flickable { id: view readonly property int currentIndex: root.screenState.dashboardTab readonly property Item currentItem: { repeater.count; return repeater.itemAt(currentIndex); } anchors.fill: parent implicitWidth: currentItem?.implicitWidth ?? 0 implicitHeight: currentItem?.implicitHeight ?? 0 contentX: currentItem?.x ?? 0 contentWidth: row.implicitWidth contentHeight: row.implicitHeight interactive: false onContentXChanged: { if (!moving || !currentItem) return; const x = contentX - currentItem.x; if (x > currentItem.implicitWidth / 2) root.screenState.dashboardTab = Math.min(root.screenState.dashboardTab + 1, tabs.count - 1); else if (x < -currentItem.implicitWidth / 2) root.screenState.dashboardTab = Math.max(root.screenState.dashboardTab - 1, 0); } RowLayout { id: row Repeater { id: repeater model: ScriptModel { values: root.dashboardTabs } delegate: Loader { id: paneLoader required property int index required property var modelData Layout.alignment: Qt.AlignTop sourceComponent: modelData.component Component.onCompleted: active = Qt.binding(() => { if (index === view.currentIndex) return true; const vx = Math.floor(view.visibleArea.xPosition * view.contentWidth); const vex = Math.floor(vx + view.visibleArea.widthRatio * view.contentWidth); return (vx >= x && vx <= x + implicitWidth) || (vex >= x && vex <= x + implicitWidth); }) } } } Component { id: dashComponent Dash { screenState: root.screenState } } Component { id: weatherComponent WeatherTab {} } Component { id: mediaComponent Media { screenState: root.screenState } } // Component { // id: testingComponent // // WeatherTest {} // } Behavior on contentX { Anim { type: Anim.DefaultEffects } } } } }