make buttons ripple

This commit is contained in:
end-4
2025-05-22 19:01:20 +02:00
parent 042a4d1c24
commit 927487c60f
26 changed files with 305 additions and 400 deletions
@@ -115,7 +115,7 @@ Singleton {
property color colLayer2Disabled: ColorUtils.mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: ColorUtils.mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: ColorUtils.mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: ColorUtils.mix(m3colors.m3primary, colLayer1Hover, 0.85)
property color colPrimaryHover: ColorUtils.mix(m3colors.m3primary, colLayer1Hover, 0.87)
property color colPrimaryActive: ColorUtils.mix(m3colors.m3primary, colLayer1Active, 0.7)
property color colPrimaryContainerHover: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
@@ -137,6 +137,7 @@ Singleton {
property int small: 12
property int normal: 17
property int large: 23
property int verylarge: 30
property int full: 9999
property int screenRounding: large
property int windowRounding: 18
@@ -147,7 +148,7 @@ Singleton {
property string main: "Rubik"
property string title: "Gabarito"
property string iconMaterial: "Material Symbols Rounded"
property string iconNerd: "JetBrains Mono NF"
property string iconNerd: "SpaceMono NF"
property string monospace: "JetBrains Mono NF"
property string reading: "Readex Pro"
}
@@ -225,11 +226,16 @@ Singleton {
property int type: Easing.BezierSpline
property list<real> bezierCurve: animationCurves.standardDecel
property int velocity: 850
property Component colorAnimation: Component {ColorAnimation {
property Component colorAnimation: Component { ColorAnimation {
duration: root.animation.elementMoveFast.duration
easing.type: root.animation.elementMoveFast.type
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
}}
property Component numberAnimation: Component { NumberAnimation {
duration: root.animation.elementMoveFast.duration
easing.type: root.animation.elementMoveFast.type
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
}}
}
property QtObject scroll: QtObject {
property int duration: 400
@@ -6,28 +6,13 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Button {
RippleButton {
id: button
property string buttonText
implicitHeight: 30
implicitWidth: buttonTextWidget.implicitWidth + 15 * 2
PointingHandInteraction {}
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active :
((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover :
ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
buttonRadius: Appearance.rounding.full
contentItem: StyledText {
id: buttonTextWidget
@@ -6,33 +6,19 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Button {
RippleButton {
id: button
property string buttonText
buttonRadius: 0
implicitHeight: 36
implicitWidth: buttonTextWidget.implicitWidth + 14 * 2
PointingHandInteraction {}
background: Rectangle {
anchors.fill: parent
color: (button.down && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.84) :
((button.hovered && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.92) :
ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
contentItem: StyledText {
id: buttonTextWidget
anchors.fill: parent
anchors.leftMargin: 14
anchors.rightMargin: 14
text: buttonText
text: button.buttonText
horizontalAlignment: Text.AlignLeft
font.pixelSize: Appearance.font.pixelSize.small
color: button.enabled ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3outline
@@ -6,7 +6,7 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Notifications
Button {
RippleButton {
id: button
property string buttonText
property string urgency
@@ -14,20 +14,10 @@ Button {
implicitHeight: 30
leftPadding: 15
rightPadding: 15
// PointingHandInteraction {}
background: Rectangle {
radius: Appearance.rounding.small
color: (urgency == NotificationUrgency.Critical) ?
(button.down ? Appearance.colors.colSecondaryContainerActive :
button.hovered ? Appearance.colors.colSecondaryContainerHover :
Appearance.m3colors.m3secondaryContainer) :
(button.down ? Appearance.colors.colSurfaceContainerHighestActive :
button.hovered ? Appearance.colors.colSurfaceContainerHighestHover :
Appearance.m3colors.m3surfaceContainerHighest)
}
buttonRadius: Appearance.rounding.small
colBackground: (urgency == NotificationUrgency.Critical) ? Appearance.m3colors.m3secondaryContainer : Appearance.m3colors.m3surfaceContainerHighest
colBackgroundHover: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSurfaceContainerHighestHover
colRipple: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerActive : Appearance.colors.colSurfaceContainerHighestActive
contentItem: StyledText {
horizontalAlignment: Text.AlignHCenter
@@ -389,27 +389,20 @@ Item {
}
}
Button { // Expand button
RippleButton { // Expand button
Layout.alignment: Qt.AlignTop
id: expandButton
implicitWidth: 22
implicitHeight: 22
PointingHandInteraction{}
buttonRadius: Appearance.rounding.full
colBackgroundHover: Appearance.colors.colLayer2Hover
colRipple: Appearance.colors.colLayer2Active
onClicked: {
root.toggleExpanded()
}
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : ColorUtils.transparentize(Appearance.colors.colLayer2, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
contentItem: MaterialSymbol {
anchors.centerIn: parent
text: "keyboard_arrow_down"
@@ -0,0 +1,141 @@
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
Button {
id: root
property bool toggled
property string buttonText
property real buttonRadius: Appearance?.rounding?.small ?? 4
property int rippleDuration: 1200
property color colBackground: ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)
property color colBackgroundHover: Appearance.colors.colLayer1Hover
property color colBackgroundToggled: Appearance.m3colors.m3primary
property color colBackgroundToggledHover: Appearance.colors.colPrimaryHover
property color colRipple: Appearance.colors.colLayer1Active
property color colRippleToggled: Appearance.colors.colPrimaryActive
property color buttonColor: root.enabled ? (root.toggled ?
(root.hovered ? colBackgroundToggledHover :
colBackgroundToggled) :
(root.hovered ? colBackgroundHover :
colBackground)) : colBackground
property color rippleColor: root.toggled ? colRippleToggled : colRipple
component RippleAnim: NumberAnimation {
duration: rippleDuration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animationCurves.standardDecel
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: (event) => {
const {x,y} = event
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();
}
onReleased: (event) => {
root.click() // Because the MouseArea already consumed the event
rippleFadeAnim.restart();
}
onCanceled: (event) => {
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.buttonRadius
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: buttonBackground.radius
}
}
Rectangle {
id: ripple
radius: Appearance.rounding.full
opacity: 0
color: root.rippleColor
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
transform: Translate {
x: -ripple.width / 2
y: -ripple.height / 2
}
}
}
contentItem: StyledText {
text: root.buttonText
}
}