feat(quickshell): quick switches under the dashboard

A row of pill switches under the dashboard's columns: Wi-Fi,
Bluetooth, do not disturb and stay awake, plus night light through
hyprsunset when it is installed. On is the light slab with ink type;
off is a hairline.
This commit is contained in:
nvrl committed 2026-10-04 23:34:27 +02:00
1 parent f7551006b3
commit 373584f34e
2 files changed
+138 -1

No files matched your search

+5
View File
@@ -105,6 +105,11 @@ meters, and what is playing. Escape or focusing anything else puts it away; a
`HyprlandFocusGrab` handles the latter, and `Actions.dashboardClosedAt` stops
the clock click that cleared the grab from opening it straight back up.
Under the columns, past a hairline, a row of switches: Wi-Fi, Bluetooth, do
not disturb and stay awake, plus night light when `hyprsunset` is installed
(it runs at 4200 K for as long as the switch is on). On is the light slab
with ink type, the same as a selection everywhere else; off is a hairline.
## Modules
| Module | Where | Left click | Right click | Middle | Scroll | Hover |
+133 -1
View File
@@ -58,7 +58,8 @@ PanelWindow {
readonly property real pad: Theme.padL
readonly property real bodyWidth: columns.implicitWidth + root.pad * 2
readonly property real bodyHeight: columns.implicitHeight + root.pad * 2
readonly property real bodyHeight: columns.implicitHeight + toggles.implicitHeight
+ Theme.padL + 1 + root.pad * 3
implicitWidth: root.bodyWidth + root.fillet * 2
implicitHeight: root.bodyHeight + 1
@@ -549,6 +550,65 @@ PanelWindow {
}
}
}
// A hairline, then the switches you reach for most.
Rectangle {
id: togglesRule
x: root.pad
y: columns.y + columns.implicitHeight + Theme.padL
width: root.bodyWidth - root.pad * 2
height: 1
color: Theme.alpha(Theme.outline, 0.5)
}
Row {
id: toggles
x: root.pad
y: togglesRule.y + 1 + root.pad
spacing: Theme.padS
readonly property int count: nightLight.available ? 5 : 4
readonly property real chipWidth:
(root.bodyWidth - root.pad * 2 - toggles.spacing * (toggles.count - 1)) / toggles.count
Toggle {
width: toggles.chipWidth
glyph: Net.wifiEnabled ? "󰖩" : "󰖪"
label: "Wi-Fi"
on: Net.wifiEnabled
onClicked: Net.toggleWifi()
}
Toggle {
width: toggles.chipWidth
enabled: Bt.available
glyph: Bt.enabled ? "󰂯" : "󰂲"
label: "Bluetooth"
on: Bt.enabled
onClicked: Bt.toggle()
}
Toggle {
width: toggles.chipWidth
glyph: Notifs.dnd ? "󰂛" : "󰂚"
label: "Do not disturb"
on: Notifs.dnd
onClicked: Notifs.toggleDnd()
}
Toggle {
width: toggles.chipWidth
glyph: "󰅶"
label: "Stay awake"
on: Idle.stayAwake
onClicked: Idle.toggleStayAwake()
}
Toggle {
width: toggles.chipWidth
visible: nightLight.available
glyph: "󰖔"
label: "Night light"
on: nightLight.running
onClicked: nightLight.running = !nightLight.running
}
}
}
}
}
@@ -572,6 +632,78 @@ PanelWindow {
readonly property real columnHeight: 214
// A warm screen for the evening, through hyprsunset if it is installed.
// It runs for as long as night light is on; stopping it restores the
// screen. The chip only appears when the binary exists.
Process {
id: nightLight
property bool available: false
command: ["hyprsunset", "--temperature", "4200"]
}
Process {
running: true
command: ["sh", "-c", "command -v hyprsunset"]
onExited: code => nightLight.available = code === 0
}
// A switch: a pill with a glyph and a name. On is the light slab with ink
// type, the same as a selection everywhere else; off is a hairline.
component Toggle: Item {
id: tg
property string glyph: ""
property string label: ""
property bool on: false
signal clicked()
height: 38
opacity: tg.enabled ? 1 : 0.35
Rectangle {
anchors.fill: parent
radius: height / 2
color: tg.on ? Theme.accentSoft : (tgHover.hovered ? Theme.treatmentHoverFill : "transparent")
border.width: tg.on ? 0 : 1
border.color: tgHover.hovered ? Theme.treatmentHoverMark : Theme.overlay
Behavior on color { ColorAnimation { duration: Theme.durBase } }
}
Row {
anchors.centerIn: parent
spacing: Theme.padS
Icon {
anchors.verticalCenter: parent.verticalCenter
text: tg.glyph
font.pixelSize: Theme.fsLarge
color: tg.on ? Theme.ink : (tgHover.hovered ? Theme.accent : Theme.text)
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: tg.label.toUpperCase()
color: tg.on ? Theme.ink : Theme.subtext
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsMicro
font.weight: Font.DemiBold
font.letterSpacing: Theme.tracking
renderType: Text.NativeRendering
}
}
HoverHandler {
id: tgHover
enabled: tg.enabled
cursorShape: Qt.PointingHandCursor
}
TapHandler {
enabled: tg.enabled
onTapped: tg.clicked()
}
}
// A label and its reading on one line, label left, reading right.
component Fact: Item {
property string label: ""