// The scaffold every settings page shares: a scrolling column with a title, a // one-line lede, and consistent margins. // // This existed eleven times as copy-pasted Flickable/Column/x:34/y:30 blocks, // which is a large part of why several pages settled for read-only text instead // of real controls -- adding a page was expensive enough that the cheap thing // won. Pages are now just their content: // // SettingsPage { // title: "Appearance" // lede: "Tokyo Night Moon, tuned for clarity and quiet motion." // // SettingsCard { title: "Windows"; ToggleRow { setting: "blurEnabled" } } // } import QtQuick import qs.config Item { id: root default property alias content: column.data property string title: "" property string lede: "" // Anything that should sit above the title and stay put while the rest // scrolls -- the Appearance page pins its live preview here. property Component header: null // A view that replaces the page entirely while it is up. Containers' log // reader is the case: logs need their own scrollback, and a scrolling view // nested inside a scrolling page makes the wheel ambiguous over exactly the // region where somebody wants to use it. A page that owns one stays a // SettingsPage rather than becoming a bare Item wrapping two of them. property Component drillIn: null property bool drilledIn: false Loader { id: pinnedHeader anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.leftMargin: 34 anchors.rightMargin: 34 anchors.topMargin: 30 visible: !root.drilledIn active: root.header !== null sourceComponent: root.header z: 1 } Loader { anchors.fill: parent active: root.drillIn !== null && root.drilledIn sourceComponent: root.drillIn z: 2 } Flickable { id: pageScroll anchors.left: parent.left anchors.right: parent.right anchors.top: pinnedHeader.implicitHeight > 0 ? pinnedHeader.bottom : parent.top anchors.bottom: parent.bottom anchors.topMargin: pinnedHeader.implicitHeight > 0 ? 16 : 0 visible: !root.drilledIn clip: true contentWidth: width contentHeight: layout.implicitHeight + (pinnedHeader.implicitHeight > 0 ? 34 : 64) boundsBehavior: Flickable.StopAtBounds Column { id: layout width: parent.width - 68 x: 34 y: pinnedHeader.implicitHeight > 0 ? 0 : 30 spacing: 16 Text { width: parent.width visible: root.title !== "" text: root.title color: Theme.fg font.family: Theme.fontFamily font.pixelSize: 27 font.weight: Font.DemiBold } Text { width: parent.width visible: root.lede !== "" text: root.lede color: Theme.fgDim font.family: Theme.fontFamily font.pixelSize: Theme.fontSize wrapMode: Text.WordWrap bottomPadding: 6 } Column { id: column width: parent.width spacing: 16 } } } }