diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-17 10:10:42 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-17 10:10:42 +0200 |
| commit | e5399f3e8d8572f1db7c4391a7c571d4845500f1 (patch) | |
| tree | fd826694491f7f7973cd077513461ba4dd7f9827 | |
| parent | c832b66159e52503ca3da4b8f9fa7d32dbd28353 (diff) | |
| download | quickshell-e5399f3e8d8572f1db7c4391a7c571d4845500f1.tar.gz quickshell-e5399f3e8d8572f1db7c4391a7c571d4845500f1.zip | |
desktop: centred About, and a resizable settings sidebar
The About text sat in the top-left corner of an otherwise empty page; it
is now centred both ways in the space beside the sidebar.
The sidebar's edge, the rule between it and the page, drags to resize it
between 160 and 420px, lit in the accent while hovered. The width lives
in Prefs, written once on release rather than on every pixel of the
drag, so it survives a restart without a file to edit by hand.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | desktop/Prefs.qml | 18 | ||||
| -rw-r--r-- | desktop/README.md | 3 | ||||
| -rw-r--r-- | desktop/Settings.qml | 102 |
3 files changed, 88 insertions, 35 deletions
diff --git a/desktop/Prefs.qml b/desktop/Prefs.qml index def720c..1cc83cd 100644 --- a/desktop/Prefs.qml +++ b/desktop/Prefs.qml @@ -35,6 +35,11 @@ Singleton { // (assistant/Presets.js, which also validates what is read here). property var presets: null + // The settings window's sidebar width, dragged by its edge. + readonly property int sidebarMin: 160 + readonly property int sidebarMax: 420 + property int settingsSidebar: 200 + // The whole parsed object, so a write keeps keys this version does not // know about. property var doc: ({}) @@ -59,6 +64,14 @@ Singleton { root.write(Object.assign({}, root.doc, { assistant: a })); } + function setSettingsSidebar(w) { + w = Math.round(Math.max(root.sidebarMin, Math.min(root.sidebarMax, w))); + if (w === root.settingsSidebar) return; + root.settingsSidebar = w; + const s = Object.assign({}, root.doc.settings, { sidebar: w }); + root.write(Object.assign({}, root.doc, { settings: s })); + } + function write(out) { root.doc = out; file.setText(JSON.stringify(out, null, 2) + "\n"); @@ -75,6 +88,9 @@ Singleton { if (pin !== root.pinnedIp) root.pinnedIp = pin; root.presets = parsed.assistant && parsed.assistant.presets !== undefined ? parsed.assistant.presets : null; + const w = parsed.settings ? parsed.settings.sidebar : undefined; + root.settingsSidebar = typeof w === "number" && w >= root.sidebarMin && w <= root.sidebarMax + ? Math.round(w) : 200; } FileView { @@ -89,6 +105,6 @@ Singleton { onFileChanged: reload() onLoaded: root.reparse() // Missing file: the defaults, and nothing written. - onLoadFailed: { root.doc = {}; root.pinnedIp = ""; root.presets = null; } + onLoadFailed: { root.doc = {}; root.pinnedIp = ""; root.presets = null; root.settingsSidebar = 200; } } } diff --git a/desktop/README.md b/desktop/README.md index 42c2efb..089f86f 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -35,6 +35,9 @@ gear tile opens it, and so does IPC: qs -p ./desktop ipc call settings open autostart qs -p ./desktop ipc call settings toggle +The sidebar's edge drags to resize it, between 160 and 420px; the width is +saved in the preferences file on release. + `open` takes a page name; an unknown or empty one opens the landing page, a short About. A page's back arrow and Escape return there; Escape on the landing page closes the window. diff --git a/desktop/Settings.qml b/desktop/Settings.qml index 2e6d1f1..986ec26 100644 --- a/desktop/Settings.qml +++ b/desktop/Settings.qml @@ -32,6 +32,11 @@ Scope { } property string query: "" + // The sidebar's width: the saved one, or the live one while its edge is + // dragged (-1 when not), saved once on release. + property real dragWidth: -1 + readonly property real sideWidth: root.dragWidth >= 0 ? root.dragWidth : Prefs.settingsSidebar + // What the search keeps, as {mod, hit, key}. A page matched by its label // or a keyword has key "" and opens at the top; hit is the keyword when // the label did not match. Then each row inside a page that matches, from @@ -99,7 +104,7 @@ Scope { Rectangle { id: search anchors { top: parent.top; left: parent.left; margins: 12 } - width: 200 + width: root.sideWidth height: 34 radius: 8 color: Theme.surface @@ -150,7 +155,7 @@ Scope { ListView { id: side anchors { top: search.bottom; left: parent.left; bottom: parent.bottom; margins: 12 } - width: 200 + width: root.sideWidth spacing: 4 model: root.found @@ -212,44 +217,73 @@ Scope { id: rule anchors { top: parent.top; bottom: parent.bottom; left: side.right; leftMargin: 12 } width: 1 - color: Qt.alpha(Theme.text, 0.12) + color: grip.containsMouse || grip.pressed ? Qt.alpha(Theme.accent, 0.6) : Qt.alpha(Theme.text, 0.12) } - // The landing page, where back returns to: what this shell is. - Column { - anchors { top: parent.top; right: parent.right; left: rule.right; margins: 16 } - visible: root.current === null - spacing: 12 - - Text { - height: 44 - verticalAlignment: Text.AlignVCenter - text: "About" - font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 2; bold: true } - color: Theme.text + // The rule is the sidebar's edge: drag it to resize. + MouseArea { + id: grip + anchors { top: parent.top; bottom: parent.bottom; horizontalCenter: rule.horizontalCenter } + width: 10 + hoverEnabled: true + cursorShape: Qt.SplitHCursor + onPositionChanged: mouse => { + if (!pressed) return; + // The rule sits 12px right of the sidebar, which starts 12px in. + const x = mapToItem(parent, mouse.x, 0).x - 24; + root.dragWidth = Math.max(Prefs.sidebarMin, Math.min(Prefs.sidebarMax, x)); + } + onReleased: { + if (root.dragWidth >= 0) Prefs.setSettingsSidebar(root.dragWidth); + root.dragWidth = -1; } + } - Text { + // The landing page, where back returns to: what this shell is, + // centred in the space beside the sidebar. + Item { + anchors { top: parent.top; right: parent.right; bottom: parent.bottom; left: rule.right; margins: 16 } + visible: root.current === null + + Column { + anchors.centerIn: parent width: Math.min(parent.width, 560) - wrapMode: Text.Wrap - textFormat: Text.PlainText - lineHeight: 1.25 - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } - color: Theme.text - text: "A desktop shell for Hyprland, built on Quickshell.\n\n" - + "SUPER alone opens the drawer, the quick area: notifications, sound, " - + "network, bluetooth, mail, VMs, performance, the clipboard and the " - + "rest of what changes during the day. The island at the top of the " - + "main screen carries the clock, volume, tray, keyboard layout and " - + "calendar, and SUPER+Home opens the assistant.\n\n" - + "This window holds what is set once and left alone. Pick a page on " - + "the left, or search for a setting by name." - } + spacing: 12 - Text { - text: "GPLv2. Colours follow the wallpaper through unified-desktop-theme." - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } - color: Theme.subtext + Text { + width: parent.width + horizontalAlignment: Text.AlignHCenter + text: "About" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 2; bold: true } + color: Theme.text + } + + Text { + width: parent.width + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + textFormat: Text.PlainText + lineHeight: 1.25 + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + color: Theme.text + text: "A desktop shell for Hyprland, built on Quickshell.\n\n" + + "SUPER alone opens the drawer, the quick area: notifications, sound, " + + "network, bluetooth, mail, VMs, performance, the clipboard and the " + + "rest of what changes during the day. The island at the top of the " + + "main screen carries the clock, volume, tray, keyboard layout and " + + "calendar, and SUPER+Home opens the assistant.\n\n" + + "This window holds what is set once and left alone. Pick a page on " + + "the left, or search for a setting by name." + } + + Text { + width: parent.width + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + text: "GPLv2. Colours follow the wallpaper through unified-desktop-theme." + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + color: Theme.subtext + } } } |
