quickshell: extract HoverRow component, dedupe 6 hover targets

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
rope 2026-06-17 13:59:26 +01:00
parent 6846f38b9a
commit 215239e7aa

View file

@ -381,6 +381,25 @@ in
}
}
// HoverRow: a rounded clickable row that owns the shared
// base02 hover-fade + pointer cursor. Drop content inside and
// handle `onClicked`; override `radius` for non-radiusTiny rows.
component HoverRow: Rectangle {
default property alias rowData: _hrContent.data
signal clicked()
radius: Theme.radiusTiny
color: _hrMa.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
Item { id: _hrContent; anchors.fill: parent }
MouseArea {
id: _hrMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: parent.clicked()
}
}
// Card: the rounded base01 section surface used by every
// dropdown. Children flow into a padded auto-height column,
// so callers just set `width` and drop content in.
@ -1757,12 +1776,13 @@ in
}
// Mute button
Rectangle {
HoverRow {
width: parent.width
height: 28
color: masterMuteMa.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
radius: Theme.radiusTiny
onClicked: {
if (volWidget.sink && volWidget.sink.audio)
volWidget.sink.audio.muted = !volWidget.sink.audio.muted;
}
Row {
anchors.centerIn: parent
@ -1778,16 +1798,6 @@ in
font.pixelSize: 12
}
}
MouseArea {
id: masterMuteMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (volWidget.sink && volWidget.sink.audio)
volWidget.sink.audio.muted = !volWidget.sink.audio.muted;
}
}
}
}
@ -1913,13 +1923,19 @@ in
}
}
Rectangle {
HoverRow {
visible: netWidget.netState === "connected"
width: parent.width
height: 28
color: disconnectMouse.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
radius: Theme.radiusTiny
onClicked: {
netDisconnectProc.targetDevice = netWidget.netDevice;
netDisconnectProc.running = true;
netWidget.netState = "disconnected";
netWidget.netConn = "";
netWidget.netIcon = "wifi_off";
bar.closeAllDropdowns();
netRefreshDelay.start();
}
SText {
anchors.centerIn: parent
@ -1927,22 +1943,6 @@ in
color: Theme.base08
font.pixelSize: 12
}
MouseArea {
id: disconnectMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
netDisconnectProc.targetDevice = netWidget.netDevice;
netDisconnectProc.running = true;
netWidget.netState = "disconnected";
netWidget.netConn = "";
netWidget.netIcon = "wifi_off";
bar.closeAllDropdowns();
netRefreshDelay.start();
}
}
}
}
@ -1959,13 +1959,18 @@ in
Repeater {
model: netWidget.wifiNetworks
Rectangle {
HoverRow {
required property var modelData
width: parent.width
height: 32
color: netItemMouse.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
radius: Theme.radiusTiny
onClicked: {
if (!modelData.active) {
wifiConnectProc.targetSsid = modelData.ssid;
wifiConnectProc.running = true;
netRefreshDelay.start();
}
bar.closeAllDropdowns();
}
Row {
anchors.verticalCenter: parent.verticalCenter
@ -2006,20 +2011,6 @@ in
}
}
MouseArea {
id: netItemMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!modelData.active) {
wifiConnectProc.targetSsid = modelData.ssid;
wifiConnectProc.running = true;
netRefreshDelay.start();
}
bar.closeAllDropdowns();
}
}
}
}
}
@ -2289,24 +2280,16 @@ in
width: parent.width
height: 28
Rectangle {
HoverRow {
width: 28; height: 28; radius: Theme.radiusSmall
anchors.left: parent.left
color: calPrevMa.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
onClicked: calPopup.shiftMonth(-1)
SIcon {
anchors.centerIn: parent
text: "chevron_left"
color: Theme.base05
font.pixelSize: 18
}
MouseArea {
id: calPrevMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: calPopup.shiftMonth(-1)
}
}
SText {
@ -2322,24 +2305,16 @@ in
}
}
Rectangle {
HoverRow {
width: 28; height: 28; radius: Theme.radiusSmall
anchors.right: parent.right
color: calNextMa.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
onClicked: calPopup.shiftMonth(1)
SIcon {
anchors.centerIn: parent
text: "chevron_right"
color: Theme.base05
font.pixelSize: 18
}
MouseArea {
id: calNextMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: calPopup.shiftMonth(1)
}
}
}
@ -2525,31 +2500,23 @@ in
{ glyph: mediaCard.modelData.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow", act: "toggle" },
{ glyph: "skip_next", act: "next" }
]
Rectangle {
HoverRow {
id: mediaBtn
required property var modelData
width: 28; height: 28; radius: 14
color: mediaBtnMa.containsMouse ? Theme.base02 : Theme.base02t
Behavior on color { ColorAnimation { duration: Theme.animFade } }
onClicked: {
let p = mediaCard.modelData;
if (!p) return;
if (mediaBtn.modelData.act === "prev") p.previous();
else if (mediaBtn.modelData.act === "next") p.next();
else p.togglePlaying();
}
SIcon {
anchors.centerIn: parent
text: mediaBtn.modelData.glyph
color: Theme.base05
font.pixelSize: 18
}
MouseArea {
id: mediaBtnMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
let p = mediaCard.modelData;
if (!p) return;
if (mediaBtn.modelData.act === "prev") p.previous();
else if (mediaBtn.modelData.act === "next") p.next();
else p.togglePlaying();
}
}
}
}
}