From bbe35dd72ebffbedc1863dbc99b94068aa6bfe32 Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Sat, 29 Aug 2026 04:13:43 +0200 Subject: [PATCH] feat(quickshell): join adjacent panels into a continuous rail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At spacing 0 a row of panels read as separate tiles, each closing its own silhouette. BarPanel can now drop either cut corner — rightChamfer (top-right) and leftChamfer (bottom-left), the only two the shape cuts — so an edge that a neighbour butts against runs square into it. The bar turns off the host's right and the vitals' left; the tray keeps both, since the spacer between them is not a panel and that edge is free. A side with its chamfer off also draws a connector: the shared edge restroked in accent at outlineWidth + 2, so the join reads as a deliberate seam rather than two outlines that happen to touch. The outline's own width becomes a property so the connector can be defined against it instead of as a second literal. The lower-right accent strip takes accentLineWidth, the same slug-derived width the upper-left one already used, instead of its own Math.min(49, width / 3). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HEtXvseVb5gwAtKNhFx2PU --- .../hyprchrome/widgets/HyprChromeBar.qml | 9 +++- .../hyprchrome/widgets/panels/BarPanel.qml | 49 ++++++++++++++++--- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/dotfiles/quickshell/hyprchrome/widgets/HyprChromeBar.qml b/dotfiles/quickshell/hyprchrome/widgets/HyprChromeBar.qml index 341a28f..b3c810b 100644 --- a/dotfiles/quickshell/hyprchrome/widgets/HyprChromeBar.qml +++ b/dotfiles/quickshell/hyprchrome/widgets/HyprChromeBar.qml @@ -100,12 +100,15 @@ Scope { x: window.margin y: window.margin width: window.width - window.margin * 2 - spacing: 8 + spacing: 0 HostPanel { id: hostPanel expanded: root.expanded + // Vitals butts against its right edge; the left end of the row is free. + rightChamfer: false + toggleOnClick: false Layout.preferredWidth: 350 Layout.fillHeight: true @@ -115,6 +118,10 @@ Scope { id: vitalsPanel expanded: root.expanded + // Host on the left, the spacer on the right — and a spacer is not a + // panel, so that edge keeps its cut. + leftChamfer: false + toggleOnClick: false Layout.preferredWidth: 500 Layout.fillHeight: true diff --git a/dotfiles/quickshell/hyprchrome/widgets/panels/BarPanel.qml b/dotfiles/quickshell/hyprchrome/widgets/panels/BarPanel.qml index bcedb43..1c711b9 100644 --- a/dotfiles/quickshell/hyprchrome/widgets/panels/BarPanel.qml +++ b/dotfiles/quickshell/hyprchrome/widgets/panels/BarPanel.qml @@ -118,6 +118,23 @@ Item { // which turns the outline inside out for the last frames of a collapse. readonly property real activeChamfer: Math.max(2, Math.min(panel.chamfer, panel.height / 2 - 1)) + // The silhouette has exactly two cut corners: top-right and bottom-left. + // Turn one off where another panel butts against that side, so a row laid + // out with no spacing reads as one continuous strip instead of a line of + // separate tiles. A cut corner costs its side nothing when disabled — the + // edge simply runs square into the neighbour. + property bool rightChamfer: true // top-right cut + property bool leftChamfer: true // bottom-left cut + + readonly property real rightCut: panel.rightChamfer ? panel.activeChamfer : 0 + readonly property real leftCut: panel.leftChamfer ? panel.activeChamfer : 0 + + // The seam where two panels meet is drawn a step heavier and in accent, so + // a chamfer-less join reads as a deliberate connector rather than as two + // outlines that happen to touch. + property int outlineWidth: 1 + readonly property int connectorWidth: panel.outlineWidth + 2 + Shape { id: panelShape anchors.fill: parent @@ -127,16 +144,34 @@ Item { ShapePath { fillColor: Theme.surface strokeColor: Theme.hair - strokeWidth: 1 + strokeWidth: panel.outlineWidth startX: 0; startY: panel.offsetY - PathLine { x: panelShape.width - panel.activeChamfer; y: panel.offsetY } - PathLine { x: panelShape.width; y: panel.activeChamfer } + PathLine { x: panelShape.width - panel.rightCut; y: panel.offsetY } + PathLine { x: panelShape.width; y: panel.rightChamfer ? panel.activeChamfer : panel.offsetY } PathLine { x: panelShape.width; y: panelShape.height } - PathLine { x: panel.activeChamfer; y: panelShape.height } - PathLine { x: 0; y: panelShape.height - panel.activeChamfer } + PathLine { x: panel.leftCut; y: panelShape.height } + PathLine { x: 0; y: panelShape.height - panel.leftCut } PathLine { x: 0; y: panel.offsetY } } + // Connecting edges — drawn only on a side whose chamfer is off, which is + // exactly where a neighbour butts against this panel. + ShapePath { + fillColor: "transparent" + strokeColor: Theme.accent + strokeWidth: panel.rightChamfer ? 0 : panel.connectorWidth + startX: panelShape.width; startY: panel.offsetY + PathLine { x: panelShape.width; y: panelShape.height } + } + + ShapePath { + fillColor: "transparent" + strokeColor: Theme.accent + strokeWidth: panel.leftChamfer ? 0 : panel.connectorWidth + startX: 0; startY: panel.offsetY + PathLine { x: 0; y: panelShape.height } + } + // Upper left accent line ShapePath { @@ -154,8 +189,8 @@ Item { fillColor: Theme.accent 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 - panel.accentLineWidth; y: panelShape.height } + PathLine { x: panelShape.width - panel.accentLineWidth; y: panelShape.height - panel.accentLineThickness } PathLine { x: panelShape.width; y: panelShape.height - panel.accentLineThickness } PathLine { x: panelShape.width; y: panelShape.height } }