Add animations everywhere

This commit is contained in:
Ly-sec 2025-08-13 15:08:54 +02:00
parent e2a0e491a0
commit bf94ebe46d
11 changed files with 618 additions and 28 deletions

View file

@ -133,11 +133,16 @@ Variants {
const localCenterX = width / 2 const localCenterX = width / 2
const localCenterY = height / 2 const localCenterY = height / 2
const globalPoint = mapToItem(null, localCenterX, localCenterY) const globalPoint = mapToItem(null, localCenterX, localCenterY)
if (sidePanel.isLoaded) if (sidePanel.isLoaded) {
// Call hide() instead of directly setting isLoaded to false
if (sidePanel.item && sidePanel.item.hide) {
sidePanel.item.hide()
} else {
sidePanel.isLoaded = false sidePanel.isLoaded = false
else if (sidePanel.openAt) }
} else if (sidePanel.openAt) {
sidePanel.openAt(globalPoint.x, screen) sidePanel.openAt(globalPoint.x, screen)
else } else {
// Fallback: toggle if API unavailable // Fallback: toggle if API unavailable
sidePanel.isLoaded = true sidePanel.isLoaded = true
} }
@ -146,3 +151,4 @@ Variants {
} }
} }
} }
}

View file

@ -19,7 +19,17 @@ NIconButton {
notificationHistoryPanelLoader.isLoaded = true notificationHistoryPanelLoader.isLoaded = true
} }
if (notificationHistoryPanelLoader.item) { if (notificationHistoryPanelLoader.item) {
notificationHistoryPanelLoader.item.visible = !notificationHistoryPanelLoader.item.visible if (notificationHistoryPanelLoader.item.visible) {
// Panel is visible, hide it with animation
if (notificationHistoryPanelLoader.item.hide) {
notificationHistoryPanelLoader.item.hide()
} else {
notificationHistoryPanelLoader.item.visible = false
}
} else {
// Panel is hidden, show it
notificationHistoryPanelLoader.item.visible = true
}
} }
} }

View file

