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:
@@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user