Build the Panama Hyprland desktop

This commit is contained in:
Gabriel Brown
2026-08-17 10:32:55 -04:00
parent 67033f2a31
commit 5248883e4b
190 changed files with 18554 additions and 34 deletions
@@ -0,0 +1,121 @@
// A GNOME-style slider: a thick rounded track with an inline leading icon,
// used for volume and brightness in the quick settings panel.
//
// Deliberately not QtQuick.Controls.Slider — that pulls in a style plugin and
// fights the theme. This is ~50 lines and does exactly what's needed.
import QtQuick
import Quickshell
import Quickshell.Widgets
import qs.config
Item {
id: root
property real value: 0 // 0.0 .. 1.0
property string icon: ""
property bool enabled: true
// Emitted continuously while dragging.
signal moved(real value)
implicitWidth: 240
implicitHeight: 32
opacity: enabled ? 1.0 : 0.45
// ThemedIcon, not a bare IconImage — see the note in Toggle.qml: Adwaita
// symbolic icons have a hardcoded near-black fill that Qt will not recolour.
ThemedIcon {
id: leadingIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
size: 18
icon: root.icon
tint: Theme.fg
visible: root.icon !== ""
}
Rectangle {
id: track
anchors.left: leadingIcon.visible ? leadingIcon.right : parent.left
anchors.leftMargin: leadingIcon.visible ? 10 : 0
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 10
radius: height / 2
color: Theme.alpha(Theme.fg, 0.12)
border.width: 0
Rectangle {
id: fill
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * Math.max(0, Math.min(1, root.value))
radius: parent.radius
border.width: 0
// The gradient is anchored to the full track, not to the fill, so
// the colour at a given position never moves as the value changes —
// dragging reveals the prism rather than squashing it.
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
position: 0.0
color: Theme.accent
}
GradientStop {
position: 1.0
color: Theme.mix(Theme.accent, Theme.accentSecondary, Math.max(0.001, Math.min(1, root.value)))
}
}
// Only animates when the value changes from outside (e.g. a media
// key); dragging sets it directly and reads as instant.
Behavior on width {
enabled: !drag.pressed
NumberAnimation {
duration: Theme.durFast
easing.type: Easing.OutQuad
}
}
}
Rectangle {
id: knob
width: 16
height: 16
radius: 8
border.width: 0
color: Theme.fg
anchors.verticalCenter: parent.verticalCenter
x: Math.max(0, Math.min(parent.width - width, fill.width - width / 2))
visible: drag.containsMouse || drag.pressed
}
MouseArea {
id: drag
anchors.fill: parent
anchors.margins: -8 // easier to grab than a 10px track
enabled: root.enabled
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
function apply(mouseX) {
const ratio = Math.max(0, Math.min(1, (mouseX + 8) / track.width));
root.moved(ratio);
}
onPressed: event => apply(event.x)
onPositionChanged: event => {
if (pressed)
apply(event.x);
}
onWheel: event => {
const step = event.angleDelta.y > 0 ? 0.05 : -0.05;
root.moved(Math.max(0, Math.min(1, root.value + step)));
}
}
}
}