Files
nvrlandClaude Opus 5.5 a8c19961e2 theme: soften the YoRHa shapes; SUPER+D opens the dashboard
The square markers, block meters and hard-cornered fills read as boxy
next to the porthole. The desktop is now soft throughout: the porthole
is the shape everything is built around and every smaller surface echoes
it.

- Theme gains radiusS / radiusM / radiusL. radiusL is frameRadius - padS,
  so anything inset padS inside one of the frame's curves is concentric
  with it.
- P5Panel and Skew draw rounded rectangles (Geom.roundedRect) whenever
  they neither lean nor are chopped, which is always now; the polygon
  path is kept for shapes brought back on purpose.
- Markers are dots; workspace pips, toggles, transport and media chips,
  notification actions and today's date are pills or discs; the slider
  handle is round. Meters are one continuous rounded line that glides to
  its level instead of a row of segments.
- Album art is rounded with ClippingRectangle in the bar, the media
  popout and the dashboard.
- Free-standing panels (launcher, ask) drop the corner brackets and take
  the frame radius.
- Fix: a hovered notification's wash was a full-bleed square, so in the
  drawer's bottom corner it ran past the drawer's curve. It is inset by
  padS/2 and rounded by radiusL, which keeps it inside the curve.

Hyprland: the discord special workspace and its window rule are gone,
SUPER+S stays the only scratchpad, and SUPER+D now opens the dashboard
(it was on SUPER+I).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:56:43 +02:00

134 lines
4.3 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Widgets
import "root:/config"
import "root:/components"
// One line in the result list. Rest is bare — no fill, no border — so a list of
// forty apps reads as a column of text rather than forty boxes. Only the
// selected row gets a slab, and it takes the full inverted treatment: white
// fill, black text. That is the strongest contrast the palette has, which is
// what the row you are about to launch should be wearing.
Item {
id: root
required property var entry
required property bool selected
property bool hovered: false
property string badge: ""
signal activated
signal pinRequested
implicitHeight: 46
// Selection slab. Leans like everything else; drawn as a Skew so the
// diagonals get analytic antialiasing instead of a pixel staircase.
Skew {
anchors.fill: parent
anchors.leftMargin: -Theme.padS
anchors.rightMargin: -Theme.padS
radius: Theme.radiusM
color: root.selected ? Theme.treatmentSelectedFill : "transparent"
opacity: root.selected ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutQuad }
}
}
// Hover is an accent tick in the gutter rather than a second slab, so
// pointing at a row cannot be mistaken for selecting it.
Skew {
anchors.verticalCenter: parent.verticalCenter
x: -Theme.padS
width: 3
height: root.hovered && !root.selected ? parent.height - 10 : 0
color: Theme.accent
Behavior on height {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
}
}
Row {
anchors.fill: parent
anchors.leftMargin: Theme.padM
anchors.rightMargin: Theme.padM
spacing: Theme.padM
IconImage {
anchors.verticalCenter: parent.verticalCenter
implicitSize: 26
asynchronous: true
source: root.entry.icon ? Quickshell.iconPath(root.entry.icon, true) : ""
visible: source !== ""
}
// Entries with no icon still need to occupy the same gutter, or their
// labels wander left and the column stops being a column.
Icon {
anchors.verticalCenter: parent.verticalCenter
width: 26
text: "󰣆"
color: root.selected ? Theme.treatmentSelectedText : Theme.muted
visible: !root.entry.icon && root.entry.kind !== "dmenu"
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - 26 - Theme.padM * 2 - trailing.width
spacing: -1
Text {
width: parent.width
text: root.entry.name
elide: Text.ElideRight
color: root.selected ? Theme.treatmentSelectedText : Theme.text
font.family: Theme.fontMono
font.pixelSize: Theme.fsBody
font.weight: root.selected ? Font.Bold : Theme.weightBody
renderType: Text.NativeRendering
}
Text {
width: parent.width
text: root.entry.sub
visible: text !== ""
elide: Text.ElideRight
color: root.selected ? Theme.alpha(Theme.ink, 0.6) : Theme.muted
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
renderType: Text.NativeRendering
}
}
}
// Trailing hint: the key that fires this row. Only the selected row shows
// one, because a column of ⏎ glyphs tells you nothing.
Text {
id: trailing
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Theme.padM
text: root.selected ? root.badge : ""
color: Theme.alpha(Theme.ink, 0.55)
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
font.letterSpacing: 2
renderType: Text.NativeRendering
}
HoverHandler {
onHoveredChanged: root.hovered = hovered
}
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onTapped: (point, button) => {
if (button === Qt.RightButton) root.pinRequested();
else root.activated();
}
}
}