Compare commits

..

No commits in common. "83d7dc47c432e69aa962646b1181e691bbd2ef01" and "102fa853a83c88fdd469dd9631939265ef5d3e9b" have entirely different histories.

17 changed files with 321 additions and 177 deletions

View file

@ -0,0 +1,70 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
ColumnLayout {
id: root
Loader {
id: sinkLoader
active: sink
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: WrapperItem {
PwNodeLinkTracker {
id: linkTracker
node: sinkLoader.sink
}
ColumnLayout {
Repeater {
model: linkTracker.linkGroups
delegate: Loader {
id: nodeLoader
active: modelData.source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
required property PwLinkGroup modelData
sourceComponent: VolumeCard {
id: nodeCard
node: nodeLoader.modelData.source
text: node.properties["media.name"] ?? ""
// if icon-name is undefined, just gonna fallback on the application name
icon: IconImage {
source: {
if (nodeCard.node.properties["application.icon-name"] !== undefined)
return `image://icon/${nodeCard.node.properties["application.icon-name"]}`;
let applicationName = nodeCard.node.properties["application.name"];
return `image://icon/${applicationName?.toLowerCase() ?? "image-missing"}`;
}
}
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: nodeCard.node.audio.muted ? "volume_off" : "volume_up"
checked: !nodeCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
nodeCard.node.audio.muted = !nodeCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}
}
}
}
}

View file

@ -0,0 +1,65 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.Pipewire
import Quickshell.Widgets
import qs
import qs.widgets
ColumnLayout {
id: root
// headphones
// don't load until the node is not null
Loader {
id: sinkLoader
active: sink !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: VolumeCard {
id: sinkCard
node: sinkLoader.sink
button: StyledMouseArea {
property bool checked: !sinkCard.node.audio.muted
// IconImage {}
onClicked: {
sinkCard.node.audio.muted = !sinkCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
// microphone, same as above
Loader {
id: sourceLoader
active: source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode source: Pipewire.defaultAudioSource
sourceComponent: VolumeCard {
id: sourceCard
node: sourceLoader.source
button: StyledMouseArea {
property bool checked: !sourceCard.node.audio.muted
// IconImage {}
onClicked: {
sourceCard.node.audio.muted = !sourceCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}

View file

@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls
import Quickshell.Widgets import Quickshell.Widgets
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.widgets import qs.widgets
@ -12,34 +13,34 @@ Loader {
active: node != null active: node != null
required property PwNode node required property PwNode node
property string label: node.nickname === "" ? node.description : node.nickname property string label: node.nickname
property Component leftWidget sourceComponent: WrapperRectangle {
id: comp
PwObjectTracker { color: ShellSettings.colors.surface_container_translucent
id: tracker radius: 12
objects: [root.node]
}
sourceComponent: WrapperItem {
margin: 6 margin: 6
border {
width: 1
color: ShellSettings.colors.active_translucent
}
// property Component button
// property Component icon
PwObjectTracker {
id: tracker
objects: [root.node]
}
RowLayout { RowLayout {
spacing: 10
Loader {
id: leftWidget
sourceComponent: root.leftWidget
Layout.preferredWidth: this.height
Layout.fillHeight: true
}
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Text { Text {
text: root.label text: root.label
color: ShellSettings.colors.active color: ShellSettings.colors.active
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
@ -48,6 +49,8 @@ Loader {
StyledSlider { StyledSlider {
value: root.node.audio.volume ?? 0 value: root.node.audio.volume ?? 0
// text: root.text
// icon: root.icon
onValueChanged: { onValueChanged: {
// only allow changes when the node is ready other wise you will combust // only allow changes when the node is ready other wise you will combust
@ -61,6 +64,42 @@ Loader {
Layout.fillHeight: true Layout.fillHeight: true
} }
} }
// StyledMouseArea {
// id: rightArrow
// Layout.preferredWidth: rightArrow.height
// // Layout.fillWidth: true
// Layout.fillHeight: true
//
// IconImage {
// source: "root:resources/general/right-arrow.svg"
// anchors.fill: parent
// }
// }
// Loader {
// id: buttonLoader
// sourceComponent: root.button
//
// Layout.preferredWidth: this.height
// Layout.fillHeight: true
// }
} }
} }
// sourceComponent: VolumeCard {
// id: sinkCard
// node: sinkLoader.sink
// button: StyledMouseArea {
// property bool checked: !sinkCard.node.audio.muted
//
// // IconImage {}
//
// onClicked: {
// sinkCard.node.audio.muted = !sinkCard.node.audio.muted;
// }
// }
//
// anchors.fill: parent
// }
} }

View file

@ -0,0 +1,36 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import qs.widgets
DeviceMixer {}
// WrapperItem {
// id: root
//
// ColumnLayout {
// spacing: 10
//
// // TabBar {
// // id: tabBar
// // model: ["headphones", "tune"]
// // Layout.fillWidth: true
// // Layout.preferredHeight: 35
// // }
//
//
// // StackLayout {
// // id: page
// // currentIndex: tabBar.currentIndex
// // Layout.fillWidth: true
// // Layout.preferredHeight: currentItem ? currentItem.implicitHeight : 0
// //
// // readonly property Item currentItem: children[currentIndex]
// //
// // DeviceMixer {}
// // ApplicationMixer {}
// // }
// }
// }

View file

@ -2,11 +2,11 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Effects
import Quickshell.Widgets import Quickshell.Widgets
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.widgets import qs.widgets
import qs.bar import qs.bar
import qs
StyledMouseArea { StyledMouseArea {
id: root id: root
@ -14,19 +14,14 @@ StyledMouseArea {
required property var bar required property var bar
property bool showMenu: false property bool showMenu: false
property PwNode sink: Pipewire.defaultAudioSink
IconImage { IconImage {
id: icon id: icon
anchors.fill: parent source: "root:resources/volume/volume-full.svg"
source: if (root.sink.audio.muted) {
return "image://icon/audio-volume-muted"; anchors {
} else if (root.sink.audio.volume > 0.66) { fill: parent
return "image://icon/audio-volume-high"; margins: 2
} else if (root.sink.audio.volume > 0.33) {
return "image://icon/audio-volume-medium";
} else {
return "image://icon/audio-volume-low";
} }
} }
@ -37,95 +32,66 @@ StyledMouseArea {
show: root.showMenu show: root.showMenu
onClosed: root.showMenu = false onClosed: root.showMenu = false
implicitWidth: 275 implicitWidth: 300
implicitHeight: container.implicitHeight + (2 * 8) implicitHeight: container.implicitHeight + (2 * 8)
property real entryHeight: 40 property PwNode sink: Pipewire.defaultAudioSink
property real entryHeight: 45
ColumnLayout { ColumnLayout {
id: container id: container
spacing: 2 spacing: 4
anchors { anchors {
fill: parent fill: parent
margins: 4 margins: 8
} }
// Default Audio // Default Audio
VolumeCard { VolumeCard {
id: defaultCard node: menu.sink
node: root.sink
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: menu.entryHeight Layout.preferredHeight: menu.entryHeight
}
leftWidget: StyledMouseArea { Rectangle {
onClicked: defaultCard.node.audio.muted = !defaultCard.node.audio.muted color: ShellSettings.colors.active_translucent
radius: height / 2
IconImage { Layout.leftMargin: 3
anchors.fill: parent Layout.rightMargin: 3
source: if (root.sink.audio.muted) { Layout.fillWidth: true
return "image://icon/audio-volume-muted"; Layout.preferredHeight: 2
} else if (root.sink.audio.volume > 0.66) {
return "image://icon/audio-volume-high";
} else if (root.sink.audio.volume > 0.33) {
return "image://icon/audio-volume-medium";
} else {
return "image://icon/audio-volume-low";
}
}
}
} }
// Application Mixer // Application Mixer
PwNodeLinkTracker { Loader {
id: linkTracker id: sinkLoader
node: root.sink active: menu.sink
}
StyledListView {
id: appList
visible: linkTracker.linkGroups.length !== 0
spacing: 2
model: linkTracker.linkGroups
clip: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: { Layout.preferredHeight: 5 * menu.entryHeight
const entryHeight = Math.min(5, linkTracker.linkGroups.length);
return entryHeight * (menu.entryHeight + appList.spacing); PwNodeLinkTracker {
id: linkTracker
node: menu.sink
} }
delegate: VolumeCard { sourceComponent: ListView {
id: appCard anchors.fill: parent
node: modelData.source spacing: 6
label: node.properties["media.name"] ?? "" model: linkTracker.linkGroups
width: ListView.view.width
height: menu.entryHeight
required property PwLinkGroup modelData delegate: Loader {
id: nodeLoader
active: modelData.source != null
width: ListView.view.width
height: menu.entryHeight
leftWidget: StyledMouseArea { required property PwLinkGroup modelData
onClicked: appCard.node.audio.muted = !appCard.node.audio.muted
IconImage { sourceComponent: VolumeCard {
id: appIcon node: nodeLoader.modelData.source
visible: false label: node.properties["media.name"] ?? ""
anchors.fill: parent
source: {
if (appCard.node.properties["application.icon-name"] !== undefined)
return `image://icon/${appCard.node.properties["application.icon-name"]}`;
let applicationName = appCard.node.properties["application.name"];
return `image://icon/${applicationName?.toLowerCase() ?? "image-missing"}`;
}
}
MultiEffect {
source: appIcon
anchors.fill: appIcon
saturation: appCard.node.audio.muted ? -1.0 : 0.0
} }
} }
} }

View file

@ -64,7 +64,7 @@ Singleton {
anchors { anchors {
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
top: parent.top top: parent.top
topMargin: screen.height / 3 topMargin: screen.height / 2.75
} }
ColumnLayout { ColumnLayout {

BIN
shell/resources/mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="white" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 16c2.206 0 4-1.794 4-4V6c0-2.217-1.785-4.021-3.979-4.021a.933.933 0 0 0-.209.025A4.006 4.006 0 0 0 8 6v6c0 2.206 1.794 4 4 4z"/><path d="M11 19.931V22h2v-2.069c3.939-.495 7-3.858 7-7.931h-2c0 3.309-2.691 6-6 6s-6-2.691-6-6H4c0 4.072 3.061 7.436 7 7.931z"/></svg>

After

Width:  |  Height:  |  Size: 497 B

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="white" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m21.707 20.293-3.4-3.4A7.93 7.93 0 0 0 20 12h-2a5.945 5.945 0 0 1-1.119 3.467l-1.449-1.45A3.926 3.926 0 0 0 16 12V6c0-2.217-1.785-4.021-3.979-4.021-.07 0-.14.009-.209.025A4.006 4.006 0 0 0 8 6v.586L3.707 2.293 2.293 3.707l18 18 1.414-1.414zM6 12H4c0 4.072 3.06 7.436 7 7.931V22h2v-2.069a7.935 7.935 0 0 0 2.241-.63l-1.549-1.548A5.983 5.983 0 0 1 12 18c-3.309 0-6-2.691-6-6z"/><path d="M8.007 12.067a3.996 3.996 0 0 0 3.926 3.926l-3.926-3.926z"/></svg>

After

Width:  |  Height:  |  Size: 682 B

View file

@ -0,0 +1,9 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#ffffff" width="128px" height="128px" viewBox="0 -32 576 576" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<path d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zm233.32-51.08c-11.17-7.33-26.18-4.24-33.51 6.95-7.34 11.17-4.22 26.18 6.95 33.51 66.27 43.49 105.82 116.6 105.82 195.58 0 78.98-39.55 152.09-105.82 195.58-11.17 7.32-14.29 22.34-6.95 33.5 7.04 10.71 21.93 14.56 33.51 6.95C528.27 439.58 576 351.33 576 256S528.27 72.43 448.35 19.97zM480 256c0-63.53-32.06-121.94-85.77-156.24-11.19-7.14-26.03-3.82-33.12 7.46s-3.78 26.21 7.41 33.36C408.27 165.97 432 209.11 432 256s-23.73 90.03-63.48 115.42c-11.19 7.14-14.5 22.07-7.41 33.36 6.51 10.36 21.12 15.14 33.12 7.46C447.94 377.94 480 319.54 480 256zm-141.77-76.87c-11.58-6.33-26.19-2.16-32.61 9.45-6.39 11.61-2.16 26.2 9.45 32.61C327.98 228.28 336 241.63 336 256c0 14.38-8.02 27.72-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.86z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,9 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#ffffff" width="800px" height="800px" viewBox="-64 0 512 512" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<path d="M215.03 72.04L126.06 161H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V89.02c0-21.47-25.96-31.98-40.97-16.98zm123.2 108.08c-11.58-6.33-26.19-2.16-32.61 9.45-6.39 11.61-2.16 26.2 9.45 32.61C327.98 229.28 336 242.62 336 257c0 14.38-8.02 27.72-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.87z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 914 B

View file

@ -0,0 +1,9 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#ffffff" width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<path d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zM461.64 256l45.64-45.64c6.3-6.3 6.3-16.52 0-22.82l-22.82-22.82c-6.3-6.3-16.52-6.3-22.82 0L416 210.36l-45.64-45.64c-6.3-6.3-16.52-6.3-22.82 0l-22.82 22.82c-6.3 6.3-6.3 16.52 0 22.82L370.36 256l-45.63 45.63c-6.3 6.3-6.3 16.52 0 22.82l22.82 22.82c6.3 6.3 16.52 6.3 22.82 0L416 301.64l45.64 45.64c6.3 6.3 16.52 6.3 22.82 0l22.82-22.82c6.3-6.3 6.3-16.52 0-22.82L461.64 256z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1,014 B

View file

@ -0,0 +1,9 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#ffffff" width="800px" height="800px" viewBox="-128 0 512 512" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier">
<path d="M215 71l-89 89H24a24 24 0 0 0-24 24v144a24 24 0 0 0 24 24h102.06L215 441c15 15 41 4.47 41-17V88c0-21.47-26-32-41-17z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 594 B

View file

@ -6,7 +6,7 @@ import QtQuick
import "bar" import "bar"
import "notifications" as Notifications import "notifications" as Notifications
import "mpris" as Mpris import "mpris" as Mpris
import "volosd" as VolumeOSD import "volume-osd" as VolumeOSD
import "settings" as Settings import "settings" as Settings
import "launcher" as Launcher import "launcher" as Launcher
import "lockscreen" as LockScreen import "lockscreen" as LockScreen

View file

@ -21,11 +21,7 @@ Scope {
target: Pipewire.defaultAudioSink?.audio target: Pipewire.defaultAudioSink?.audio
function onVolumeChanged() { function onVolumeChanged() {
root.shouldShowOsd = true; console.log("Volume Changed, showing OSD.");
hideTimer.restart();
}
function onMutedChanged() {
root.shouldShowOsd = true; root.shouldShowOsd = true;
hideTimer.restart(); hideTimer.restart();
} }
@ -57,8 +53,6 @@ Scope {
// radius: 8 // radius: 8
RowLayout { RowLayout {
spacing: 10
anchors { anchors {
fill: parent fill: parent
leftMargin: 10 leftMargin: 10
@ -67,25 +61,15 @@ Scope {
IconImage { IconImage {
implicitSize: 30 implicitSize: 30
source: if (Pipewire.defaultAudioSink?.audio.muted) { source: "root:resources/volume/volume-full.svg"
return "image://icon/audio-volume-muted";
} else if (Pipewire.defaultAudioSink?.audio.volume > 0.66) {
return "image://icon/audio-volume-high";
} else if (Pipewire.defaultAudioSink?.audio.volume > 0.33) {
return "image://icon/audio-volume-medium";
} else {
return "image://icon/audio-volume-low";
}
} }
Rectangle { Rectangle {
id: sliderBackground id: sliderBackground
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 10 implicitHeight: 10
radius: height / 2 radius: 20
color: "transparent" color: ShellSettings.colors.inactive
border.color: ShellSettings.colors.active_translucent
border.width: 1
layer.enabled: true layer.enabled: true
layer.effect: OpacityMask { layer.effect: OpacityMask {
@ -99,13 +83,13 @@ Scope {
Rectangle { Rectangle {
color: ShellSettings.colors.active color: ShellSettings.colors.active
implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0)
anchors { anchors {
left: parent.left left: parent.left
top: parent.top top: parent.top
bottom: parent.bottom bottom: parent.bottom
} }
implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0)
} }
} }
} }

View file

@ -1,53 +0,0 @@
import QtQuick
ListView {
id: root
add: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1
duration: 100
}
}
displaced: Transition {
NumberAnimation {
property: "y"
duration: 200
easing.type: Easing.OutCubic
}
NumberAnimation {
property: "opacity"
to: 1
duration: 100
}
}
move: Transition {
NumberAnimation {
property: "y"
duration: 200
easing.type: Easing.OutCubic
}
NumberAnimation {
property: "opacity"
to: 1
duration: 100
}
}
remove: Transition {
NumberAnimation {
property: "y"
duration: 200
easing.type: Easing.OutCubic
}
NumberAnimation {
property: "opacity"
to: 0
duration: 100
}
}
}

View file

@ -7,18 +7,15 @@ import ".."
Slider { Slider {
id: slider id: slider
implicitHeight: 7 implicitHeight: 8
property var accentColor: ShellSettings.colors.active property var accentColor: ShellSettings.colors.active
background: Rectangle { background: Rectangle {
id: sliderContainer id: sliderContainer
width: slider.availableWidth width: slider.availableWidth
height: slider.implicitHeight height: slider.implicitHeight
color: "transparent" color: ShellSettings.colors.inactive
border.color: ShellSettings.colors.active_translucent radius: 4
border.width: 1
radius: 5
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
layer.enabled: true layer.enabled: true
@ -42,7 +39,7 @@ Slider {
id: fill id: fill
width: slider.handle.width / 2 + slider.visualPosition * (sliderContainer.width - slider.handle.width) width: slider.handle.width / 2 + slider.visualPosition * (sliderContainer.width - slider.handle.width)
height: sliderContainer.height height: sliderContainer.height
color: ShellSettings.colors.active_translucent color: Qt.color(slider.accentColor ?? "purple").darker(1.2)
} }
} }