diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-16 10:19:46 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-16 10:19:46 +0200 |
| commit | 1e0cb0bc16d5971e6e42c105622443d955ccdf5e (patch) | |
| tree | b28783d823f1511d78d5dd30ae8d54e9fe4a572f | |
| parent | 22db61bebaba4fdc58110f8bcc07313d330ac658 (diff) | |
| download | quickshell-1e0cb0bc16d5971e6e42c105622443d955ccdf5e.tar.gz quickshell-1e0cb0bc16d5971e6e42c105622443d955ccdf5e.zip | |
feat(shared): one faded glow for hovers across the shells
Hover and attention effects were solid: a flat accent ring round the
user page's avatar, a flat quarter-disc in the hot corner, and thick
accent or white borders on window cards, keycaps and knobs. Glow.qml
is a RectangularShadow in the accent, fading out from the shape's edge
and in over 140ms, linked into desktop, window-switcher and keybinds
like Theme.qml, and all five places use it. Selection borders in the
appearance tabs stay: they mark state, not hover.
The avatar also gains the hover cue in the first place: the hand
cursor never showed under a hyprcursor-only theme, so without it the
picture gave no sign it could be clicked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | AGENTS.md | 5 | ||||
| l--------- | desktop/Glow.qml | 1 | ||||
| -rw-r--r-- | desktop/modules/user/UserPage.qml | 54 | ||||
| l--------- | keybinds/Glow.qml | 1 | ||||
| -rw-r--r-- | keybinds/PadPanel.qml | 18 | ||||
| -rw-r--r-- | shared/Glow.qml | 28 | ||||
| l--------- | window-switcher/Glow.qml | 1 | ||||
| -rw-r--r-- | window-switcher/HotCorner.qml | 12 | ||||
| -rw-r--r-- | window-switcher/WindowCard.qml | 8 |
9 files changed, 101 insertions, 27 deletions
@@ -376,7 +376,10 @@ component's `Theme.qml` edits all three. Do not replace a link with a copy. `shared/Workspaces.qml`, the workspace icon map, is linked the same way, from `desktop/` and `window-switcher/`, so the island's flick and the switcher's -cards show the same icons. `Status.qml` and `Notify.qml` are shared links too. +cards show the same icons. `Status.qml` and `Notify.qml` are shared links too, and so is `Glow.qml`, +the one hover glow (a `RectangularShadow`), linked from `desktop/`, +`window-switcher/` and `keybinds/`; a new glow uses it rather than a +solid ring or a thick accent border. Hot reload does not follow any of them (see Reloading). Glyphs are Nerd Font private-use codepoints and render with `Theme.iconFamily`, diff --git a/desktop/Glow.qml b/desktop/Glow.qml new file mode 120000 index 0000000..779c66a --- /dev/null +++ b/desktop/Glow.qml @@ -0,0 +1 @@ +../shared/Glow.qml
\ No newline at end of file diff --git a/desktop/modules/user/UserPage.qml b/desktop/modules/user/UserPage.qml index feaf85f..fabb3e4 100644 --- a/desktop/modules/user/UserPage.qml +++ b/desktop/modules/user/UserPage.qml @@ -142,31 +142,51 @@ Column { onAccepted: form.set("avatar", decodeURIComponent(selectedFile.toString().replace(/^file:\/\//, ""))) } - ClippingRectangle { + // The picture glows on hover. The glow is what says "clickable": + // the hand cursor never shows here, since the cursor theme only ships + // hyprcursors and Qt finds no hand in it. + Item { anchors.horizontalCenter: parent.horizontalCenter - width: 160 - height: 160 - radius: 80 - color: Theme.surfaceAlt + width: 176 + height: 176 - Image { - id: pic - anchors.fill: parent - source: form.draft.avatar ? "file://" + form.draft.avatar.split("/").map(encodeURIComponent).join("/") : "" - fillMode: Image.PreserveAspectCrop - sourceSize: Qt.size(320, 320) - cache: false + Glow { + anchors.centerIn: parent + width: 160 + height: 160 + radius: 80 + on: avatarArea.containsMouse } - Text { + + ClippingRectangle { anchors.centerIn: parent - visible: pic.status !== Image.Ready - text: "\uf007" - font { family: Theme.iconFamily; pixelSize: 64 } - color: Theme.subtext + width: 160 + height: 160 + radius: 80 + color: Theme.surfaceAlt + + Image { + id: pic + anchors.fill: parent + source: form.draft.avatar ? "file://" + form.draft.avatar.split("/").map(encodeURIComponent).join("/") : "" + fillMode: Image.PreserveAspectCrop + sourceSize: Qt.size(320, 320) + cache: false + } + Text { + anchors.centerIn: parent + visible: pic.status !== Image.Ready + text: "\uf007" + font { family: Theme.iconFamily; pixelSize: 64 } + color: Theme.subtext + } } + MouseArea { + id: avatarArea anchors.fill: parent enabled: !form.busy + hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: picker.open() } diff --git a/keybinds/Glow.qml b/keybinds/Glow.qml new file mode 120000 index 0000000..779c66a --- /dev/null +++ b/keybinds/Glow.qml @@ -0,0 +1 @@ +../shared/Glow.qml
\ No newline at end of file diff --git a/keybinds/PadPanel.qml b/keybinds/PadPanel.qml index d9f8941..c338c64 100644 --- a/keybinds/PadPanel.qml +++ b/keybinds/PadPanel.qml @@ -81,8 +81,13 @@ Item { height: panel.unit radius: panel.unit * 0.12 color: cap.cap - border.color: panel.hovered === padId ? Theme.text : "transparent" - border.width: 3 + + Glow { + anchors.fill: parent + z: -1 + radius: parent.radius + on: panel.hovered === keycap.padId + } Column { anchors.centerIn: parent @@ -140,9 +145,16 @@ Item { height: width radius: width / 2 color: panel.hovered === modelData ? Theme.surfaceAlt : Theme.surface - border.color: panel.hovered === modelData ? Theme.accent : Theme.overlay + border.color: Theme.overlay border.width: 2 + Glow { + anchors.fill: parent + z: -1 + radius: parent.radius + on: panel.hovered === parent.modelData + } + MouseArea { anchors.fill: parent hoverEnabled: true diff --git a/shared/Glow.qml b/shared/Glow.qml new file mode 100644 index 0000000..58aa45d --- /dev/null +++ b/shared/Glow.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2026 Danilo M. <danix@danix.xyz> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 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. + +import QtQuick +import QtQuick.Effects + +// The shells' one glow: an accent haze fading out from a shape's edge, in +// place of solid rings and thick hover borders. It goes under the item it +// lights, same size and radius: a child with `z: -1` and `anchors.fill: +// parent`, or a sibling declared before it. `on` fades it in. Linked into +// each shell that uses it, like Theme.qml. +RectangularShadow { + property bool on: false + + color: Theme.accent + blur: 20 + spread: 2 + opacity: on ? 0.9 : 0 + Behavior on opacity { NumberAnimation { duration: 140 } } +} diff --git a/window-switcher/Glow.qml b/window-switcher/Glow.qml new file mode 120000 index 0000000..779c66a --- /dev/null +++ b/window-switcher/Glow.qml @@ -0,0 +1 @@ +../shared/Glow.qml
\ No newline at end of file diff --git a/window-switcher/HotCorner.qml b/window-switcher/HotCorner.qml index cb7d863..eebcf05 100644 --- a/window-switcher/HotCorner.qml +++ b/window-switcher/HotCorner.qml @@ -87,15 +87,17 @@ PanelWindow { } } - // A quarter circle centred on the corner, growing with the dwell. - Rectangle { - readonly property real r: corner.width * corner.progress + // A glow centred on the corner, growing with the dwell. The disc is + // smaller than the window so the fade fits inside it. + Glow { + readonly property real r: corner.width * 0.5 * corner.progress x: corner.width - r y: -r width: 2 * r height: 2 * r radius: r - color: Theme.accent - opacity: 0.6 * corner.progress + blur: r + on: true + opacity: 0.8 * corner.progress } } diff --git a/window-switcher/WindowCard.qml b/window-switcher/WindowCard.qml index 177aac9..be97427 100644 --- a/window-switcher/WindowCard.qml +++ b/window-switcher/WindowCard.qml @@ -40,13 +40,19 @@ Item { HoverHandler { id: cardHover } + Glow { + anchors.fill: box + radius: box.radius + on: cardHover.hovered + } + Rectangle { id: box anchors.fill: parent radius: 10 color: Theme.surface border.color: cardHover.hovered ? Theme.accent : Theme.surfaceAlt - border.width: cardHover.hovered ? 3 : 1 + border.width: 1 // The rect already has the window's shape, so the preview fills it. // The fit is kept for the moment before a capture lands: an |