@ -15,17 +15,56 @@ NLoader {
NPanel { NPanel {
id: notificationPanel id: notificationPanel
// Override hide function to animate first
function hide() {
// Start hide animation
notificationRect.scaleValue = 0.8
notificationRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
Connections { Connections {
target: notificationPanel target: notificationPanel
ignoreUnknownSignals: true ignoreUnknownSignals: true
function onDismissed() { function onDismissed() {
// Start hide animation
notificationRect.scaleValue = 0.8
notificationRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && notificationRect.opacityValue > 0) {
// Start hide animation
notificationRect.scaleValue = 0.8
notificationRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
notificationPanel.visible = false notificationPanel.visible = false
notificationPanel.dismissed()
} }
} }
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
Rectangle { Rectangle {
id: notificationRect
color: Colors.backgroundSecondary color: Colors.backgroundSecondary
radius: Style.radiusMedium * scaling radius: Style.radiusMedium * scaling
border.color: Colors.backgroundTertiary border.color: Colors.backgroundTertiary
@ -37,6 +76,36 @@ NLoader {
anchors.topMargin: Style.marginTiny * scaling anchors.topMargin: Style.marginTiny * scaling
anchors.rightMargin: Style.marginTiny * scaling anchors.rightMargin: Style.marginTiny * scaling
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Style.marginLarge * scaling anchors.margins: Style.marginLarge * scaling
@ -72,7 +141,7 @@ NLoader {
icon: "close" icon: "close"
sizeMultiplier: 0.8 sizeMultiplier: 0.8
onClicked: { onClicked: {
notificationPanel.visible = false notificationPanel.hide()
} }
} }
} }

View file

@ -122,16 +122,91 @@ Item {
NPanel { NPanel {
id: trayPanel id: trayPanel
showOverlay: false // no colors overlay even if activated in settings showOverlay: false // no colors overlay even if activated in settings
// Override hide function to animate first
function hide() {
// Start hide animation
trayMenuRect.scaleValue = 0.8
trayMenuRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
Connections { Connections {
target: trayPanel target: trayPanel
ignoreUnknownSignals: true ignoreUnknownSignals: true
function onDismissed() { function onDismissed() {
// Start hide animation
trayMenuRect.scaleValue = 0.8
trayMenuRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && trayMenuRect.opacityValue > 0) {
// Start hide animation
trayMenuRect.scaleValue = 0.8
trayMenuRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
trayPanel.visible = false trayPanel.visible = false
trayMenu.hideMenu() trayMenu.hideMenu()
} }
} }
Rectangle {
id: trayMenuRect
color: "transparent"
anchors.fill: parent
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
TrayMenu { TrayMenu {
id: trayMenu id: trayMenu
} }
} }
} }
}

View file

@ -29,12 +29,19 @@ NIconButton {
wifiMenuLoader.isLoaded = true wifiMenuLoader.isLoaded = true
} }
if (wifiMenuLoader.item) { if (wifiMenuLoader.item) {
wifiMenuLoader.item.visible = !wifiMenuLoader.item.visible
if (wifiMenuLoader.item.visible) { if (wifiMenuLoader.item.visible) {
network.onMenuOpened() // Panel is visible, hide it with animation
if (wifiMenuLoader.item.hide) {
wifiMenuLoader.item.hide()
} else { } else {
wifiMenuLoader.item.visible = false
network.onMenuClosed() network.onMenuClosed()
} }
} else {
// Panel is hidden, show it
wifiMenuLoader.item.visible = true
network.onMenuOpened()
}
} }
} }

View file

@ -18,11 +18,47 @@ NLoader {
property string passwordInput: "" property string passwordInput: ""
property bool showPasswordPrompt: false property bool showPasswordPrompt: false
function hide() {
wifiMenuRect.scaleValue = 0.8
wifiMenuRect.opacityValue = 0.0
hideTimer.start()
}
// Connect to NPanel's dismissed signal to handle external close events
Connections { Connections {
target: wifiPanel target: wifiPanel
ignoreUnknownSignals: true ignoreUnknownSignals: true
function onDismissed() { function onDismissed() {
// Start hide animation
wifiMenuRect.scaleValue = 0.8
wifiMenuRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && wifiMenuRect.opacityValue > 0) {
// Start hide animation
wifiMenuRect.scaleValue = 0.8
wifiMenuRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
wifiPanel.visible = false wifiPanel.visible = false
wifiPanel.dismissed()
network.onMenuClosed() network.onMenuClosed()
} }
} }
@ -30,6 +66,7 @@ NLoader {
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
Rectangle { Rectangle {
id: wifiMenuRect
color: Colors.backgroundSecondary color: Colors.backgroundSecondary
radius: Style.radiusMedium * scaling radius: Style.radiusMedium * scaling
border.color: Colors.backgroundTertiary border.color: Colors.backgroundTertiary
@ -41,6 +78,34 @@ NLoader {
anchors.topMargin: Style.marginTiny * scaling anchors.topMargin: Style.marginTiny * scaling
anchors.rightMargin: Style.marginTiny * scaling anchors.rightMargin: Style.marginTiny * scaling
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Style.marginLarge * scaling anchors.margins: Style.marginLarge * scaling
@ -87,8 +152,7 @@ NLoader {
icon: "close" icon: "close"
sizeMultiplier: 0.8 sizeMultiplier: 0.8
onClicked: { onClicked: {
wifiPanel.visible = false wifiPanel.hide()
network.onMenuClosed()
} }
} }
} }

View file

@ -15,7 +15,54 @@ NLoader {
readonly property real scaling: Scaling.scale(screen) readonly property real scaling: Scaling.scale(screen)
// Override hide function to animate first
function hide() {
// Start hide animation
calendarRect.scaleValue = 0.8
calendarRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
// Connect to NPanel's dismissed signal to handle external close events
Connections {
target: calendarPanel
function onDismissed() {
// Start hide animation
calendarRect.scaleValue = 0.8
calendarRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && calendarRect.opacityValue > 0) {
// Start hide animation
calendarRect.scaleValue = 0.8
calendarRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
calendarPanel.visible = false
calendarPanel.dismissed()
}
}
Rectangle { Rectangle {
id: calendarRect
color: Colors.backgroundSecondary color: Colors.backgroundSecondary
radius: Style.radiusMedium * scaling radius: Style.radiusMedium * scaling
border.color: Colors.backgroundTertiary border.color: Colors.backgroundTertiary
@ -27,11 +74,41 @@ NLoader {
anchors.topMargin: Style.marginTiny * scaling anchors.topMargin: Style.marginTiny * scaling
anchors.rightMargin: Style.marginTiny * scaling anchors.rightMargin: Style.marginTiny * scaling
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Prevent closing when clicking in the panel bg // Prevent closing when clicking in the panel bg
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
} }
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
// Main Column // Main Column
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent

View file

@ -15,9 +15,54 @@ NLoader {
readonly property real scaling: Scaling.scale(screen) readonly property real scaling: Scaling.scale(screen)
// Override hide function to animate first
function hide() {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
// Connect to NPanel's dismissed signal to handle external close events
Connections {
target: demoPanel
function onDismissed() {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && bgRect.opacityValue > 0) {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
demoPanel.visible = false
demoPanel.dismissed()
}
}
// Ensure panel shows itself once created // Ensure panel shows itself once created
Component.onCompleted: { Component.onCompleted: {
console.log("[DemoPanel] Component completed, showing panel")
show() show()
} }
@ -31,11 +76,41 @@ NLoader {
height: 700 * scaling height: 700 * scaling
anchors.centerIn: parent anchors.centerIn: parent
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Prevent closing when clicking in the panel bg // Prevent closing when clicking in the panel bg
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
} }
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Style.marginXL * scaling anchors.margins: Style.marginXL * scaling

View file

@ -16,6 +16,40 @@ NLoader {
readonly property real scaling: Scaling.scale(screen) readonly property real scaling: Scaling.scale(screen)
// Override hide function to animate first
function hide() {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
// Connect to NPanel's dismissed signal to handle external close events
Connections {
target: panel
function onDismissed() {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
panel.visible = false
panel.dismissed()
}
}
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
property int currentTabIndex: 0 property int currentTabIndex: 0
@ -65,9 +99,18 @@ NLoader {
"source": "Tabs/About.qml" "source": "Tabs/About.qml"
}] }]
// Combined visibility change handler
onVisibleChanged: { onVisibleChanged: {
if (visible) if (visible) {
currentTabIndex = 0 currentTabIndex = 0
} else if (bgRect.opacityValue > 0) {
// Start hide animation
bgRect.scaleValue = 0.8
bgRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
} }
Component.onCompleted: show() Component.onCompleted: show()
@ -83,10 +126,40 @@ NLoader {
height: (screen.height * 0.5) * scaling height: (screen.height * 0.5) * scaling
anchors.centerIn: parent anchors.centerIn: parent
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
} }
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Style.marginLarge * scaling anchors.margins: Style.marginLarge * scaling
@ -196,7 +269,7 @@ NLoader {
tooltipText: "Close" tooltipText: "Close"
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
onClicked: { onClicked: {
settingsPanel.isLoaded = !settingsPanel.isLoaded panel.hide()
} }
} }
} }

View file

@ -41,6 +41,41 @@ NLoader {
// Ensure this panel attaches to the intended screen // Ensure this panel attaches to the intended screen
screen: root.targetScreen screen: root.targetScreen
// Override hide function to animate first
function hide() {
// Start hide animation
panelBackground.scaleValue = 0.8
panelBackground.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
// Connect to NPanel's dismissed signal to handle external close events
Connections {
target: sidePanel
function onDismissed() {
// Start hide animation
panelBackground.scaleValue = 0.8
panelBackground.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Also handle visibility changes from external sources
onVisibleChanged: {
if (!visible && panelBackground.opacityValue > 0) {
// Start hide animation
panelBackground.scaleValue = 0.8
panelBackground.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
}
}
// Ensure panel shows itself once created // Ensure panel shows itself once created
Component.onCompleted: show() Component.onCompleted: show()
@ -62,11 +97,54 @@ NLoader {
x: Math.max(Style.marginSmall * scaling, Math.min(parent.width - width - Style.marginSmall * scaling, x: Math.max(Style.marginSmall * scaling, Math.min(parent.width - width - Style.marginSmall * scaling,
Math.round(anchorX - width / 2))) Math.round(anchorX - width / 2)))
// Animation properties
property real scaleValue: 0.8
property real opacityValue: 0.0
scale: scaleValue
opacity: opacityValue
// Animate in when component is completed
Component.onCompleted: {
scaleValue = 1.0
opacityValue = 1.0
}
// Timer to hide panel after animation
Timer {
id: hideTimer
interval: Style.animationSlow
repeat: false
onTriggered: {
sidePanel.visible = false
sidePanel.dismissed()
}
}
// Prevent closing when clicking in the panel bg // Prevent closing when clicking in the panel bg
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
} }
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationSlow
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
}
// Content wrapper to ensure childrenRect drives implicit height // Content wrapper to ensure childrenRect drives implicit height
Item { Item {
id: content id: content

View file

@ -55,11 +55,23 @@ Window {
x = pos.x - width / 2 + target.width / 2 x = pos.x - width / 2 + target.width / 2
y = pos.y + 12 // 12 px margin below y = pos.y + 12 // 12 px margin below
} }
// Start with animation values
tooltipRect.scaleValue = 0.8
tooltipRect.opacityValue = 0.0
visible = true visible = true
// Use a timer to trigger the animation after the component is visible
showTimer.start()
} }
function _hideNow() { function _hideNow() {
visible = false // Start hide animation
tooltipRect.scaleValue = 0.8
tooltipRect.opacityValue = 0.0
// Hide after animation completes
hideTimer.start()
} }
Connections { Connections {
@ -97,7 +109,30 @@ Window {
} }
} }
// Timer to hide tooltip after animation
Timer {
id: hideTimer
interval: Style.animationNormal
repeat: false
onTriggered: {
visible = false
}
}
// Timer to trigger show animation
Timer {
id: showTimer
interval: 10 // Very short delay to ensure component is visible
repeat: false
onTriggered: {
// Animate to final values
tooltipRect.scaleValue = 1.0
tooltipRect.opacityValue = 1.0
}
}
Rectangle { Rectangle {
id: tooltipRect
anchors.fill: parent anchors.fill: parent
radius: Style.radiusMedium * scaling radius: Style.radiusMedium * scaling
gradient: Gradient { gradient: Gradient {
@ -113,6 +148,27 @@ Window {
border.color: Colors.outline border.color: Colors.outline
border.width: Math.max(1, Style.borderThin * scaling) border.width: Math.max(1, Style.borderThin * scaling)
z: 1 z: 1
// Animation properties
property real scaleValue: 1.0
property real opacityValue: 1.0
scale: scaleValue
opacity: opacityValue
// Animation behaviors
Behavior on scale {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutExpo
}
}
Behavior on opacity {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutQuad
}
} }
NText { NText {
@ -123,6 +179,6 @@ Window {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap wrapMode: Text.Wrap
z: 1 }
} }
} }