Repository: status-im/status-desktop
Pull request #17853: fix(Qt6): Broken styling on some platforms 
Author: login: caybro
Created: 2025-04-28T08:15:24Z | Merged: 2025-05-12T13:46:15Z

### What does the PR do

- fix Qt6 styling for Status(Base)Button and StatusChatInput
- remove `Universal` style imports
- bring Qt6 hover effects/events in line with the old behavior of Qt 5, that is when the control is disabled, we get no hover events (changed bg, different cursor shape, etc)
- fix some spurious startup issue (more visible on mac), related to nested `Rectangle` aliased properties

(see the commits for a more detailed description) 

Fixes #17763
Fixes https://github.com/status-im/status-desktop/issues/17693
Fixes https://github.com/status-im/status-desktop/issues/17905

### Affected areas

StatusButton, StatusChatInput

### Architecture compliance

- [x] I am familiar with the application architecture and agreed good practices.
My PR is consistent with this document: [Status Desktop Architecture Guide](https://github.com/status-im/status-desktop/blob/master/CONTRIBUTING.md)

### Screenshot of functionality (including design for comparison)

- [x] I've checked the design and this PR matches it

![image](https://github.com/user-attachments/assets/d9d6d9b8-46a6-472b-9c2e-cfef04b10373)

![image](https://github.com/user-attachments/assets/a7f18b1f-99ae-46bd-883c-9aa5c84f7916)


Linked issue #17763: [Qt 5->6]: Broken styling on some platforms
# Bug Report

## Description

The app styling seems to be broken on some platforms (at least macOS and Windows).
- buttons have a wrong padding
- statusChatInput bas the wrong styling
- Buttons hovering uses some platform specific styling

https://github.com/user-attachments/assets/1c779800-b79a-4ee3-924b-903b80e6877c

<img width="736" alt="Image" src="https://github.com/user-attachments/assets/da7eac74-ab6d-4edb-827c-83531f5005d6" />

<img width="834" alt="Image" src="https://github.com/user-attachments/assets/ba9e4921-c953-4e27-a832-c67343df2ce2" />

## Steps to reproduce

Compile the app using qt6

#### Expected behavior

App styling is identical to qt5

#### Actual behavior

App styling is broken

### Additional Information

- Operating System: MacOs, Windows


Diff:
diff --git a/storybook/main.cpp b/storybook/main.cpp
index 70caf314737..604a5a7f15b 100644
--- a/storybook/main.cpp
+++ b/storybook/main.cpp
@@ -42,7 +42,7 @@ int main(int argc, char *argv[])
     QGuiApplication::setApplicationName(QStringLiteral("Status Desktop Storybook"));
     QGuiApplication::setApplicationDisplayName(QStringLiteral("%1 [Qt %2]").arg(QGuiApplication::applicationName(), qVersion()));
 
-    QQuickStyle::setStyle(QStringLiteral("Universal")); // StatusQ uses this as the default
+    QQuickStyle::setStyle(QStringLiteral("Universal")); // only used as a basic style for SB itself
 
     QCommandLineParser cmdParser;
     cmdParser.addHelpOption();
diff --git a/storybook/main.qml b/storybook/main.qml
index b4c2e9e07af..ac1f47bdef4 100644
--- a/storybook/main.qml
+++ b/storybook/main.qml
@@ -22,7 +22,8 @@ ApplicationWindow {
 
     font.pixelSize: 13
 
-    Universal.theme: darkModeCheckBox.checked ? Universal.Dark : Universal.Light
+    // cf. Universal theme kept here as the basic light/dark theme for the app itself
+    Universal.theme: darkModeCheckBox.checked ? Theme.Style.Dark : Theme.Style.Light
 
     onCurrentPageChanged: {
         testsReRunTimer.restart()
@@ -158,7 +159,7 @@ ApplicationWindow {
                         Layout.fillWidth: true
 
                         text: "Dark mode"
-                        onCheckedChanged: Theme.changeTheme(checked ? Universal.Dark : Universal.Light, !checked)
+                        onCheckedChanged: Theme.changeTheme(checked ? Theme.Style.Dark : Theme.Style.Light, !checked)
                     }
 
                     HotReloaderControls {
diff --git a/storybook/pages/ProfileContextMenuPage.qml b/storybook/pages/ProfileContextMenuPage.qml
index f62eb90e373..b3001d10653 100644
--- a/storybook/pages/ProfileContextMenuPage.qml
+++ b/storybook/pages/ProfileContextMenuPage.qml
@@ -13,57 +13,60 @@ import Models 1.0
 SplitView {
     Logs { id: logs }
 
-    SplitView {
-        orientation: Qt.Vertical
+    Component.onCompleted: contextMenu.open()
+
+    Pane {
         SplitView.fillWidth: true
+        SplitView.fillHeight: true
 
-        Item {
-            SplitView.fillWidth: true
-            SplitView.fillHeight: true
-
-            ProfileContextMenu {
-                anchors.centerIn: parent
-                visible: true
-                closePolicy: Popup.NoAutoClose
-                userIcon: useIconCheckBox.checked ? ModelsData.icons.cryptPunks : ""
-
-                compressedPubKey: "zQ3shQBu4PRDX17veeYYhSczbTjgi44iTXxcMNvQLeyQsBDF4"
-                displayName: displayNameTextField.text
-                hideDisabledItems: hideDisabledCheckBox.checked
-                profileType: profileTypeSelector.currentValue
-                trustStatus: trustStatusSelector.currentValue
-                contactType: contactTypeSelector.currentValue
-                ensVerified: ensVerifiedCheckBox.checked
-                onlineStatus: onlineStatusSelector.currentValue
-                hasLocalNickname: hasLocalNicknameCheckBox.checked
-                chatType: chatTypeSelector.currentValue
-                isAdmin: isAdminCheckBox.checked
-
-                colorHash: [
-                    { segmentLength: 3, colorId: 11 },
-                    { segmentLength: 5, colorId: 9  },
-                    { segmentLength: 1, colorId: 26 },
-                    { segmentLength: 2, colorId: 19 },
-                    { segmentLength: 5, colorId: 17 }
-                ]
-
-                colorId: colorIdSpinBox.value
-
-                onOpenProfileClicked: logs.logEvent("Open profile clicked")
-                onCreateOneToOneChat: logs.logEvent("Create one-to-one chat clicked")
-                onReviewContactRequest: logs.logEvent("Review contact request")
-                onSendContactRequest: logs.logEvent("Send contact request")
-                onEditNickname: logs.logEvent("Edit nickname")
-                onRemoveNickname: logs.logEvent("Remove nickname")
-                onUnblockContact: logs.logEvent("Unblock contact")
-                onMarkAsUntrusted: logs.logEvent("Mark as untrusted")
-                onRemoveTrustStatus: logs.logEvent("Remove trust status")
-                onRemoveContact: logs.logEvent("Remove contact")
-                onBlockContact: logs.logEvent("Block contact")
-                onRemoveFromGroup: logs.logEvent("Remove from group")
-
-                onClosed: open()
-            }
+        Button {
+            anchors.centerIn: parent
+            text: "Open menu"
+            onClicked: contextMenu.open()
+        }
+
+        ProfileContextMenu {
+            id: contextMenu
+            anchors.centerIn: parent
+            closePolicy: Popup.NoAutoClose
+            userIcon: useIconCheckBox.checked ? ModelsData.icons.cryptPunks : ""
+
+            compressedPubKey: "zQ3shQBu4PRDX17veeYYhSczbTjgi44iTXxcMNvQLeyQsBDF4"
+            displayName: displayNameTextField.text
+            hideDisabledItems: hideDisabledCheckBox.checked
+            profileType: profileTypeSelector.currentValue
+            trustStatus: trustStatusSelector.currentValue
+            contactType: contactTypeSelector.currentValue
+            ensVerified: ensVerifiedCheckBox.checked
+            onlineStatus: onlineStatusSelector.currentValue
+            hasLocalNickname: hasLocalNicknameCheckBox.checked
+            chatType: chatTypeSelector.currentValue
+            isAdmin: isAdminCheckBox.checked
+
+            colorHash: [
+                { segmentLength: 3, colorId: 11 },
+                { segmentLength: 5, colorId: 9  },
+                { segmentLength: 1, colorId: 26 },
+                { segmentLength: 2, colorId: 19 },
+                { segmentLength: 5, colorId: 17 }
+            ]
+
+            colorId: colorIdSpinBox.value
+
+            onOpenProfileClicked: logs.logEvent("Open profile clicked")
+            onCreateOneToOneChat: logs.logEvent("Create one-to-one chat clicked")
+            onReviewContactRequest: logs.logEvent("Review contact request")
+            onSendContactRequest: logs.logEvent("Send contact request")
+            onEditNickname: logs.logEvent("Edit nickname")
+            onRemoveNickname: logs.logEvent("Remove nickname")
+            onUnblockContact: logs.logEvent("Unblock contact")
+            onMarkAsUntrusted: logs.logEvent("Mark as untrusted")
+            onRemoveTrustStatus: logs.logEvent("Remove trust status")
+            onRemoveContact: logs.logEvent("Remove contact")
+            onBlockContact: logs.logEvent("Block contact")
+            onRemoveFromGroup: logs.logEvent("Remove from group")
+
+            onClosed: open()
         }
     }
 
diff --git a/storybook/pages/StatusNavBarTabButtonPage.qml b/storybook/pages/StatusNavBarTabButtonPage.qml
index 845bff78136..92b1e4e8235 100644
--- a/storybook/pages/StatusNavBarTabButtonPage.qml
+++ b/storybook/pages/StatusNavBarTabButtonPage.qml
@@ -28,6 +28,11 @@ Item {
             icon.name: "help"
             tooltip.text: "With icon"
         }
+        StatusNavBarTabButton {
+            icon.name: "help"
+            tooltip.text: "Disabled with icon"
+            enabled: false
+        }
         StatusNavBarTabButton {
             icon.source: ModelsData.icons.socks
             tooltip.text: "With image"
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusBaseButton.qml b/ui/StatusQ/src/StatusQ/Controls/StatusBaseButton.qml
index 5cdf4ccd0c1..6a30aa6726e 100644
--- a/ui/StatusQ/src/StatusQ/Controls/StatusBaseButton.qml
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusBaseButton.qml
@@ -7,9 +7,13 @@ import StatusQ.Core.Theme 0.1
 import StatusQ.Components 0.1
 import StatusQ.Core.Utils 0.1
 
-Button {
+AbstractButton {
     id: root
 
+    // compat with `Button`, cf https://bugreports.qt.io/browse/QTBUG-136704
+    property bool flat
+    property bool highlighted
+
     enum Size {
         XSmall,
         Tiny,
@@ -34,6 +38,8 @@ Button {
         color: d.textColor
     }
 
+    hoverEnabled: enabled
+
     property alias tooltip: tooltip
 
     property bool loading
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusIconTabButton.qml b/ui/StatusQ/src/StatusQ/Controls/StatusIconTabButton.qml
index ce0d458ce2c..897bcae5c62 100644
--- a/ui/StatusQ/src/StatusQ/Controls/StatusIconTabButton.qml
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusIconTabButton.qml
@@ -20,6 +20,8 @@ TabButton {
     icon.width: 24
     icon.color: Theme.palette.baseColor1
 
+    hoverEnabled: enabled
+
     contentItem: Item {
         anchors.fill: parent
         StatusSmartIdenticon {
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusTabButton.qml b/ui/StatusQ/src/StatusQ/Controls/StatusTabButton.qml
index eabcb4e5aef..3b400be3786 100644
--- a/ui/StatusQ/src/StatusQ/Controls/StatusTabButton.qml
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusTabButton.qml
@@ -35,6 +35,8 @@ TabButton {
     font.weight: Font.Medium
     font.pixelSize: Theme.primaryTextFontSize
 
+    hoverEnabled: enabled
+
     opacity: enabled ? 1 : Theme.disabledOpacity
 
     spacing: Theme.smallPadding
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml b/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml
index 5f528307675..7a40da62863 100644
--- a/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml
@@ -67,7 +67,7 @@ TextArea {
 
     font {
         family: Theme.baseFont.name
-        pixelSize: 15
+        pixelSize: Theme.primaryTextFontSize
     }
 
     selectByMouse: true
diff --git a/ui/StatusQ/src/StatusQ/Core/Theme/Theme.qml b/ui/StatusQ/src/StatusQ/Core/Theme/Theme.qml
index 65cf5c1c82c..ccde1dfc480 100644
--- a/ui/StatusQ/src/StatusQ/Core/Theme/Theme.qml
+++ b/ui/StatusQ/src/StatusQ/Core/Theme/Theme.qml
@@ -1,7 +1,6 @@
 pragma Singleton
 
 import QtQuick 2.15
-import QtQuick.Controls.Universal 2.15
 
 QtObject {
     enum FontSize {
@@ -13,6 +12,12 @@ QtObject {
         FontSizeXXL
     }
 
+    enum Style {
+        Light,
+        Dark,
+        System
+    }
+
     property ThemePalette palette: StatusLightTheme {}
 
     readonly property ThemePalette statusQLightTheme: StatusLightTheme {}
@@ -22,13 +27,13 @@ QtObject {
 
     function changeTheme(theme:int, isCurrentSystemThemeDark:bool) {
         switch (theme) {
-        case Universal.Light:
+        case Theme.Style.Light:
             Theme.palette = statusQLightTheme
             break
-        case Universal.Dark:
+        case Theme.Style.Dark:
             Theme.palette = statusQDarkTheme
             break
-        case Universal.System:
+        case Theme.Style.System:
             Theme.palette = isCurrentSystemThemeDark ? statusQDarkTheme : statusQLightTheme
             break
         default:
diff --git a/ui/StatusQ/src/StatusQ/Popups/StatusMenu.qml b/ui/StatusQ/src/StatusQ/Popups/StatusMenu.qml
index cb782b894c0..31f90497730 100644
--- a/ui/StatusQ/src/StatusQ/Popups/StatusMenu.qml
+++ b/ui/StatusQ/src/StatusQ/Popups/StatusMenu.qml
@@ -70,8 +70,8 @@ Menu {
 
     dim: false
     closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
-    topPadding: Theme.halfPadding
-    bottomPadding: Theme.halfPadding
+    verticalPadding: Theme.halfPadding
+    horizontalPadding: 0
     margins: Theme.padding
 
     onOpened: {
diff --git a/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml b/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml
index c7c14ea2ddf..040a627d76b 100644
--- a/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml
+++ b/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml
@@ -13,7 +13,9 @@ MenuItem {
     objectName: action ? action.objectName : "StatusMenuItemDelegate"
 
     spacing: 4
-    horizontalPadding: 8
+    horizontalPadding: Theme.halfPadding
+
+    hoverEnabled: enabled
 
     property bool visibleOnDisabled: d.isStatusAction ? action.visibleOnDisabled : false
 
@@ -94,7 +96,7 @@ MenuItem {
         }
 
         readonly property StatusFontSettings defaultFontSettings: StatusFontSettings {
-            pixelSize: 13
+            pixelSize: Theme.additionalTextSize
             bold: false
             italic: false
         }
@@ -178,10 +180,8 @@ MenuItem {
         }
     }
 
-    StatusMouseArea {
-        anchors.fill: parent
-        cursorShape: Qt.PointingHandCursor
-        acceptedButtons: Qt.NoButton
-        hoverEnabled: root.enabled
+    HoverHandler {
+        cursorShape: hovered ? Qt.PointingHandCursor : undefined
+        enabled: root.enabled
     }
 }
diff --git a/ui/app/AppLayouts/Communities/panels/SharedAddressesPermissionsPanel.qml b/ui/app/AppLayouts/Communities/panels/SharedAddressesPermissionsPanel.qml
index 87fb8ebbb3b..09d240def9a 100644
--- a/ui/app/AppLayouts/Communities/panels/SharedAddressesPermissionsPanel.qml
+++ b/ui/app/AppLayouts/Communities/panels/SharedAddressesPermissionsPanel.qml
@@ -515,9 +515,9 @@ Rectangle {
                         id: channelPermsSubPanel
 
                         readonly property int permissionType: modelData
-                        readonly property alias tokenCriteriaMet: overallPermissionRow2.tokenCriteriaMet
+                        readonly property bool tokenCriteriaMet: overallPermissionRow2.tokenCriteriaMet
                         readonly property bool permissionLost: d.initialChannelPermissions[channelPermsPanel.channelKey][index] && !tokenCriteriaMet
-                        readonly property alias channelPermissionsModel: permissionsRepeater2.model
+                        readonly property var channelPermissionsModel: permissionsRepeater2.model
 
                         Layout.fillWidth: true
                         Layout.preferredHeight: grid2.implicitHeight + grid2.anchors.margins*2
diff --git a/ui/app/AppLayouts/Profile/views/AppearanceView.qml b/ui/app/AppLayouts/Profile/views/AppearanceView.qml
index fffc9528346..d69d14b39d1 100644
--- a/ui/app/AppLayouts/Profile/views/AppearanceView.qml
+++ b/ui/app/AppLayouts/Profile/views/AppearanceView.qml
@@ -2,7 +2,6 @@ import QtQuick 2.15
 import QtQuick.Controls 2.15
 import QtQuick.Layouts 1.15
 import QtQuick.Window 2.15
-import QtQuick.Controls.Universal 2.15
 
 import utils 1.0
 import shared 1.0
@@ -140,10 +139,10 @@ SettingsContentBase {
                 Layout.preferredHeight: implicitHeight
                 image.source: Theme.png("appearance-light")
                 control.text: qsTr("Light")
-                control.checked: localAppSettings.theme === Universal.Light
+                control.checked: localAppSettings.theme === Theme.Style.Light
                 onRadioCheckedChanged: {
                     if (checked) {
-                        appearanceView.updateTheme(Universal.Light)
+                        appearanceView.updateTheme(Theme.Style.Light)
                     }
                 }
             }
@@ -152,10 +151,10 @@ SettingsContentBase {
                 Layout.preferredWidth: parent.width/3 - parent.spacing
                 image.source: Theme.png("appearance-dark")
                 control.text: qsTr("Dark")
-                control.checked: localAppSettings.theme === Universal.Dark
+                control.checked: localAppSettings.theme === Theme.Style.Dark
                 onRadioCheckedChanged: {
                     if (checked) {
-                        appearanceView.updateTheme(Universal.Dark)
+                        appearanceView.updateTheme(Theme.Style.Dark)
                     }
                 }
             }
@@ -164,10 +163,10 @@ SettingsContentBase {
                 Layout.preferredWidth: parent.width/3 - parent.spacing
                 image.source: Theme.png("appearance-system")
                 control.text: qsTr("System")
-                control.checked: localAppSettings.theme === Universal.System
+                control.checked: localAppSettings.theme === Theme.Style.System
                 onRadioCheckedChanged: {
                     if (checked) {
-                        appearanceView.updateTheme(Universal.System)
+                        appearanceView.updateTheme(Theme.Style.System)
                     }
                 }
             }
diff --git a/ui/app/AppLayouts/Wallet/views/RightTabView.qml b/ui/app/AppLayouts/Wallet/views/RightTabView.qml
index 6676107c035..707055ae8b3 100644
--- a/ui/app/AppLayouts/Wallet/views/RightTabView.qml
+++ b/ui/app/AppLayouts/Wallet/views/RightTabView.qml
@@ -171,7 +171,7 @@ RightTabBaseView {
                             // TODO remove me when Activity is no longer experimental
                             // Keep Activity as the last tab for now as the Experimental tag don't flow 
                             anchors.top: parent.top
-                            anchors.topMargin: 6
+                            anchors.topMargin: parent.verticalPadding
                             anchors.left: parent.right
                             anchors.leftMargin: 5
                             cursorShape: Qt.PointingHandCursor
diff --git a/ui/imports/shared/status/StatusChatInput.qml b/ui/imports/shared/status/StatusChatInput.qml
index 4f6943625c2..94e07a7533c 100644
--- a/ui/imports/shared/status/StatusChatInput.qml
+++ b/ui/imports/shared/status/StatusChatInput.qml
@@ -1307,7 +1307,7 @@ Rectangle {
                         padding: 0
                         contentWidth: availableWidth
 
-                        TextArea {
+                        StatusQ.StatusTextArea {
                             id: messageInputField
 
                             objectName: "messageInputField"
@@ -1319,17 +1319,13 @@ Rectangle {
                             width: inputScrollView.availableWidth
 
                             textFormat: Text.RichText
-                            font.pixelSize: 15
-                            font.family: Theme.baseFont.name
-                            wrapMode: TextArea.Wrap
                             placeholderText: control.chatInputPlaceholder
-                            placeholderTextColor: Theme.palette.secondaryText
-                            selectByMouse: true
                             color: isEdit ? Theme.palette.directColor1 : Theme.palette.textColor
                             topPadding: 9
                             bottomPadding: 9
                             leftPadding: 0
-                            padding: 0
+                            rightPadding: 0
+                            background: null
                             // This is needed to make sure the text area is disabled when the input is disabled
                             Binding on enabled {
                                 value: control.enabled
@@ -1354,8 +1350,6 @@ Rectangle {
                             }
                             Keys.onReleased: onRelease(event) // gives much more up to date cursorPosition
                             Keys.onShortcutOverride: event.accepted = isUploadFilePressed(event)
-                            selectionColor: Theme.palette.primaryColor2
-                            persistentSelection: true
                             property var keyEvent
 
                             Component.onDestruction: {
@@ -1432,10 +1426,6 @@ Rectangle {
                                 }
                             }
 
-                            cursorDelegate: StatusCursorDelegate {
-                                cursorVisible: messageInputField.cursorVisible
-                            }
-
                             StatusSyntaxHighlighter {
                                 quickTextDocument: messageInputField.textDocument
                                 codeBackgroundColor: Theme.palette.baseColor4
diff --git a/ui/main.qml b/ui/main.qml
index b2b36176aca..be936e9784a 100644
--- a/ui/main.qml
+++ b/ui/main.qml
@@ -5,7 +5,6 @@ import Qt.labs.platform 1.1
 import Qt.labs.settings 1.1
 import QtQuick.Window 2.15
 import QtQml 2.15
-import QtQuick.Controls.Universal 2.15
 
 import utils 1.0
 import shared 1.0
@@ -47,8 +46,6 @@ StatusWindow {
     property MetricsStore metricsStore: MetricsStore {}
     property UtilsStore utilsStore: UtilsStore {}
 
-    Universal.theme: Universal.System
-
     objectName: "mainWindow"
     minimumWidth: 1200
     minimumHeight: 680
@@ -261,14 +258,14 @@ StatusWindow {
     }
 
     function changeThemeFromOutside() {
-        Theme.changeTheme(startupOnboardingLoader.item.visible ? Universal.System : localAppSettings.theme,
+        Theme.changeTheme(startupOnboardingLoader.item.visible ? Theme.Style.System : localAppSettings.theme,
                           systemPalette.isCurrentSystemThemeDark())
     }
 
     Component.onCompleted: {
         console.info(">>> %1 %2 started, using Qt version %3".arg(Qt.application.name).arg(Qt.application.version).arg(SystemUtils.qtRuntimeVersion()))
 
-        Theme.changeTheme(Universal.System, systemPalette.isCurrentSystemThemeDark());
+        Theme.changeTheme(Theme.Style.System, systemPalette.isCurrentSystemThemeDark());
 
         restoreAppState();
 


Reviews:
user: login: micieslak
body: I added Qt bug regarding `enabled` property behavior in context of mouse handling: https://bugreports.qt.io/browse/QTBUG-136598. I'm going to review other problems covered in that pr and report bugs similarly.

I think it's important to not only provide (in our code) workarounds for qt bugs, but also report them to qt to actively help improving the framework.

It also helps in maintenance of our code - we can put link to the qt bug directly next to the workaround we create in our code. It's much easier for reader to understand why things are done in given way (when we do a workaround). And later when updating qt version it's much easier to remove the workaround and make code simpler.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T12:26:19Z
user: login: noeliaSD
body: Just one comment added. The rest LGTM!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T09:47:06Z
user: login: caybro
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T09:49:05Z
user: login: micieslak
body: The styling fix, done in the PR as changing base of `StatusBaseButton` from `Button` to `AbstractButton` is kind of workaround and doesn't solve the root of the problem.

I think it's also not a qt bug even though the behavior is quite confusing and different from Qt 5.

In `Storybook` button's paddings are correct and it's nice hint regarding where is the real problem.
In storybook's main.cpp we call:
```
    QQuickStyle::setStyle(QStringLiteral("Universal"));
```
Thanks to that, the style is set from the very beginning. In the app the style is not set in that way. The only indication for the app to use that style is import of `QtQuick.Controls.Universal`. However the import is after import of `QtQuick.Controls`. That's probably why our binding get overwritten.

So the proper solution of the problem seem to be one of following:
1. Calling `QQuickStyle::setStyle(QStringLiteral("Universal"));` in cpp/nim code.
2. Importing `QtQuick.Controls.Universal` earlier

I did some research and both method works fine. However with reordered imports the app sometimes hangs on startup. It's not clear for me if it's problem caused by reorder or just general issue. It requires further investigation probably.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-06T11:20:31Z
user: login: micieslak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T13:15:57Z
user: login: alexjba
body: Looks good on IOS
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T12:23:13Z
user: login: micieslak
body: Nice!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-12T13:34:21Z
user: login: micieslak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-12T13:35:23Z

Review comments:
diff_hunk: @@ -1,6 +1,7 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.15
 import QtQuick.Layouts 1.15
+import QtQuick.Controls.Universal 2.15
path: ui/imports/shared/status/StatusChatInput.qml
user: login: noeliaSD
body: I think this is unnecessary.
created_at: 2025-05-06T09:46:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,6 +1,7 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.15
 import QtQuick.Layouts 1.15
+import QtQuick.Controls.Universal 2.15
path: ui/imports/shared/status/StatusChatInput.qml
user: login: caybro
body: It is necessary for the tablet, I added it on Alex's request and we tested it together 
created_at: 2025-05-06T09:49:05Z
author_association: MEMBER
diff_hunk: @@ -1,6 +1,7 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.15
 import QtQuick.Layouts 1.15
+import QtQuick.Controls.Universal 2.15
path: ui/imports/shared/status/StatusChatInput.qml
user: login: micieslak
body: This also looks like a bit shady workaround. Probably calling `QQuickStyle::setStyle(QStringLiteral("Universal"));` is remedy for that as well.
created_at: 2025-05-06T13:15:57Z
author_association: MEMBER
diff_hunk: @@ -42,7 +42,7 @@ int main(int argc, char *argv[])
     QGuiApplication::setApplicationName(QStringLiteral("Status Desktop Storybook"));
     QGuiApplication::setApplicationDisplayName(QStringLiteral("%1 [Qt %2]").arg(QGuiApplication::applicationName(), qVersion()));
 
-    QQuickStyle::setStyle(QStringLiteral("Universal")); // StatusQ uses this as the default
+    QQuickStyle::setStyle(QStringLiteral("Universal")); // only used as a basic style for SB itself
path: storybook/main.cpp
user: login: micieslak
body: I would add some small note here that it enforces style which no longer will have any native elements. Like popup animations. Especially that it may be surprising to observe different behavior in Storybook and in the app, where we rely on the native-style base.
created_at: 2025-05-12T13:35:23Z
author_association: MEMBER

PR comments:
user: login: status-im-auto
created_at: 2025-04-28T08:24:34Z
body: 
### Jenkins Builds
<details>
<summary>Click to see older builds (30)</summary>

| :grey_question: | Commit | :hash: | Finished (UTC) | Duration | Platform | Result |
|-|-|-|-|-|-|-|
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/1/) | 2025-04-28 08:24:33 | ~8 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/1//consoleText) |
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/1/) | 2025-04-28 08:24:47 | ~9 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-081545-ea019f-pr17853-aarch64.dmg) |
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/1/) | 2025-04-28 08:29:37 | ~13 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/1//consoleText) |
| :x: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/1/) | 2025-04-28 08:35:22 | ~19 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/1/consoleText) |
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/1/) | 2025-04-28 08:36:26 | ~20 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-081545-ea019f-pr17853-x86_64.dmg) |
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/1/) | 2025-04-28 08:37:50 | ~22 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-081539-ea019f-pr17853-x86_64.tar.gz) |
| :heavy_check_mark: | ea019f22 | [#1](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/1/) | 2025-04-28 08:38:09 | ~22 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-081538-ea019f-pr17853-x86_64.nix.tar.gz) |
| | | | | | | |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/2/) | 2025-04-28 09:03:59 | ~6 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-085730-1db109-pr17853-aarch64.dmg) |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/2/) | 2025-04-28 09:06:09 | ~8 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/2//consoleText) |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/2/) | 2025-04-28 09:10:54 | ~13 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/2//consoleText) |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/2/) | 2025-04-28 09:11:48 | ~14 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-085732-1db109-pr17853-x86_64.dmg) |
| :x: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/2/) | 2025-04-28 09:12:14 | ~14 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/2/consoleText) |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/2/) | 2025-04-28 09:16:07 | ~18 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-085725-1db109-pr17853-x86_64.nix.tar.gz) |
| :heavy_check_mark: | 1db1095c | [#2](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/2/) | 2025-04-28 09:18:42 | ~21 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-085726-1db109-pr17853-x86_64.tar.gz) |
| | | | | | | |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/3/) | 2025-04-28 09:45:20 | ~6 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-093842-03570e-pr17853-aarch64.dmg) |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/3/) | 2025-04-28 09:47:22 | ~8 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/3//consoleText) |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/3/) | 2025-04-28 09:52:41 | ~13 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/3//consoleText) |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/3/) | 2025-04-28 09:52:59 | ~14 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-093843-03570e-pr17853-x86_64.dmg) |
| :x: | 03570eb9 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/4/) | 2025-04-28 09:54:49 | ~16 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/4/consoleText) |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/3/) | 2025-04-28 09:57:45 | ~19 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-093837-03570e-pr17853-x86_64.nix.tar.gz) |
| :heavy_check_mark: | 03570eb9 | [#3](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/3/) | 2025-04-28 09:59:53 | ~21 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-093838-03570e-pr17853-x86_64.tar.gz) |
| :heavy_check_mark: | 03570eb9 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/5/) | 2025-04-28 10:19:23 | ~21 min | `windows/x86_64` | [:cd:`exe`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250428-095819-03570e-pr17853-x86_64.exe) |
| | | | | | | |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/4/) | 2025-05-01 12:30:21 | ~7 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250501-122227-dd6a44-pr17853-aarch64.dmg) |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/4/) | 2025-05-01 12:32:30 | ~10 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/4//consoleText) |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/4/) | 2025-05-01 12:35:41 | ~13 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/4//consoleText) |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/4/) | 2025-05-01 12:38:53 | ~16 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250501-122229-dd6a44-pr17853-x86_64.dmg) |
| :x: | dd6a4433 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/6/) | 2025-05-01 12:40:54 | ~18 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/6/consoleText) |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/4/) | 2025-05-01 12:43:17 | ~20 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250501-122223-dd6a44-pr17853-x86_64.nix.tar.gz) |
| :heavy_check_mark: | dd6a4433 | [#4](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/4/) | 2025-05-01 12:45:22 | ~22 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250501-122224-dd6a44-pr17853-x86_64.tar.gz) |
| :heavy_check_mark: | dd6a4433 | [#7](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/7/) | 2025-05-01 13:19:57 | ~21 min | `windows/x86_64` | [:cd:`exe`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250501-125846-dd6a44-pr17853-x86_64.exe) |
</details>

| :grey_question: | Commit | :hash: | Finished (UTC) | Duration | Platform | Result |
|-|-|-|-|-|-|-|
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/5/) | 2025-05-07 09:58:58 | ~7 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250507-095129-b2533a-pr17853-aarch64.dmg) |
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/5/) | 2025-05-07 10:01:45 | ~10 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/5//consoleText) |
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/5/) | 2025-05-07 10:05:12 | ~13 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/5//consoleText) |
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/5/) | 2025-05-07 10:07:42 | ~16 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250507-095129-b2533a-pr17853-x86_64.dmg) |
| :x: | b2533aa6 | [#8](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/8/) | 2025-05-07 10:10:24 | ~18 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/8/consoleText) |
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/5/) | 2025-05-07 10:13:34 | ~22 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250507-095125-b2533a-pr17853-x86_64.tar.gz) |
| :heavy_check_mark: | b2533aa6 | [#5](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/5/) | 2025-05-07 10:13:53 | ~22 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250507-095122-b2533a-pr17853-x86_64.nix.tar.gz) |
| :heavy_check_mark: | b2533aa6 | [#9](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/9/) | 2025-05-07 10:37:25 | ~26 min | `windows/x86_64` | [:cd:`exe`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250507-101108-b2533a-pr17853-x86_64.exe) |
| | | | | | | |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/aarch64/job/package/job/PR-17853/6/) | 2025-05-12 11:16:21 | ~7 min | `macos/aarch64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250512-110916-627568-pr17853-aarch64.dmg) |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/6/) | 2025-05-12 11:17:24 | ~8 min | `tests/nim` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-nim/job/PR-17853/6//consoleText) |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/6/) | 2025-05-12 11:22:13 | ~12 min | `tests/ui` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/tests-ui/job/PR-17853/6//consoleText) |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/macos/job/x86_64/job/package/job/PR-17853/6/) | 2025-05-12 11:25:44 | ~16 min | `macos/x86_64` | [:apple:`dmg`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250512-110917-627568-pr17853-x86_64.dmg) |
| :x: | 627568b6 | [#10](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/10/) | 2025-05-12 11:26:25 | ~17 min | `windows/x86_64` | [:page_facing_up:`log`](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/10/consoleText) |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package-nix/job/PR-17853/6/) | 2025-05-12 11:29:47 | ~20 min | `linux-nix/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250512-110911-627568-pr17853-x86_64.nix.tar.gz) |
| :heavy_check_mark: | 627568b6 | [#6](https://ci.status.im/job/status-desktop/job/prs/job/linux/job/x86_64/job/package/job/PR-17853/6/) | 2025-05-12 11:30:35 | ~21 min | `linux/x86_64` | [:package:`tgz`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250512-110912-627568-pr17853-x86_64.tar.gz) |
| :heavy_check_mark: | 627568b6 | [#11](https://ci.status.im/job/status-desktop/job/prs/job/windows/job/x86_64/job/package/job/PR-17853/11/) | 2025-05-12 12:17:38 | ~21 min | `windows/x86_64` | [:cd:`exe`](https://status-im-desktop-prs.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-250512-115631-627568-pr17853-x86_64.exe) |

author_association: MEMBER
user: login: caybro
created_at: 2025-05-06T14:59:31Z
body: > The styling fix, done in the PR as changing base of `StatusBaseButton` from `Button` to `AbstractButton` is kind of workaround and doesn't solve the root of the problem.
> 
> I think it's also not a qt bug even though the behavior is quite confusing and different from Qt 5.
> 
> In `Storybook` button's paddings are correct and it's nice hint regarding where is the real problem. In storybook's main.cpp we call:
> 
> ```
>     QQuickStyle::setStyle(QStringLiteral("Universal"));
> ```
> 
> Thanks to that, the style is set from the very beginning. In the app the style is not set in that way. The only indication for the app to use that style is import of `QtQuick.Controls.Universal`. However the import is after import of `QtQuick.Controls`. That's probably why our binding get overwritten.
> 
> So the proper solution of the problem seem to be one of following:
> 
> 1. Calling `QQuickStyle::setStyle(QStringLiteral("Universal"));` in cpp/nim code.
> 2. Importing `QtQuick.Controls.Universal` earlier
> 
> I did some research and both method works fine. However with reordered imports the app sometimes hangs on startup. It's not clear for me if it's problem caused by reorder or just general issue. It requires further investigation probably.

Alright, I'll amend the PR; however, not sure it's possible to do so from NIM (the `QQuickStyle` is not exposed) but it should be possible with some envvar, I'll give it a try
author_association: MEMBER
user: login: alexjba
created_at: 2025-05-07T10:20:20Z
body: > In `Storybook` button's paddings are correct and it's nice hint regarding where is the real problem. In storybook's main.cpp we call:
> 
> ```
>     QQuickStyle::setStyle(QStringLiteral("Universal"));
> ```

I'll do some tests with this and share the results on different platforms. With this approach we'll probably drop any OS specific styling to fix a few cases where the styling is incorrect. So it's a double edged sword
author_association: CONTRIBUTOR
user: login: caybro
created_at: 2025-05-07T10:23:51Z
body: > > In `Storybook` button's paddings are correct and it's nice hint regarding where is the real problem. In storybook's main.cpp we call:
> > ```
> >     QQuickStyle::setStyle(QStringLiteral("Universal"));
> > ```
> 
> I'll do some tests with this and share the results on different platforms. With this approach we'll probably drop any OS specific styling to fix a few cases where the styling is incorrect. So it's a double edged sword

Yeah... that's also true :(
author_association: MEMBER
user: login: alexjba
created_at: 2025-05-08T11:12:39Z
body: Tested on IOS, Android and MacOS.

We're indeed loosing the native feeling of the app. All animations are dropped and the app feels less responsive.
The blocker now is on MacOs where the app is freezing. It seems there's a deadlock in qt when using `QT_QUICK_CONTROLS_STYLE=Universal`. I can see this deadlock only when launching the app from the app package. Inside the app package we have a symlink to the real executable. When launching the real executable directly, the app works fine.

Even without this PR we'll have this difference:

- deadlock
`QT_QUICK_CONTROLS_STYLE=Universal ./bin/StatusDev.app/Contents/MacOS/nim_status_client`

- no deadlock
`QT_QUICK_CONTROLS_STYLE=Universal ./bin/nim_status_client`
author_association: CONTRIBUTOR
user: login: caybro
created_at: 2025-05-08T11:16:14Z
body: > Tested on IOS, Android and MacOS.
> 
> We're indeed loosing the native feeling of the app. All animations are dropped and the app feels less responsive. The blocker now is on MacOs where the app is freezing.

OK, so I'll revert the "Universal" style change, and go back to selective styling fixes only (StatusBaseButton and StatusTextArea) only; CC @micieslak 
author_association: MEMBER
user: login: alexjba
created_at: 2025-05-08T11:37:34Z
body: Tried to reproduce on a smaller scale, but it's not clear what would be the repro steps.

> However with reordered imports the app sometimes hangs on startup.

@micieslak Which imports you've tried to reorder?
author_association: CONTRIBUTOR
user: login: micieslak
created_at: 2025-05-09T16:59:57Z
body: After further research it turns out that style handling has been substantially changed in Qt 6 (at least regarding how the style to be used is determined).

Under Qt 5 we can freely import any style e.g.
```
import QtQuick.Controls.Universal 2.15
```
and that import won't trigger any actual style change in the app.

In the app style is not set explicitly anywhere (like via `QQuickStyle::setStyle` or env variable). It means that we were not using actual `Universal` style. We were only reusing enum defined within that style.

E.g. in `Theme.qml`:

```
    function changeTheme(theme:int, isCurrentSystemThemeDark:bool) {
        switch (theme) {
        case Universal.Light:
            Theme.palette = statusQLightTheme
            break
        case Universal.Dark:
            Theme.palette = statusQDarkTheme
            break
        case Universal.System:
            Theme.palette = isCurrentSystemThemeDark ? statusQDarkTheme : statusQLightTheme
            break
        default:
            console.warn('Unknown theme. Valid themes are "light" and "dark"')
        }
    }
```
With our own enum the app would work in exactly the same way.

In Qt 6 the logic is different.

First, there are two modes (according to https://doc.qt.io/qt-6/qtquickcontrols-styles.html#using-styles-in-qt-quick-controls):

- Compile-Time Style Selection
In that mode `QtQuick.Controls` should not be imported at all. It's not the case in status app.

- Run-Time Style Selection
This mode is enabled by importing `QtQuick.Controls`. And it should be possible to specify style e.g. via `QQuickStyle`. However also in this mode importing custom style triggers style change, sometimes in an unexpected way: https://bugreports.qt.io/browse/QTBUG-136709

Summary
- Using the trick proposed by @caybro (using AbstractButton as base) seems to be good solution for now, as a workaround for https://bugreports.qt.io/browse/QTBUG-136704
- We should remove all imports point to custom theme as it may trigger unintended style change (https://bugreports.qt.io/browse/QTBUG-136709)
- Setting any custom type for the app is probably not an option because only the default system-specific one can provide some nice os-specific native feeling. 

author_association: MEMBER