import QtQuick import QtQuick.Templates as T FocusScope { id: root required property Theme theme property real value: 0 property real step: 0.05 property string accessibleName: "" signal moved(real value) readonly property real boundedValue: Math.max(0, Math.min(1, value)) readonly property bool pressed: slider.pressed readonly property real position: slider.position readonly property real displayedValue: slider.value readonly property Item handle: slider.handle implicitWidth: 120 implicitHeight: 20 activeFocusOnTab: enabled opacity: enabled ? 1 : 0.48 Accessible.name: accessibleName Accessible.ignored: true T.Slider { id: slider anchors.fill: parent focus: true focusPolicy: Qt.ClickFocus hoverEnabled: true from: 0 to: 1 value: root.boundedValue stepSize: root.step snapMode: T.Slider.NoSnap padding: 0 live: true Accessible.name: root.Accessible.name onMoved: root.moved(value) background: Rectangle { x: slider.handle.width / 2 y: (slider.height - height) / 2 width: Math.max(0, slider.width - slider.handle.width) height: slider.hovered || slider.pressed || root.activeFocus ? 8 : 6 radius: height / 2 color: root.theme.withAlpha(root.theme.ui.minor, 0.28) Rectangle { width: parent.width * slider.position height: parent.height radius: parent.radius color: root.theme.ui.accent } } // Fixed geometry keeps both the hit target and value mapping stable // throughout a drag. Press feedback does not resize the handle. handle: Rectangle { x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) y: (slider.height - height) / 2 implicitWidth: 16 implicitHeight: 16 radius: width / 2 color: slider.pressed ? root.theme.ui.accent : root.theme.content.normal border.width: root.activeFocus ? 2 : 1 border.color: root.activeFocus ? root.theme.content.focus : root.theme.withAlpha(root.theme.ui.backdrop, 0.7) } } }