diff --git a/sandbox/main.qml b/sandbox/main.qml
index f80da55a..c436414e 100644
--- a/sandbox/main.qml
+++ b/sandbox/main.qml
@@ -300,12 +300,16 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
-
StatusNavigationListItem {
title: "StatusModal"
selected: viewLoader.source.toString().includes("Popups")
onClicked: mainPageView.control("Popups");
}
+ StatusNavigationListItem {
+ title: "StatusDialog"
+ selected: viewLoader.source.toString().includes(title)
+ onClicked: mainPageView.page(title);
+ }
StatusListSectionHeadline { text: "StatusQ.Platform" }
StatusNavigationListItem {
title: "StatusMacNotification"
diff --git a/sandbox/pages/StatusDialogPage.qml b/sandbox/pages/StatusDialogPage.qml
new file mode 100644
index 00000000..04bdd40f
--- /dev/null
+++ b/sandbox/pages/StatusDialogPage.qml
@@ -0,0 +1,282 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+import QtQml.Models 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Controls 0.1
+import StatusQ.Popups.Dialog 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Components 0.1
+
+ColumnLayout {
+ id: root
+
+ StatusButton {
+ text: "Content"
+ onClicked: contentDialog.open()
+
+ StatusDialog {
+ id: contentDialog
+
+ standardButtons: Dialog.ApplyRole
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Title and content"
+ onClicked: titleContentDialog.open()
+
+ StatusDialog {
+ id: titleContentDialog
+ title: "Title"
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "No buttons"
+ onClicked: noButtonsDialog.open()
+
+ StatusDialog {
+ id: noButtonsDialog
+ title: "No buttons"
+
+ standardButtons: Dialog.NoButton
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Long title"
+ onClicked: longTitleDialog.open()
+
+ StatusDialog {
+ id: longTitleDialog
+ title: "Long title long title Long title long title Long title long title"
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Long title elided"
+ onClicked: longTitleElidedDialog.open()
+
+ StatusDialog {
+ id: longTitleElidedDialog
+ title: "Long title long title Long title long title Long title long title"
+
+ width: 400
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Title subtitle"
+ onClicked: titleSubtitleDialog.open()
+
+ StatusDialog {
+ id: titleSubtitleDialog
+ title: "This title will be ignored"
+
+ header: StatusDialogHeader {
+ headline.title: "Title"
+ headline.subtitle: "Subtitle"
+
+ actions.closeButton.onClicked: titleSubtitleDialog.close()
+ }
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Auto adjustable"
+ onClicked: autoAdjustableDialog.open()
+
+ StatusDialog {
+ id: autoAdjustableDialog
+
+ header: StatusDialogHeader {
+ headline.title: "Dialog size will auto adapt"
+ headline.subtitle: "To conent size"
+
+ actions.closeButton.onClicked: autoAdjustableDialog.close()
+ }
+
+ footer: StatusDialogFooter {
+ leftButtons: ObjectModel {
+ StatusRoundButton {
+ icon.name: "arrow-left"
+ onClicked: autoAdjustableDialogContent.implicitWidth -= 100
+ }
+ StatusRoundButton {
+ icon.name: "arrow-right"
+ onClicked: autoAdjustableDialogContent.implicitWidth += 100
+ }
+ }
+ rightButtons: ObjectModel {
+ StatusRoundButton {
+ icon.name: "arrow-down"
+ onClicked: autoAdjustableDialogContent.implicitHeight -= 100
+ }
+ StatusRoundButton {
+ icon.name: "arrow-up"
+ onClicked: autoAdjustableDialogContent.implicitHeight += 100
+ }
+ }
+ }
+
+ Rectangle {
+ id: autoAdjustableDialogContent
+
+ anchors.fill: parent
+
+ implicitWidth: 200
+ implicitHeight: 200
+
+ color: Theme.palette.primaryColor3
+
+ StatusBaseText {
+ anchors.centerIn: parent
+ text: "W: %1 H: %2\nIW: %3 IH: %4".arg(parent.width).arg(parent.height).arg(parent.implicitWidth).arg(parent.implicitHeight)
+ }
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Complex dialog"
+ onClicked: complexDialog.open()
+
+ StatusDialog {
+ id: complexDialog
+
+ header: StatusDialogHeader {
+ id: dialogHeader
+
+ headline.title: "Complex dialog"
+ headline.subtitle: "identicon, title subtitle, custom actions"
+
+ leftComponent: StatusLetterIdenticon {
+ name: dialogHeader.headline.title
+ }
+
+ actions {
+ infoButton.visible: true
+
+ customButtons: ObjectModel {
+ StatusFlatRoundButton {
+ icon.name: "warning"
+ icon.width: 20
+ icon.height: 20
+ }
+ }
+
+ closeButton.onClicked: complexDialog.close()
+ }
+ }
+
+ footer: StatusDialogFooter {
+ leftButtons: ObjectModel {
+ StatusRoundButton {
+ icon.name: "arrow-left"
+ }
+ }
+ rightButtons: ObjectModel {
+ StatusButton {
+ text: "Custom cancel action"
+ type: StatusButton.Danger
+ }
+ StatusButton {
+ text: "Custom approve action"
+ }
+ }
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ StatusBaseText {
+ text: "Content A"
+ }
+
+ StatusBaseText {
+ text: "Content B"
+ }
+
+ StatusBaseText {
+ text: "Content C"
+ }
+ }
+ }
+ }
+
+ StatusButton {
+ text: "Custom header/footer"
+ onClicked: customHeaderAndFooter.open()
+
+ StatusDialog {
+ id: customHeaderAndFooter
+ title: "No buttons"
+
+ header: Rectangle {
+ implicitHeight: customHeaderText.height * 2
+ implicitWidth: customHeaderText.width * 2
+
+ border.width: 2
+ color: Theme.palette.statusPopupMenu.hoverBackgroundColor
+
+ StatusBaseText {
+ id: customHeaderText
+ anchors.centerIn: parent
+ text: "Custom header"
+ }
+ }
+
+ footer: Rectangle {
+ implicitHeight: customHeaderText.height * 2
+ implicitWidth: customHeaderText.width * 2
+
+ border.width: 2
+ color: Theme.palette.statusPopupMenu.hoverBackgroundColor
+
+ StatusBaseText {
+ id: customFooter
+ anchors.centerIn: parent
+ text: "Custom footer"
+ }
+ }
+
+
+ StatusBaseText {
+ anchors.fill: parent
+ text: "Content"
+ }
+ }
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusDialog.qml b/src/StatusQ/Popups/Dialog/StatusDialog.qml
new file mode 100644
index 00000000..ffd3a717
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusDialog.qml
@@ -0,0 +1,104 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+import QtQml.Models 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Controls 0.1
+import StatusQ.Core.Theme 0.1
+
+Dialog {
+ id: root
+
+ anchors.centerIn: Overlay.overlay
+
+ padding: 16
+ margins: 64
+ modal: true
+
+ standardButtons: Dialog.Cancel | Dialog.Ok
+
+ Overlay.modal: Rectangle {
+ color: Theme.palette.backdropColor
+ }
+
+ background: Rectangle {
+ color: Theme.palette.statusModal.backgroundColor
+ radius: 8
+ }
+
+ header: StatusDialogHeader {
+ visible: root.title
+ headline.title: root.title
+ actions.closeButton.onClicked: root.close()
+ }
+
+ footer: StatusDialogFooter {
+ id: footerItem
+
+ readonly property int rejectRoleFlags: Dialog.Cancel | Dialog.Close | Dialog.Abort
+ readonly property int noRoleFlags: Dialog.No | Dialog.NoToAll
+ readonly property int acceptRoleFlags: Dialog.Ok | Dialog.Open | Dialog.Save | Dialog.SaveAll | Dialog.Retry | Dialog.Ignore
+ readonly property int yesRoleFlags: Dialog.Yes | Dialog.YesToAll
+
+ visible: rightButtons &&
+ root.standardButtons & (rejectRoleFlags | noRoleFlags | acceptRoleFlags | yesRoleFlags | Dialog.ApplyRole)
+
+ rightButtons: ObjectModel {
+ StatusButton {
+ visible: root.standardButtons & footerItem.rejectRoleFlags
+ type: StatusButton.Danger
+ text: {
+ if (root.standardButtons & Dialog.Close) return qsTr("Close")
+ if (root.standardButtons & Dialog.Abort) return qsTr("Abort")
+ return qsTr("Cancel")
+ }
+
+ onClicked: root.reject()
+ }
+
+ StatusButton {
+ visible: root.standardButtons & footerItem.noRoleFlags
+ type: StatusButton.Danger
+ text: {
+ if (root.standardButtons & Dialog.NoToAll) return qsTr("No to all")
+ return qsTr("No")
+ }
+
+ onClicked: root.reject()
+ }
+
+ StatusButton {
+ visible: root.standardButtons & footerItem.acceptRoleFlags
+ text: {
+ if (root.standardButtons & Dialog.Open) return qsTr("Open")
+ if (root.standardButtons & Dialog.Save) return qsTr("Save")
+ if (root.standardButtons & Dialog.SaveAll) return qsTr("Save all")
+ if (root.standardButtons & Dialog.Retry) return qsTr("Retry")
+ if (root.standardButtons & Dialog.Ignore) return qsTr("Ignore")
+ return qsTr("Ok")
+ }
+
+ onClicked: root.accept()
+ }
+
+ StatusButton {
+ visible: root.standardButtons & footerItem.yesRoleFlags
+ type: StatusButton.Danger
+ text: {
+ if (root.standardButtons & Dialog.YesToAll) return qsTr("Yes to all")
+ return qsTr("Yes")
+ }
+
+ onClicked: root.accept()
+ }
+
+ StatusButton {
+ visible: root.standardButtons & Dialog.ApplyRole
+ text: qsTr("Apply")
+
+ onClicked: root.applied()
+ }
+ }
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusDialogDivider.qml b/src/StatusQ/Popups/Dialog/StatusDialogDivider.qml
new file mode 100644
index 00000000..bc15a91a
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusDialogDivider.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.14
+
+import StatusQ.Core.Theme 0.1
+
+Rectangle {
+ color: Theme.palette.baseColor2
+ implicitHeight: 1
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusDialogFooter.qml b/src/StatusQ/Popups/Dialog/StatusDialogFooter.qml
new file mode 100644
index 00000000..e650e0d7
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusDialogFooter.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.14
+import QtQuick.Layouts 1.14
+import QtQml.Models 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+
+Rectangle {
+ id: root
+
+ property ObjectModel leftButtons
+ property ObjectModel rightButtons
+
+ color: Theme.palette.statusModal.backgroundColor
+ radius: 8
+
+ implicitHeight: layout.implicitHeight + layout.anchors.topMargin + layout.anchors.bottomMargin
+ implicitWidth: layout.implicitWidth + layout.anchors.leftMargin + layout.anchors.rightMargin
+
+ RowLayout {
+ id: layout
+
+ clip: true
+
+ anchors {
+ fill: parent
+ margins: 16
+ }
+
+ Repeater {
+ model: root.leftButtons
+ onItemAdded: item.Layout.fillHeight = true
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Repeater {
+ model: root.rightButtons
+ onItemAdded: item.Layout.fillHeight = true
+ }
+ }
+
+ StatusDialogDivider {
+ width: parent.width
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusDialogHeader.qml b/src/StatusQ/Popups/Dialog/StatusDialogHeader.qml
new file mode 100644
index 00000000..91156524
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusDialogHeader.qml
@@ -0,0 +1,58 @@
+import QtQuick 2.14
+import QtQuick.Layouts 1.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+
+Rectangle {
+ id: root
+
+ readonly property alias headline: headline
+ readonly property alias actions: actions
+
+ property alias leftComponent: leftComponentLoader.sourceComponent
+
+ color: Theme.palette.statusModal.backgroundColor
+ radius: 8
+
+ implicitHeight: layout.implicitHeight + layout.anchors.topMargin + layout.anchors.bottomMargin
+ implicitWidth: layout.implicitWidth + layout.anchors.leftMargin + layout.anchors.rightMargin
+
+ RowLayout {
+ id: layout
+
+ clip: true
+
+ anchors {
+ fill: parent
+ margins: 16
+ }
+
+ spacing: 8
+
+ Loader {
+ id: leftComponentLoader
+
+ Layout.fillHeight: true
+ visible: sourceComponent
+ }
+
+ StatusTitleSubtitle {
+ id: headline
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ StatusHeaderActions {
+ id: actions
+
+ Layout.alignment: Qt.AlignTop
+ }
+ }
+
+ StatusDialogDivider {
+ anchors.bottom: parent.bottom
+ width: parent.width
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusHeaderActions.qml b/src/StatusQ/Popups/Dialog/StatusHeaderActions.qml
new file mode 100644
index 00000000..05be23fd
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusHeaderActions.qml
@@ -0,0 +1,70 @@
+import QtQuick 2.14
+import QtQuick.Layouts 1.14
+import QtQml.Models 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Controls 0.1
+
+Item {
+ id: root
+
+ property ObjectModel customButtons
+
+ readonly property alias closeButton: closeButton
+ readonly property alias infoButton: infoButton
+
+ implicitHeight: layout.implicitHeight
+ implicitWidth: layout.implicitWidth
+
+ QtObject {
+ id: d
+ readonly property int buttonSize: 32
+ readonly property int iconSize: 20
+ }
+
+ RowLayout {
+ id: layout
+
+ anchors.fill: parent
+
+ Repeater {
+ model: root.customButtons
+ onItemAdded: {
+ item.Layout.fillHeight = true
+ item.Layout.preferredHeight = d.buttonSize
+ item.Layout.preferredWidth = d.buttonSize
+ }
+ }
+
+ StatusFlatRoundButton {
+ id: infoButton
+
+ Layout.fillHeight: true
+ Layout.preferredHeight: d.buttonSize
+ Layout.preferredWidth: d.buttonSize
+
+ visible: false
+
+ type: StatusFlatRoundButton.Type.Secondary
+ icon.name: "info"
+ icon.color: Theme.palette.directColor1
+ icon.width: d.iconSize
+ icon.height: d.iconSize
+ }
+
+ StatusFlatRoundButton {
+ id: closeButton
+
+ Layout.fillHeight: true
+ Layout.preferredHeight: d.buttonSize
+ Layout.preferredWidth: d.buttonSize
+
+ type: StatusFlatRoundButton.Type.Secondary
+ icon.name: "close"
+ icon.color: Theme.palette.directColor1
+ icon.width: d.iconSize
+ icon.height: d.iconSize
+ }
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/StatusTitleSubtitle.qml b/src/StatusQ/Popups/Dialog/StatusTitleSubtitle.qml
new file mode 100644
index 00000000..92fa044a
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/StatusTitleSubtitle.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.14
+import QtQuick.Layouts 1.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+
+Item {
+ id: root
+
+ property alias title: title.text
+ property alias subtitle: subtitle.text
+
+ implicitHeight: layout.implicitHeight
+ implicitWidth: layout.implicitWidth
+
+ ColumnLayout {
+ id: layout
+
+ anchors.fill: parent
+ spacing: 0
+
+ StatusBaseText {
+ id: title
+
+ Layout.fillWidth: true
+
+ color: Theme.palette.directColor1
+ font {
+ family: Theme.palette.baseFont.name
+ pixelSize: 17
+ bold: true
+ }
+ elide: Text.ElideMiddle
+ }
+
+ StatusBaseText {
+ id: subtitle
+
+ Layout.fillWidth: true
+
+ visible: text !== ""
+ color: Theme.palette.baseColor1
+ font {
+ family: Theme.palette.baseFont.name
+ pixelSize: 15
+ }
+ elide: Text.ElideMiddle
+ }
+ }
+}
diff --git a/src/StatusQ/Popups/Dialog/qmldir b/src/StatusQ/Popups/Dialog/qmldir
new file mode 100644
index 00000000..f06e149e
--- /dev/null
+++ b/src/StatusQ/Popups/Dialog/qmldir
@@ -0,0 +1,8 @@
+module StatusQ.Popups.Dialog
+
+StatusDialog 0.1 StatusDialog.qml
+StatusDialogDivider 0.1 StatusDialogDivider.qml
+StatusDialogFooter 0.1 StatusDialogFooter.qml
+StatusDialogHeader 0.1 StatusDialogHeader.qml
+StatusHeaderActions 0.1 StatusHeaderActions.qml
+StatusTitleSubtitle 0.1 StatusTitleSubtitle.qml
diff --git a/src/StatusQ/Popups/StatusModal.qml b/src/StatusQ/Popups/StatusModal.qml
index 0cb83606..ae0c144a 100644
--- a/src/StatusQ/Popups/StatusModal.qml
+++ b/src/StatusQ/Popups/StatusModal.qml
@@ -50,6 +50,9 @@ import "statusModal" as Spares
For a list of components available see StatusQ.
*/
+
+// Deprecation annotations come with Qt6.2
+// @Deprecated { reason: "Use StatusDialog instead, see reasoning: https://github.com/status-im/StatusQ/issues/720" }
QC.Popup {
id: statusModal
diff --git a/src/StatusQ/Popups/qmldir b/src/StatusQ/Popups/qmldir
index 381befc9..02ceb60b 100644
--- a/src/StatusQ/Popups/qmldir
+++ b/src/StatusQ/Popups/qmldir
@@ -7,6 +7,7 @@ StatusMenuItemDelegate 0.1 StatusMenuItemDelegate.qml
StatusMenuHeadline 0.1 StatusMenuHeadline.qml
StatusModal 0.1 StatusModal.qml
StatusStackModal 0.1 StatusStackModal.qml
+StatusDialog 0.1 StatusDialog.qml
StatusSearchPopup 0.1 StatusSearchPopup.qml
StatusModalDivider 0.1 StatusModalDivider.qml
StatusSearchPopupMenuItem 0.1 StatusSearchPopupMenuItem.qml
diff --git a/statusq.qrc b/statusq.qrc
index e553be83..d85db052 100644
--- a/statusq.qrc
+++ b/statusq.qrc
@@ -10502,5 +10502,12 @@
src/StatusQ/Animations/SkeletonGradientStop.qml
src/StatusQ/Animations/qmldir
src/assets/img/icons/arrow-up.svg
+ src/StatusQ/Popups/Dialog/qmldir
+ src/StatusQ/Popups/Dialog/StatusDialog.qml
+ src/StatusQ/Popups/Dialog/StatusTitleSubtitle.qml
+ src/StatusQ/Popups/Dialog/StatusHeaderActions.qml
+ src/StatusQ/Popups/Dialog/StatusDialogHeader.qml
+ src/StatusQ/Popups/Dialog/StatusDialogFooter.qml
+ src/StatusQ/Popups/Dialog/StatusDialogDivider.qml