refactor(quickshell): rework the panel chrome, extract it as StatusBarPanel

The dense bar's panel chrome gets a squarer outline (top-right and bottom-left
chamfers only, square on the other two corners) and a second accent line in
the lower right to balance the existing upper-left one.

The chrome then moves out of DenseBarContent's inline `component
TelemetryPanel` into its own file. The call sites are unchanged apart from the
name -- children still come from the default property -- and the widgets they
pass in (RadarGauge, NetworkTrace, MetricBlock) stay declared in
DenseBarContent, so their scope is unaffected by moving only the definition.

Two things could not come along and had to be reproduced locally, because a
component in its own file has no access to the enclosing scope:

  - the palette and the two font families, previously read off `root`. They
    are properties with defaults matching DenseBarContent's, which is this
    repo's per-component convention. Duplicated on purpose for now; a shared
    theme singleton is the place to collapse it.
  - MicroText, which is an *inline* component of DenseBarContent and so
    invisible from another file. Expanded to the Text it desugars to.

Also qualified the bare offsetY/chamfer/accentLineThickness references as
panel.*; they resolved through the component scope before, but being explicit
avoids ComponentBehavior: Bound warnings in the new file.

Verified the move was verbatim by normalising the old inline block and the new
file body and diffing them -- the only differences are the relocated property
block, the panel.* qualification and the MicroText expansion. Loads clean both
headlessly and in the real layer-shell shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgcWkm3t6BDQktYHQvb8Hx
This commit is contained in:
2026-08-28 07:55:59 +02:00
co-authored by Claude Opus 5
parent 54896033c6
commit 01bc169180
2 changed files with 147 additions and 109 deletions
@@ -69,11 +69,6 @@ Item {
onTriggered: root.now = new Date() onTriggered: root.now = new Date()
} }
Rectangle {
anchors.fill: parent
color: root.voidColor
}
// Faint drafting grid; no gradient and deliberately subordinate to data. // Faint drafting grid; no gradient and deliberately subordinate to data.
Repeater { Repeater {
model: Math.ceil(root.width / 40) model: Math.ceil(root.width / 40)
@@ -115,7 +110,7 @@ Item {
anchors.fill: parent anchors.fill: parent
spacing: 8 spacing: 8
TelemetryPanel { StatusBarPanel {
width: array.identityWidth width: array.identityWidth
height: array.height height: array.height
panelId: "001" panelId: "001"
@@ -198,7 +193,7 @@ Item {
} }
} }
TelemetryPanel { StatusBarPanel {
width: array.flexWidth width: array.flexWidth
height: array.height height: array.height
panelId: "02" panelId: "02"
@@ -245,7 +240,7 @@ Item {
} }
} }
TelemetryPanel { StatusBarPanel {
width: array.radarWidth width: array.radarWidth
height: array.height height: array.height
panelId: "03" panelId: "03"
@@ -259,7 +254,7 @@ Item {
} }
} }
TelemetryPanel { StatusBarPanel {
width: array.flexWidth width: array.flexWidth
height: array.height height: array.height
panelId: "04" panelId: "04"
@@ -306,7 +301,7 @@ Item {
} }
} }
TelemetryPanel { StatusBarPanel {
width: array.stateWidth width: array.stateWidth
height: array.height height: array.height
panelId: "05" panelId: "05"
@@ -362,7 +357,7 @@ Item {
} }
} }
TelemetryPanel { StatusBarPanel {
id: rail id: rail
x: 12 x: 12
y: 108 y: 108
@@ -555,104 +550,6 @@ Item {
} }
} }
component TelemetryPanel: Item {
id: panel
property string panelId: ""
property string title: ""
property string meta: ""
property bool showHeader: true
property int chamfer: 13
Shape {
id: panelShape
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: root.voidColor
strokeColor: root.hairColor
strokeWidth: 1
startX: 1; startY: 1
PathLine { x: panelShape.width - panel.chamfer; y: 1 }
PathLine { x: panelShape.width - 1; y: panel.chamfer }
PathLine { x: panelShape.width - 1; y: panelShape.height - 8 }
PathLine { x: panelShape.width - 8; y: panelShape.height - 1 }
PathLine { x: 16; y: panelShape.height - 1 }
PathLine { x: 1; y: panelShape.height - 16 }
PathLine { x: 1; y: 1 }
}
ShapePath {
fillColor: root.accentColor
strokeWidth: 0
startX: 1; startY: 1
PathLine { x: Math.min(49, panelShape.width / 3); y: 1 }
PathLine { x: Math.min(49, panelShape.width / 3); y: 3 }
PathLine { x: 1; y: 3 }
PathLine { x: 1; y: 1 }
}
}
Rectangle {
visible: panel.showHeader
x: 1; y: 20
width: parent.width - 2
height: 1
color: root.inkColor
opacity: 0.12
}
Rectangle {
visible: panel.showHeader
x: 9; y: 5
width: panel.panelId.length > 2 ? 29 : 24
height: 11
color: root.accentColor
Text {
anchors.centerIn: parent
text: panel.panelId
color: root.voidColor
font.family: root.microFont
font.pixelSize: 7
font.bold: true
}
}
Text {
visible: panel.showHeader
x: 40; y: 5
width: parent.width - 105
text: panel.title
color: root.inkColor
font.family: root.displayFont
font.pixelSize: 9
font.bold: true
font.letterSpacing: 1.1
elide: Text.ElideRight
}
MicroText {
visible: panel.showHeader && panel.meta.length > 0
anchors.right: parent.right
anchors.rightMargin: 12
y: 6
text: panel.meta
width: Math.min(80, parent.width / 4)
horizontalAlignment: Text.AlignRight
elide: Text.ElideRight
}
Row {
visible: panel.showHeader
anchors.right: parent.right
anchors.rightMargin: 10
y: 14
spacing: 2
Repeater {
model: 5
Rectangle { required property int index; width: 3; height: 1; color: root.accentColor }
}
}
}
component MetricBlock: Item { component MetricBlock: Item {
id: metric id: metric
property string label: "" property string label: ""
@@ -0,0 +1,141 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Shapes
// Chamfered panel chrome for the dense status rail: outline, corner accent
// lines, and the optional header strip (id chip / title / meta / tick marks).
// Content is supplied as children by the call site.
//
// Palette and fonts are properties with defaults rather than references to the
// parent, because a component in its own file has no access to the enclosing
// scope. The defaults match DenseBarContent's, which is the repo's existing
// per-component convention (see quickshell/CLAUDE.md) — a shared theme
// singleton would be the place to collapse the duplication.
Item {
id: panel
property string panelId: ""
property string title: ""
property string meta: ""
property bool showHeader: true
property int chamfer: 13
property int offsetY: 2
property int accentLineThickness: 3
property color voidColor: "#0a0a0a"
property color inkColor: "#dedede"
property color mutedColor: "#858585"
property color accentColor: "#e8722a"
property color hairColor: Qt.rgba(0.87, 0.87, 0.87, 0.28)
property string displayFont: "DepartureMono Nerd Font"
property string microFont: "DejaVu Sans Mono"
Shape {
id: panelShape
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: panel.voidColor
strokeColor: panel.hairColor
strokeWidth: 1
startX: 0; startY: panel.offsetY
PathLine { x: panelShape.width - panel.chamfer; y: panel.offsetY }
PathLine { x: panelShape.width; y: panel.chamfer }
PathLine { x: panelShape.width; y: panelShape.height }
PathLine { x: panel.chamfer; y: panelShape.height }
PathLine { x: 0; y: panelShape.height - panel.chamfer }
PathLine { x: 0; y: panel.offsetY }
}
// Upper left accent line
ShapePath {
fillColor: panel.accentColor
strokeWidth: 0
startX: 0; startY: 0
PathLine { x: Math.min(49, panelShape.width / 3); y: 0 }
PathLine { x: Math.min(49, panelShape.width / 3); y: panel.accentLineThickness }
PathLine { x: 0; y: panel.accentLineThickness }
PathLine { x: 0; y: 0 }
}
// Lower right accent line
ShapePath {
fillColor: panel.accentColor
strokeWidth: 0
startX: panelShape.width; startY: panelShape.height
PathLine { x: panelShape.width - Math.min(49, panelShape.width / 3); y: panelShape.height }
PathLine { x: panelShape.width - Math.min(49, panelShape.width / 3); y: panelShape.height - panel.accentLineThickness }
PathLine { x: panelShape.width; y: panelShape.height - panel.accentLineThickness }
PathLine { x: panelShape.width; y: panelShape.height }
}
}
Rectangle {
visible: panel.showHeader
x: 1; y: 22
width: parent.width - 2
height: 1
color: panel.inkColor
opacity: 0.12
}
Rectangle {
visible: panel.showHeader
x: 5; y: 7
width: panel.panelId.length > 2 ? 29 : 24
height: 11
color: panel.accentColor
Text {
anchors.centerIn: parent
text: panel.panelId
color: panel.voidColor
font.family: panel.microFont
font.pixelSize: 8
font.bold: true
}
}
Text {
visible: panel.showHeader
x: 40; y: 7
width: parent.width - 105
text: panel.title
color: panel.inkColor
font.family: panel.displayFont
font.pixelSize: 9
font.bold: true
font.letterSpacing: 1.1
elide: Text.ElideRight
}
// Inlined rather than reusing DenseBarContent's MicroText, which is an
// inline component and therefore not visible from another file.
Text {
visible: panel.showHeader && panel.meta.length > 0
anchors.right: parent.right
anchors.rightMargin: 12
y: 6
text: panel.meta
width: Math.min(80, parent.width / 4)
color: panel.mutedColor
font.family: panel.microFont
font.pixelSize: 6
font.letterSpacing: 0.7
horizontalAlignment: Text.AlignRight
elide: Text.ElideRight
}
Row {
visible: panel.showHeader
anchors.right: parent.right
anchors.rightMargin: 10
y: 14
spacing: 2
Repeater {
model: 5
Rectangle { required property int index; width: 4; height: 2; color: panel.accentColor }
}
}
}