Add outline cursor mode to CursorSurface for slider rows

Wide content rows (slider rows in audio / monitor panels) opted out of
the cursor fill by setting fill: "transparent" on their CursorSurface,
which left them with no cursor visual at all — j/k landed there
silently with no way to know what was selected.

Add an `outline: bool` flag to CursorSurface. When true, hasCursor
paints an accent border (Style.focusBorderColor at
Style.focusBorderWidth) instead of a fill, leaving the row's chrome
fully visible underneath. Use for slider rows where a fill would
obscure the track.

Audio output / input slider rows and the monitor brightness row opt
in. The dev gallery's slider section replaces its bespoke Rectangle
wrapper with the same CursorSurface { outline: true }, so what the
gallery documents is what the panels ship.
This commit is contained in:
Ryan Hughes
2026-05-18 12:19:23 -04:00
parent b5f7ba02c2
commit 8b858d4093
4 changed files with 28 additions and 16 deletions
+20 -4
View File
@@ -6,20 +6,36 @@ import qs.Commons
// hover updates the panel's cursor state at the root; visuals derive from
// `hasCursor` / `current`. That's what guarantees a single highlight on
// screen at any time across both keyboard and mouse interaction.
//
// Two cursor visuals are supported:
//
// default (outline: false) — paint a tinted fill across the row when
// hasCursor is true. Use for narrow text rows (wifi networks, audio
// devices, menu items) where fill reads cleanly.
//
// outline: true — paint an accent border instead of a fill. Use for
// wide content rows where a fill would obscure the row's chrome
// (slider rows in audio / monitor panels). The fill / currentFill
// props are ignored in this mode.
Rectangle {
id: root
property bool hasCursor: false
property bool current: false
property bool outline: false
property color foreground: "#cacccc"
property color foreground: Color.foreground
property color fill: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.08)
property color currentFill: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
radius: Style.cornerRadius
color: hasCursor ? fill : (current ? currentFill : "transparent")
border.width: 0
border.color: foreground
color: root.outline
? "transparent"
: (hasCursor ? fill : (current ? currentFill : "transparent"))
border.color: root.outline && hasCursor ? Style.focusBorderColor : foreground
border.width: root.outline && hasCursor ? Style.focusBorderWidth : 0
Behavior on color {
ColorAnimation { duration: 60 }
+2 -2
View File
@@ -454,7 +454,7 @@ Item {
hasCursor: root.focusSection === "output" && root.selectedIndex === -1
onHasCursorChanged: if (hasCursor) root.ensureCursorVisible(outputSliderRow)
foreground: root.bar.foreground
fill: "transparent"
outline: true
Row {
id: outputSliderInner
@@ -571,7 +571,7 @@ Item {
hasCursor: root.focusSection === "input" && root.selectedIndex === -1
onHasCursorChanged: if (hasCursor) root.ensureCursorVisible(inputSliderRow)
foreground: root.bar.foreground
fill: "transparent"
outline: true
Row {
id: inputSliderInner
+1 -1
View File
@@ -415,7 +415,7 @@ Item {
hasCursor: root.focusSection === "brightness" && root.selectedIndex === -1
onHasCursorChanged: if (hasCursor) root.ensureCursorVisible(brightnessRow)
foreground: root.bar.foreground
fill: "transparent"
outline: true
Row {
id: brightnessInner
+5 -9
View File
@@ -1121,18 +1121,14 @@ Item {
wrapMode: Text.WordWrap
}
Rectangle {
CursorSurface {
id: sliderWrapper
width: parent.width
implicitHeight: sliderRow.implicitHeight + 24
readonly property bool focused: root.focusSection === "slider"
color: Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b, 0.04)
radius: Style.cornerRadius
border.color: focused
? Style.focusBorderColor
: Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b, 0.10)
border.width: focused ? Style.focusBorderWidth : 1
onFocusedChanged: if (focused) root.ensureCursorVisible(this)
outline: true
foreground: root.foreground
hasCursor: root.focusSection === "slider"
onHasCursorChanged: if (hasCursor) root.ensureCursorVisible(this)
HoverHandler {
onHoveredChanged: if (hovered) {