Move shell popups to shared motion

Apply Motion tokens to notification drag and stack transitions, volume OSD feedback, KRunner field state, media controls height changes, and action-button popup affordances. Leave timeout and marquee animations as timing behavior.
This commit is contained in:
Marco Allegretti 2026-05-21 11:13:06 +02:00
parent 1074b86225
commit 7f9087f342
13 changed files with 145 additions and 107 deletions

View file

@ -26,6 +26,9 @@ Window {
property int angle: 0 property int angle: 0
property string iconSource property string iconSource
property bool active: false property bool active: false
readonly property int buttonAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property real hiddenScale: MobileShell.Motion.hiddenScale
readonly property real pressedScale: MobileShell.Motion.pressScaleOut
signal triggered() signal triggered()
@ -82,7 +85,7 @@ Window {
// Hide the root window after the button disappearing animation finishes. // Hide the root window after the button disappearing animation finishes.
Timer { Timer {
id: hideButton id: hideButton
interval: Kirigami.Units.longDuration interval: root.buttonAnimationDuration
repeat: false repeat: false
onTriggered: if (!active) root.visible = false; onTriggered: if (!active) root.visible = false;
} }
@ -101,20 +104,14 @@ Window {
height: root.size height: root.size
opacity: root.active ? 1 : 0 opacity: root.active ? 1 : 0
property double scale: !root.active ? 0.5 : (button.pressed ? 1.5 : 1) property double scale: !root.active ? root.hiddenScale : (button.pressed ? root.pressedScale : 1)
Behavior on scale { Behavior on scale {
NumberAnimation { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.StandardDecel }
duration: Kirigami.Units.longDuration
easing.type: Easing.OutBack
}
} }
Behavior on opacity { Behavior on opacity {
NumberAnimation { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.StandardDecel }
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCirc
}
} }
transform: Scale { transform: Scale {
@ -133,12 +130,20 @@ Window {
Controls.AbstractButton { Controls.AbstractButton {
id: button id: button
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
MobileShell.HapticsEffect { MobileShell.HapticsEffect {
id: haptics id: haptics
} }
contentItem: Item { contentItem: Item {
MobileShell.MotionStateLayer {
anchors.fill: parent
radius: root.size
hovered: button.hovered
pressed: button.pressed
}
Kirigami.Icon { Kirigami.Icon {
anchors.centerIn: parent anchors.centerIn: parent
width: Kirigami.Units.iconSizes.small width: Kirigami.Units.iconSizes.small

View file

@ -28,6 +28,10 @@ Item {
property int popupWidth property int popupWidth
property real openOffset property real openOffset
property bool isConvergence: false property bool isConvergence: false
readonly property int primaryAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.5)
readonly property int secondaryAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
readonly property int stackAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
readonly property int stackMomentumAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 0.5)
// In convergence the popup enters from the bottom-right corner // In convergence the popup enters from the bottom-right corner
readonly property real effectiveOpenOffset: isConvergence readonly property real effectiveOpenOffset: isConvergence
@ -54,7 +58,7 @@ Item {
// due to it not looking great to have a notification sliding up while another one is sliding down // due to it not looking great to have a notification sliding up while another one is sliding down
// we use a timer so that the current notification can know to use "closeWithScale" instead // we use a timer so that the current notification can know to use "closeWithScale" instead
property Timer queueTimer: Timer { property Timer queueTimer: Timer {
interval: Kirigami.Units.veryLongDuration interval: notificationPopup.secondaryAnimationDuration
running: true running: true
onTriggered: { onTriggered: {
visible = true; visible = true;
@ -113,9 +117,9 @@ Item {
// animate the notifications entering and exiting the expanded drawer // animate the notifications entering and exiting the expanded drawer
property real fullOffsetAn: fullOpenOffset property real fullOffsetAn: fullOpenOffset
Behavior on fullOffsetAn { Behavior on fullOffsetAn {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.5 duration: notificationPopup.primaryAnimationDuration
easing.type: Easing.OutExpo type: MobileShell.Motion.SpatialSlow
} }
} }
@ -125,21 +129,21 @@ Item {
// animate this value so that the popup in some situations will not jump around // animate this value so that the popup in some situations will not jump around
property real scaleOriginY: inPopupDrawer && !popupDrawerOpened ? popupNotifications.currentPopupHeight : Math.round(popupHeight / 2) property real scaleOriginY: inPopupDrawer && !popupDrawerOpened ? popupNotifications.currentPopupHeight : Math.round(popupHeight / 2)
Behavior on scaleOriginY { Behavior on scaleOriginY {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration duration: notificationPopup.secondaryAnimationDuration
easing.type: Easing.OutExpo type: MobileShell.Motion.SpatialSlow
} }
} }
// the vertical drag offset for the notification popup // the vertical drag offset for the notification popup
// we drag is released, animate back to 0 // we drag is released, animate back to 0
property real dragOffset: 0 property real dragOffset: 0
NumberAnimation on dragOffset { MobileShell.MotionNumberAnimation on dragOffset {
id: dragOffsetAn id: dragOffsetAn
running: false running: false
to: 0 to: 0
duration: Kirigami.Units.veryLongDuration * 1.5 type: MobileShell.Motion.SpatialSlow
easing.type: Easing.OutExpo duration: notificationPopup.primaryAnimationDuration
} }
// if the popup height ever changes, update the notification below with new height // if the popup height ever changes, update the notification below with new height
@ -385,21 +389,21 @@ Item {
} }
} }
Behavior on drawerScale { Behavior on drawerScale {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25 duration: notificationPopup.stackAnimationDuration
easing.type: Easing.OutQuint type: MobileShell.Motion.Emphasized
} }
} }
Behavior on drawerAddedOffset { Behavior on drawerAddedOffset {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25 duration: notificationPopup.stackAnimationDuration
easing.type: Easing.OutQuint type: MobileShell.Motion.Emphasized
} }
} }
Behavior on drawerOpacity { Behavior on drawerOpacity {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25 duration: notificationPopup.stackAnimationDuration
easing.type: Easing.OutQuint type: MobileShell.Motion.Emphasized
} }
} }
@ -487,27 +491,30 @@ Item {
if (notificationPopup.closedWithSwipe || (topPopup && popupClosing && popupBelow)) { if (notificationPopup.closedWithSwipe || (topPopup && popupClosing && popupBelow)) {
// make sure the speed it faster when closed with a swipe or if there is a popup below when closing // make sure the speed it faster when closed with a swipe or if there is a popup below when closing
// as to make sure the speed feels comparable with the easing type is set to linear // as to make sure the speed feels comparable with the easing type is set to linear
return Kirigami.Units.veryLongDuration * 0.5; return notificationPopup.stackMomentumAnimationDuration;
} else { } else {
return Kirigami.Units.veryLongDuration * 1.25; return notificationPopup.stackAnimationDuration;
} }
} }
transitions: Transition { transitions: Transition {
SequentialAnimation { SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "offset" properties: "offset"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration duration: notificationItem.notificationDuration
} }
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "scale" properties: "scale"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration duration: notificationItem.notificationDuration
} }
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "popupOpacity" properties: "popupOpacity"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration duration: notificationItem.notificationDuration
} }

