aboutsummaryrefslogtreecommitdiffstats
path: root/config/quickshell/modules/common/widgets/RippleButton.qml
diff options
context:
space:
mode:
authorKiran George <kirangeorge1995@gmail.com>2025-06-09 11:30:08 +0530
committerKiran George <kirangeorge1995@gmail.com>2025-06-09 11:30:08 +0530
commit952aa63147c9fb28f6ace6f0bc7ccf45ced1299a (patch)
tree306e6d86603a162c00bc5113b56baac0fe7bec7c /config/quickshell/modules/common/widgets/RippleButton.qml
parent4cf0d0bd5930da76e60f6770de3ee97c10ca7024 (diff)
Overview v2
Diffstat (limited to 'config/quickshell/modules/common/widgets/RippleButton.qml')
-rw-r--r--config/quickshell/modules/common/widgets/RippleButton.qml185
1 files changed, 185 insertions, 0 deletions
diff --git a/config/quickshell/modules/common/widgets/RippleButton.qml b/config/quickshell/modules/common/widgets/RippleButton.qml
new file mode 100644
index 00000000..cd7762b9
--- /dev/null
+++ b/config/quickshell/modules/common/widgets/RippleButton.qml
@@ -0,0 +1,185 @@
+import "root:/modules/common"
+import "root:/modules/common/widgets"
+import "root:/modules/common/functions/color_utils.js" as ColorUtils
+import Qt5Compat.GraphicalEffects
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell.Io
+import Quickshell.Widgets
+
+/**
+ * A button with ripple effect similar to in Material Design.
+ */
+Button {
+ id: root
+ property bool toggled
+ property string buttonText
+ property real buttonRadius: Appearance?.rounding?.small ?? 4
+ property real buttonRadiusPressed: buttonRadius
+ property real buttonEffectiveRadius: root.down ? root.buttonRadiusPressed : root.buttonRadius
+ property int rippleDuration: 1200
+ property bool rippleEnabled: true
+ property var downAction // When left clicking (down)
+ property var releaseAction // When left clicking (release)
+ property var altAction // When right clicking
+ property var middleClickAction // When middle clicking
+
+ property color colBackground: ColorUtils.transparentize(Appearance?.colors.colLayer1Hover, 1) || "transparent"
+ property color colBackgroundHover: Appearance?.colors.colLayer1Hover ?? "#E5DFED"
+ property color colBackgroundToggled: Appearance?.colors.colPrimary ?? "#65558F"
+ property color colBackgroundToggledHover: Appearance?.colors.colPrimaryHover ?? "#77699C"
+ property color colRipple: Appearance?.colors.colLayer1Active ?? "#D6CEE2"
+ property color colRippleToggled: Appearance?.colors.colPrimaryActive ?? "#D6CEE2"
+
+ property color buttonColor: root.enabled ? (root.toggled ?
+ (root.hovered ? colBackgroundToggledHover :
+ colBackgroundToggled) :
+ (root.hovered ? colBackgroundHover :
+ colBackground)) : colBackground
+ property color rippleColor: root.toggled ? colRippleToggled : colRipple
+
+ function startRipple(x, y) {
+ const stateY = buttonBackground.y;
+ rippleAnim.x = x;
+ rippleAnim.y = y - stateY;
+
+ const dist = (ox,oy) => ox*ox + oy*oy
+ const stateEndY = stateY + buttonBackground.height
+ rippleAnim.radius = Math.sqrt(Math.max(dist(0, stateY), dist(0, stateEndY), dist(width, stateY), dist(width, stateEndY)))
+
+ rippleFadeAnim.complete();
+ rippleAnim.restart();
+ }
+
+ component RippleAnim: NumberAnimation {
+ duration: rippleDuration
+ easing.type: Appearance?.animation.elementMoveEnter.type
+ easing.bezierCurve: Appearance?.animationCurves.standardDecel
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+ onPressed: (event) => {
+ if(event.button === Qt.RightButton) {
+ if (root.altAction) root.altAction();
+ return;
+ }
+ if(event.button === Qt.MiddleButton) {
+ if (root.middleClickAction) root.middleClickAction();
+ return;
+ }
+ root.down = true
+ if (root.downAction) root.downAction();
+ if (!root.rippleEnabled) return;
+ const {x,y} = event
+ startRipple(x, y)
+ }
+ onReleased: (event) => {
+ root.down = false
+ if (event.button != Qt.LeftButton) return;
+ if (root.releaseAction) root.releaseAction();
+ root.click() // Because the MouseArea already consumed the event
+ if (!root.rippleEnabled) return;
+ rippleFadeAnim.restart();
+ }
+ onCanceled: (event) => {
+ root.down = false
+ if (!root.rippleEnabled) return;
+ rippleFadeAnim.restart();
+ }
+ }
+
+ RippleAnim {
+ id: rippleFadeAnim
+ target: ripple
+ property: "opacity"
+ to: 0
+ }
+
+ SequentialAnimation {
+ id: rippleAnim
+
+ property real x
+ property real y
+ property real radius
+
+ PropertyAction {
+ target: ripple
+ property: "x"
+ value: rippleAnim.x
+ }
+ PropertyAction {
+ target: ripple
+ property: "y"
+ value: rippleAnim.y
+ }
+ PropertyAction {
+ target: ripple
+ property: "opacity"
+ value: 1
+ }
+ ParallelAnimation {
+ RippleAnim {
+ target: ripple
+ properties: "implicitWidth,implicitHeight"
+ from: 0
+ to: rippleAnim.radius * 2
+ }
+ }
+ }
+
+ background: Rectangle {
+ id: buttonBackground
+ radius: root.buttonEffectiveRadius
+ implicitHeight: 50
+
+ color: root.buttonColor
+ Behavior on color {
+ animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this)
+ }
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Rectangle {
+ width: buttonBackground.width
+ height: buttonBackground.height
+ radius: root.buttonEffectiveRadius
+ }
+ }
+
+ Item {
+ id: ripple
+ width: ripple.implicitWidth
+ height: ripple.implicitHeight
+ opacity: 0
+
+ property real implicitWidth: 0
+ property real implicitHeight: 0
+
+ Behavior on opacity {
+ animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this)
+ }
+
+ RadialGradient {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: root.rippleColor }
+ GradientStop { position: 0.3; color: root.rippleColor }
+ GradientStop { position: 0.5; color: Qt.rgba(root.rippleColor.r, root.rippleColor.g, root.rippleColor.b, 0) }
+ }
+ }
+
+ transform: Translate {
+ x: -ripple.width / 2
+ y: -ripple.height / 2
+ }
+ }
+ }
+
+ contentItem: StyledText {
+ text: root.buttonText
+ }
+}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage