final theme

This commit is contained in:
2026-08-11 02:05:46 +02:00
parent 105cf6b3a8
commit 08146fe16f
5 changed files with 174 additions and 39 deletions
+8
View File
@@ -52,6 +52,14 @@ PanelWindow {
slash: true
slashColor: Theme.accent
slashWidth: 5
// No offset copy on the big slabs. The 3px black silhouette behind the
// fill is a print-misregistration trick, and at this scale it stops
// reading as one: on a 1900px bar you only ever see it at the chopped
// corners, where it turns the single clean cut into a staggered double
// edge that looks like a rendering fault. The black keyline still
// carries the heavy outer contour, which is what the corner needs.
drop: false
}
readonly property real edgeInset: Theme.barHeight * Theme.skew + Theme.padM
+5
View File
@@ -56,6 +56,11 @@ PanelWindow {
slash: true
slashColor: Theme.accent
slashWidth: 5
// Same as the bar — see the note there. The doubled corner is worse on
// the rail, because its chopped corners sit against the wallpaper's
// high-contrast stripes rather than against other chrome.
drop: false
}
readonly property real edgeInset: Theme.railWidth * Theme.skew + Theme.padM
+91
View File
@@ -0,0 +1,91 @@
import QtQuick
import "root:/config"
import "root:/components"
// One metric in a popout: a label and its reading on a line, with a wide
// sheared segmented meter underneath.
//
// This replaces the radial Gauge. A 270° dial was the only curved thing in a
// shell whose whole geometry is sheared slabs and hard chamfers, so it read as
// though it had been imported from another design. The meter says the same
// thing in the language the bar and the OSD already speak, and it gets far more
// resolution across a popout's width than a 88px dial did.
Item {
id: root
property string label: ""
property real value: 0 // 0..100
property string readout: Math.round(root.value) + "%"
property string sub: ""
property color tone: Theme.heat(root.value)
property int segments: 24
property real segmentSpacing: 3
implicitHeight: head.height + Theme.padS + meter.height
Item {
id: head
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: Math.max(name.implicitHeight, figure.implicitHeight)
Text {
id: name
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: root.label.toUpperCase()
color: Theme.subtext
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
font.letterSpacing: 2
renderType: Text.NativeRendering
}
// The secondary figure — temperature, used-of-total. Sits next to the
// label rather than under the number so the right edge stays a single
// clean column of readings.
Text {
anchors.left: name.right
anchors.leftMargin: Theme.padM
anchors.right: figure.left
anchors.rightMargin: Theme.padM
anchors.verticalCenter: parent.verticalCenter
visible: root.sub !== ""
text: root.sub
color: Theme.muted
elide: Text.ElideRight
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
renderType: Text.NativeRendering
}
SplitText {
// Not `value` — an id by that name shadows the `value` property, and
// the defaults above then round a Text item instead of a number.
id: figure
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: root.readout
pixelSize: Theme.fsBody
color: Theme.text
split: 1
splitOpacity: 0.5
}
}
MeterBar {
id: meter
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 12
segments: root.segments
spacing: root.segmentSpacing
// Fill the row exactly rather than leaving a ragged tail on the right.
segmentWidth: (width - (root.segments - 1) * root.segmentSpacing) / root.segments
value: root.value
activeColor: root.tone
}
}
+50 -26
View File
@@ -9,7 +9,11 @@ Popout {
id: root
contentWidth: 310
contentHeight: 296
// Derived: the charge block is a different height from the dial it
// replaced, and the health line comes and goes.
contentHeight: header.height + Theme.padM + readout.height + Theme.padM
+ bar.height + Theme.padM + detailText.implicitHeight + Theme.padL
+ suspendButton.height + Theme.padM * 2
PopoutSurface {
anchors.fill: parent
@@ -26,27 +30,42 @@ Popout {
subtitle: Battery.charging ? "CHARGING" : (Battery.onBattery ? "ON BATTERY" : "AC")
}
Row {
// The dial that used to sit here duplicated the meter below it and was
// the only curve in the shell. The charge is now simply set large, and
// the MeterBar underneath is left to carry the level on its own.
Item {
id: readout
anchors.top: header.bottom
anchors.topMargin: Theme.padM
anchors.left: parent.left
anchors.right: parent.right
spacing: Theme.padM
height: Math.max(charge.height, detail.height)
Gauge {
width: 92; height: 92
value: Battery.percent
label: "CHARGE"
arcColor: Battery.tint
readout: Math.round(Battery.percent) + "%"
Column {
id: charge
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
// No "CHARGE" caption under the number. It landed directly on
// top of the meter, and between the header and a full-width
// charge bar there was nothing left for it to disambiguate.
SplitText {
text: Math.round(Battery.percent) + "%"
pixelSize: Theme.fsHuge
color: Battery.tint
split: 2.5
splitOpacity: 0.7
}
}
Column {
id: detail
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.padS
SplitText {
anchors.right: parent.right
horizontalAlignment: Text.AlignRight
text: Battery.timeLabel
pixelSize: Theme.fsBody
split: 1.1
@@ -57,6 +76,8 @@ Popout {
text: Battery.changeRate > 0
? Battery.changeRate.toFixed(1) + " W " + (Battery.charging ? "in" : "draw")
: "idle"
anchors.right: parent.right
horizontalAlignment: Text.AlignRight
color: Theme.subtext
font.family: Theme.fontMono
font.pixelSize: Theme.fsSmall
@@ -66,6 +87,8 @@ Popout {
Text {
visible: Battery.health > 0
text: "Health " + Math.round(Battery.health) + "%"
anchors.right: parent.right
horizontalAlignment: Text.AlignRight
color: Battery.health < 70 ? Theme.warn : Theme.muted
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
@@ -88,9 +111,26 @@ Popout {
activeColor: Battery.tint
}
Text {
id: detailText
anchors.top: bar.bottom
anchors.topMargin: Theme.padM
anchors.left: parent.left
anchors.right: parent.right
text: Battery.detail
wrapMode: Text.WordWrap
color: Theme.muted
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
renderType: Text.NativeRendering
}
// Follows the detail line rather than being pinned to the bottom of a
// fixed-height panel, which is what left a dead band above it.
P5Button {
id: suspendButton
anchors.bottom: parent.bottom
anchors.top: detailText.bottom
anchors.topMargin: Theme.padL
anchors.left: parent.left
text: "Suspend"
icon: "󰤄"
@@ -99,21 +139,5 @@ Popout {
Actions.suspend();
}
}
Text {
anchors.top: bar.bottom
anchors.topMargin: Theme.padS
anchors.bottom: suspendButton.top
anchors.bottomMargin: Theme.padS
anchors.left: parent.left
anchors.right: parent.right
text: Battery.detail
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignTop
color: Theme.muted
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
renderType: Text.NativeRendering
}
}
}
+20 -13
View File
@@ -9,7 +9,12 @@ Popout {
id: root
contentWidth: 420
contentHeight: 268
// Derived rather than a fixed number: the meters are taller than the dials
// they replaced, and the GPU block disappears entirely on machines without
// one. A hardcoded height would either clip or leave a hole.
contentHeight: header.height + Theme.padM
+ gauges.implicitHeight + Theme.padL
+ details.implicitHeight + Theme.padM * 2
PopoutSurface {
anchors.fill: parent
@@ -26,37 +31,38 @@ Popout {
subtitle: "UP " + Sys.uptime + " · " + Sys.procs + " PROCS"
}
Row {
Column {
id: gauges
anchors.top: header.bottom
anchors.topMargin: Theme.padM
anchors.horizontalCenter: parent.horizontalCenter
anchors.left: parent.left
anchors.right: parent.right
spacing: Theme.padM
Gauge {
width: 88; height: 88
MetricRow {
width: parent.width
value: Sys.cpuUsage
label: "CPU"
sub: Math.round(Sys.cpuTemp) + "°C"
}
Gauge {
width: 88; height: 88
MetricRow {
width: parent.width
value: Sys.memPercent
label: "MEM"
sub: Sys.gb(Sys.memUsed) + "/" + Sys.gb(Sys.memTotal)
sub: Sys.gb(Sys.memUsed) + " / " + Sys.gb(Sys.memTotal)
}
Gauge {
width: 88; height: 88
MetricRow {
width: parent.width
visible: Sys.gpuAvailable
value: Sys.gpuUsage
label: "GPU"
sub: Math.round(Sys.gpuTemp) + "°C"
}
Gauge {
width: 88; height: 88
MetricRow {
width: parent.width
value: Sys.diskPercent
label: "DISK"
sub: Sys.diskFree + " free"
@@ -64,8 +70,9 @@ Popout {
}
Column {
id: details
anchors.top: gauges.bottom
anchors.topMargin: Theme.padM
anchors.topMargin: Theme.padL
anchors.left: parent.left
anchors.right: parent.right
spacing: 3