View file

@ -36,6 +36,7 @@ Window {
// Margin between popup and screen edge in convergence mode; used in both // Margin between popup and screen edge in convergence mode; used in both
// the delegate x position and the input-region calculation so they stay in sync. // the delegate x position and the input-region calculation so they stay in sync.
readonly property real convergencePopupMargin: Kirigami.Units.gridUnit * 2 readonly property real convergencePopupMargin: Kirigami.Units.gridUnit * 2
readonly property int popupAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.5)
property var keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone property var keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone
LayerShell.Window.scope: "notification" LayerShell.Window.scope: "notification"
@ -60,9 +61,9 @@ Window {
readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05) readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05)
color: popupDrawerOpened && visible ? backgroundColor : "transparent" color: popupDrawerOpened && visible ? backgroundColor : "transparent"
Behavior on color { Behavior on color {
ColorAnimation { MobileShell.MotionColorAnimation {
duration: Kirigami.Units.veryLongDuration * 1.5 duration: notificationPopupManager.popupAnimationDuration
easing.type: Easing.OutExpo type: MobileShell.Motion.SpatialSlow
} }
} }
@ -82,7 +83,7 @@ Window {
// hide on timeout to give time to finish animations // hide on timeout to give time to finish animations
Timer { Timer {
id: hideTimeout id: hideTimeout
interval: Kirigami.Units.veryLongDuration * 1.5 interval: notificationPopupManager.popupAnimationDuration
repeat: false repeat: false
onTriggered: if (notifications.count == 0) notificationPopupManager.visible = false; onTriggered: if (notifications.count == 0) notificationPopupManager.visible = false;
} }
@ -153,12 +154,12 @@ Window {
resetContentY.running = true; resetContentY.running = true;
} }
NumberAnimation on contentY { MobileShell.MotionNumberAnimation on contentY {
id: resetContentY id: resetContentY
running: false running: false
to: 0 to: 0
duration: Kirigami.Units.veryLongDuration * 1.5 type: MobileShell.Motion.SpatialSlow
easing.type: Easing.OutExpo duration: notificationPopupManager.popupAnimationDuration
} }
MouseArea { MouseArea {

View file

@ -16,6 +16,7 @@ import org.kde.kquickcontrolsaddons
import org.kde.plasma.core as PlasmaCore import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume import org.kde.plasma.private.volume
import "icon.js" as Icon import "icon.js" as Icon
@ -24,6 +25,8 @@ import "icon.js" as Icon
Controls.AbstractButton { Controls.AbstractButton {
id: baseItem id: baseItem
hoverEnabled: true
property string label property string label
property alias listIcon: clientIcon.source property alias listIcon: clientIcon.source
property string type // sink, source, source-output property string type // sink, source, source-output
@ -46,9 +49,15 @@ Controls.AbstractButton {
background: Rectangle { background: Rectangle {
radius: Kirigami.Units.cornerRadius radius: Kirigami.Units.cornerRadius
color: (baseItem.down) color: "transparent"
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.3)
: 'transparent' MobileShell.MotionStateLayer {
anchors.fill: parent
radius: parent.radius
hovered: baseItem.hovered
pressed: baseItem.down
active: baseItem.selected
}
} }
contentItem: RowLayout { contentItem: RowLayout {
@ -193,12 +202,11 @@ Controls.AbstractButton {
SequentialAnimation { SequentialAnimation {
id: seqAnimation id: seqAnimation
NumberAnimation { MobileShell.MotionNumberAnimation {
id: toAnimation id: toAnimation
target: slider target: slider
property: "to" property: "to"
duration: Kirigami.Units.shortDuration type: MobileShell.Motion.EffectsFast
easing.type: Easing.InOutQuad
} }
ScriptAction { ScriptAction {
script: slider.updateVolume() script: slider.updateVolume()

View file

@ -39,6 +39,7 @@ Window {
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
color: "transparent" color: "transparent"
readonly property int popupAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
function showOverlay() { function showOverlay() {
if (cards.state == "closed") { if (cards.state == "closed") {
@ -116,8 +117,10 @@ Window {
transitions: Transition { transitions: Transition {
SequentialAnimation { SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "offset"; easing.type: cards.state == "open" ? Easing.OutQuint : Easing.InQuint; duration: Kirigami.Units.veryLongDuration * 1.25 properties: "offset"
type: cards.state == "open" ? MobileShell.Motion.Emphasized : MobileShell.Motion.EmphasizedAccel
duration: window.popupAnimationDuration
} }
} }
ScriptAction { ScriptAction {

View file

@ -35,6 +35,7 @@ Window {
LayerShell.Window.exclusionZone: -1 LayerShell.Window.exclusionZone: -1
readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05) readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05)
readonly property int overlayAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
@ -83,7 +84,7 @@ Window {
pressDelay: 50 pressDelay: 50
property real offset: -Kirigami.Units.gridUnit property real offset: -Kirigami.Units.gridUnit
property real scale: 0.95 property real cardScale: 0.95
state: "closed" state: "closed"
@ -94,7 +95,7 @@ Window {
target: flickable; offset: 0 target: flickable; offset: 0
} }
PropertyChanges { PropertyChanges {
target: flickable; scale: 1.0 target: flickable; cardScale: 1.0
} }
PropertyChanges { PropertyChanges {
target: flickable; opacity: 1.0 target: flickable; opacity: 1.0
@ -109,7 +110,7 @@ Window {
target: flickable; offset: -Kirigami.Units.gridUnit * 3 target: flickable; offset: -Kirigami.Units.gridUnit * 3
} }
PropertyChanges { PropertyChanges {
target: flickable; scale: 0.95 target: flickable; cardScale: 0.95
} }
PropertyChanges { PropertyChanges {
target: flickable; opacity: 0.0 target: flickable; opacity: 0.0
@ -123,17 +124,17 @@ Window {
transitions: Transition { transitions: Transition {
SequentialAnimation { SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "offset"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25 properties: "offset"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
} }
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "scale"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25 properties: "cardScale"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
} }
PropertyAnimation { MobileShell.MotionNumberAnimation {
properties: "opacity"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25 properties: "opacity"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
} }
PropertyAnimation { MobileShell.MotionColorAnimation {
properties: "color"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25 properties: "color"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
} }
} }
ScriptAction { ScriptAction {
@ -172,7 +173,7 @@ Window {
Layout.topMargin: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3 Layout.topMargin: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: cards.width Layout.preferredWidth: cards.width
scale: flickable.scale scale: flickable.cardScale
} }
PopupCard { PopupCard {
@ -180,7 +181,7 @@ Window {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: Kirigami.Units.gridUnit Layout.bottomMargin: Kirigami.Units.gridUnit
scaleFactor: flickable.scale scaleFactor: flickable.cardScale
contentItem: PlasmaComponents.ToolButton { contentItem: PlasmaComponents.ToolButton {
id: audioSettingsButton id: audioSettingsButton

View file

@ -12,6 +12,7 @@ import org.kde.kquickcontrolsaddons
import org.kde.plasma.components as PC3 import org.kde.plasma.components as PC3
import org.kde.ksvg as KSvg import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume import org.kde.plasma.private.volume
// Audio volume slider. Value represents desired volume level in // Audio volume slider. Value represents desired volume level in
@ -21,6 +22,7 @@ PC3.Slider {
id: control id: control
property VolumeObject volumeObject property VolumeObject volumeObject
readonly property real mutedOpacity: 0.55
// When muted, the whole slider will appear slightly faded, but remain // When muted, the whole slider will appear slightly faded, but remain
// functional and interactive. // functional and interactive.
@ -37,22 +39,20 @@ PC3.Slider {
} }
Behavior on volume { Behavior on volume {
NumberAnimation { MobileShell.MotionNumberAnimation {
id: animate id: animate
duration: Kirigami.Units.shortDuration type: MobileShell.Motion.EffectsFast
easing.type: Easing.OutQuad
} }
} }
// When a maximum volume limit is raised/lower, animate the change. // When a maximum volume limit is raised/lower, animate the change.
Behavior on to { Behavior on to {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.shortDuration type: MobileShell.Motion.EffectsFast
easing.type: Easing.InOutQuad
} }
} }
opacity: muted ? 0.5 : 1 opacity: muted ? mutedOpacity : 1
// Prevents the groove from showing through the handle // Prevents the groove from showing through the handle
layer.enabled: opacity < 1 layer.enabled: opacity < 1

View file

@ -17,9 +17,18 @@ import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.milou as Milou import org.kde.milou as Milou
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
MouseArea { MouseArea {
id: root id: root
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
readonly property color fieldColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
readonly property color fieldActiveColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.20)
readonly property color resultHoverColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.16)
readonly property color resultPressedColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
onClicked: root.requestedClose(false) onClicked: root.requestedClose(false)
function requestFocus() { function requestFocus() {
@ -54,9 +63,9 @@ MouseArea {
background: Rectangle { background: Rectangle {
radius: Kirigami.Units.cornerRadius radius: Kirigami.Units.cornerRadius
color: Qt.rgba(255, 255, 255, (queryField.hovered || queryField.focus) ? 0.2 : 0.1) color: (queryField.hovered || queryField.focus) ? root.fieldActiveColor : root.fieldColor
Behavior on color { ColorAnimation {} } Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast } }
} }
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
@ -66,8 +75,8 @@ MouseArea {
bottomPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing bottomPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
placeholderText: i18nc("@info:placeholder", "Search…") placeholderText: i18nc("@info:placeholder", "Search…")
placeholderTextColor: Qt.rgba(255, 255, 255, 0.8) placeholderTextColor: Kirigami.Theme.disabledTextColor
color: 'white' color: Kirigami.Theme.textColor
inputMethodHints: Qt.ImhNoPredictiveText // don't need to press "enter" to update text inputMethodHints: Qt.ImhNoPredictiveText // don't need to press "enter" to update text
font.weight: Font.Bold font.weight: Font.Bold
@ -133,7 +142,7 @@ MouseArea {
type: Kirigami.Heading.Primary type: Kirigami.Heading.Primary
text: sectionHeader.section text: sectionHeader.section
elide: Text.ElideRight elide: Text.ElideRight
color: 'white' color: Kirigami.Theme.textColor
// we override the Primary type's font weight (DemiBold) for Bold for contrast with small text // we override the Primary type's font weight (DemiBold) for Bold for contrast with small text
font.weight: Font.Bold font.weight: Font.Bold
@ -176,7 +185,7 @@ MouseArea {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: Kirigami.Units.cornerRadius radius: Kirigami.Units.cornerRadius
color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.3) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.1) : "transparent") color: delegate.pressed ? root.resultPressedColor : (delegate.containsMouse ? root.resultHoverColor : "transparent")
} }
RowLayout { RowLayout {
@ -211,7 +220,7 @@ MouseArea {
maximumLineCount: 1 maximumLineCount: 1
elide: Text.ElideRight elide: Text.ElideRight
text: typeof modelData !== "undefined" ? modelData : model.display text: typeof modelData !== "undefined" ? modelData : model.display
color: "white" color: Kirigami.Theme.textColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize font.pointSize: Kirigami.Theme.defaultFont.pointSize
} }
@ -224,7 +233,7 @@ MouseArea {
maximumLineCount: 1 maximumLineCount: 1
elide: Text.ElideRight elide: Text.ElideRight
text: model.subtext || "" text: model.subtext || ""
color: "white" color: Kirigami.Theme.textColor
opacity: 0.8 opacity: 0.8
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 0.8) font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 0.8)

View file

@ -32,9 +32,9 @@ Item {
implicitHeight: visible ? padding * 2 + contentHeight : 0 implicitHeight: visible ? padding * 2 + contentHeight : 0
Behavior on implicitHeight { Behavior on implicitHeight {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: implicitHeight == 0 ? 0 : Kirigami.Units.longDuration type: MobileShell.Motion.StandardDecel
easing.type: Easing.OutQuart duration: implicitHeight == 0 ? 0 : MobileShell.Motion.duration(type)
} }
} }

View file

@ -68,6 +68,8 @@ Item {
* The current drag offset for this notification. * The current drag offset for this notification.
*/ */
property real dragOffset: 0 property real dragOffset: 0
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property int veryLongAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
signal tapped() signal tapped()
signal dismissRequested() signal dismissRequested()
@ -84,10 +86,10 @@ Item {
implicitHeight: contentParent.implicitHeight implicitHeight: contentParent.implicitHeight
NumberAnimation on dragOffset { MobileShell.MotionNumberAnimation on dragOffset {
id: dragAnim id: dragAnim
duration: Kirigami.Units.longDuration type: MobileShell.Motion.StandardDecel
easing.type: Easing.OutCubic duration: root.longAnimationDuration
onFinished: { onFinished: {
if (to !== 0) { if (to !== 0) {
root.dismissRequested(); root.dismissRequested();
@ -112,9 +114,9 @@ Item {
implicitHeight: inPopupDrawer ? currentPopupHeight : contentParent.implicitHeight implicitHeight: inPopupDrawer ? currentPopupHeight : contentParent.implicitHeight
Behavior on implicitHeight { Behavior on implicitHeight {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration duration: root.veryLongAnimationDuration
easing.type: Easing.OutExpo type: MobileShell.Motion.SpatialSlow
} }
} }
@ -129,9 +131,9 @@ Item {
opacity: closeTimerRunning ? 1 : 0 opacity: closeTimerRunning ? 1 : 0
Behavior on opacity { Behavior on opacity {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.longDuration duration: root.longAnimationDuration
easing.type: Easing.OutQuad type: MobileShell.Motion.StandardDecel
} }
} }

View file

@ -10,12 +10,14 @@ import QtQuick.Layouts 1.1
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell
Item { Item {
id: actionContainer id: actionContainer
required property BaseNotificationItem notification required property BaseNotificationItem notification
property bool popupNotification: false property bool popupNotification: false
readonly property int transitionDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
implicitHeight: Math.max(actionFlow.implicitHeight, replyLoader.height) implicitHeight: Math.max(actionFlow.implicitHeight, replyLoader.height)
visible: actionRepeater.count > 0 visible: actionRepeater.count > 0
@ -31,9 +33,9 @@ Item {
opacity: replyLoader.active ? 0 : 1 opacity: replyLoader.active ? 0 : 1
Behavior on opacity { Behavior on opacity {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.longDuration duration: actionContainer.transitionDuration
easing.type: Easing.InOutQuad type: MobileShell.Motion.Standard
} }
} }
@ -94,15 +96,15 @@ Item {
property bool replying: false property bool replying: false
Behavior on x { Behavior on x {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.longDuration duration: actionContainer.transitionDuration
easing.type: Easing.InOutQuad type: MobileShell.Motion.Standard
} }
} }
Behavior on opacity { Behavior on opacity {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.longDuration duration: actionContainer.transitionDuration
easing.type: Easing.InOutQuad type: MobileShell.Motion.Standard
} }
} }

View file

@ -31,6 +31,7 @@ BaseNotificationItem {
property bool inLockScreen: false property bool inLockScreen: false
property int panelType: MobileShell.PanelBackground.PanelType.Drawer property int panelType: MobileShell.PanelBackground.PanelType.Drawer
readonly property int popupFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
signal dragStart() signal dragStart()
signal dragEnd() signal dragEnd()
@ -69,9 +70,9 @@ BaseNotificationItem {
opacity: notificationItem.inPopupDrawer ? 0 : 1 opacity: notificationItem.inPopupDrawer ? 0 : 1
Behavior on opacity { Behavior on opacity {
NumberAnimation { MobileShell.MotionNumberAnimation {
duration: Kirigami.Units.veryLongDuration duration: notificationItem.popupFadeDuration
easing.type: Easing.OutExpo type: MobileShell.Motion.SpatialSlow
} }
} }

View file

@ -14,7 +14,6 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.clock import org.kde.plasma.clock
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents3 import org.kde.plasma.components 3.0 as PlasmaComponents3
@ -190,7 +189,7 @@ Item {
property NotificationItem pendingNotificationWithAction: null property NotificationItem pendingNotificationWithAction: null
readonly property int animationDuration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0 readonly property int animationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
// If a screen overflow occurs, fix height in order to maintain tool buttons in place. // If a screen overflow occurs, fix height in order to maintain tool buttons in place.
readonly property bool listOverflowing: listHeight + spacing >= root.height readonly property bool listOverflowing: listHeight + spacing >= root.height
@ -271,11 +270,11 @@ Item {
// Run every time an item is visually added to the list, thus when `Show n more` button is clicked as well. // Run every time an item is visually added to the list, thus when `Show n more` button is clicked as well.
add: Transition { add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: list.animationDuration } MobileShell.MotionNumberAnimation { property: "opacity"; from: 0; to: 1; duration: list.animationDuration; type: MobileShell.Motion.Standard }
} }
// Run every time an item is displaced, such as when the order is scrambled due to a group expansion. // Run every time an item is displaced, such as when the order is scrambled due to a group expansion.
displaced: Transition { displaced: Transition {
NumberAnimation { properties: "y"; duration: list.animationDuration } MobileShell.MotionNumberAnimation { properties: "y"; duration: list.animationDuration; type: MobileShell.Motion.Standard }
} }
function isRowExpanded(row) { function isRowExpanded(row) {
@ -325,7 +324,7 @@ Item {
// We have to do this here in order to control the animation before the item is completely removed // We have to do this here in order to control the animation before the item is completely removed
ListView.onRemove: SequentialAnimation { ListView.onRemove: SequentialAnimation {
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: true } PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: true }
NumberAnimation { target: delegateLoader; property: "opacity"; to: 0.0; duration: list.animationDuration } MobileShell.MotionNumberAnimation { target: delegateLoader; property: "opacity"; to: 0.0; duration: list.animationDuration; type: MobileShell.Motion.Standard }
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: false } PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: false }
} }
@ -420,7 +419,7 @@ Item {
to: "VISIBLE" to: "VISIBLE"
SequentialAnimation { SequentialAnimation {
PauseAnimation { duration: list.animationDuration * 2 } PauseAnimation { duration: list.animationDuration * 2 }
NumberAnimation { properties: "opacity"; duration: list.animationDuration } MobileShell.MotionNumberAnimation { properties: "opacity"; duration: list.animationDuration; type: MobileShell.Motion.Standard }
} }
} }