feat(WalletFirst): Creating the wallet banner UI component
Banner items are created as per design. Banner items support customizable close button. Banner items have hove state as per design. Banner items are added to storybook with all possible configurations. Banner items have a close animation including fade-out and the remaining item occupy the empty space. QML tests are added.
This commit is contained in:
parent
b555d19a1a
commit
5e6db4d2ff
|
@ -0,0 +1,59 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
Pane {
|
||||
id: leftPane
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
BannerCard {
|
||||
anchors.centerIn: parent
|
||||
title: titleField.text
|
||||
subTitle: subTitleField.text
|
||||
image: Theme.png("wallet/wallet-green")
|
||||
closeEnabled: closeEnabled.checked
|
||||
onClicked: {
|
||||
print("BannerCard clicked")
|
||||
}
|
||||
onClose: {
|
||||
print("BannerCard closed")
|
||||
}
|
||||
}
|
||||
}
|
||||
Pane {
|
||||
id: rightPane
|
||||
SplitView.fillHeight: true
|
||||
SplitView.preferredWidth: 300
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
CheckBox {
|
||||
id: closeEnabled
|
||||
text: "Show close button"
|
||||
checked: true
|
||||
}
|
||||
Label {
|
||||
text: "Title"
|
||||
}
|
||||
TextField {
|
||||
id: titleField
|
||||
text: "Ways to buy crypto"
|
||||
}
|
||||
Label {
|
||||
text: "Sub title"
|
||||
}
|
||||
TextField {
|
||||
id: subTitleField
|
||||
text: "Via card or bank transfer"
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import AppLayouts.Wallet.panels 1.0
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
Pane {
|
||||
id: leftPane
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
BuyReceiveBanner {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
width: leftPane.width
|
||||
closeEnabled: closeEnabled.checked
|
||||
buyEnabled: buyEnabled.checked
|
||||
receiveEnabled: receiveEnabled.checked
|
||||
onBuyClicked: {
|
||||
print("Buy clicked")
|
||||
}
|
||||
onReceiveClicked: {
|
||||
print("Receive clicked")
|
||||
}
|
||||
onCloseBuy: {
|
||||
buyEnabled.checked = false
|
||||
}
|
||||
onCloseReceive: {
|
||||
receiveEnabled.checked = false
|
||||
}
|
||||
onAnyVisibleItemsChanged: {
|
||||
print("Any visible: ", anyVisibleItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
Pane {
|
||||
id: rightPane
|
||||
SplitView.fillHeight: true
|
||||
SplitView.preferredWidth: 300
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
text: "Any visible items"
|
||||
}
|
||||
Rectangle {
|
||||
width: 30
|
||||
height: 30
|
||||
radius: 15
|
||||
color: banner.anyVisibleItems ? "green" : "red"
|
||||
}
|
||||
CheckBox {
|
||||
id: closeEnabled
|
||||
text: "Show close button"
|
||||
checked: true
|
||||
}
|
||||
CheckBox {
|
||||
id: buyEnabled
|
||||
text: "Show buy button"
|
||||
checked: false
|
||||
}
|
||||
CheckBox {
|
||||
id: receiveEnabled
|
||||
text: "Show receive button"
|
||||
checked: false
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import QtQuick 2.15
|
||||
import QtTest 1.15
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 600
|
||||
height: 400
|
||||
|
||||
Component {
|
||||
id: bannerCardComponent
|
||||
|
||||
BannerCard {}
|
||||
}
|
||||
|
||||
TestCase {
|
||||
id: bannerCardTest
|
||||
|
||||
when: windowShown
|
||||
|
||||
property BannerCard componentUnderTest
|
||||
|
||||
function init() {
|
||||
componentUnderTest = createTemporaryObject(bannerCardComponent, root)
|
||||
}
|
||||
|
||||
function test_empty() {
|
||||
compare(componentUnderTest.image, "")
|
||||
compare(componentUnderTest.title, "")
|
||||
compare(componentUnderTest.subTitle, "")
|
||||
compare(componentUnderTest.closeEnabled, true)
|
||||
}
|
||||
|
||||
function test_geometry() {
|
||||
verify(componentUnderTest.height > 0)
|
||||
verify(componentUnderTest.width > 0)
|
||||
}
|
||||
|
||||
function test_hoverState() {
|
||||
compare(componentUnderTest.hovered, false)
|
||||
mouseMove(componentUnderTest)
|
||||
compare(componentUnderTest.hovered, true)
|
||||
|
||||
const closeButton = findChild(componentUnderTest, "bannerCard_closeButton")
|
||||
verify(!!closeButton)
|
||||
verify(closeButton.visible)
|
||||
verify(closeButton.width > 0)
|
||||
verify(closeButton.height > 0)
|
||||
|
||||
mouseMove(closeButton, closeButton.width / 2, closeButton.height / 2)
|
||||
compare(componentUnderTest.hovered, true)
|
||||
}
|
||||
|
||||
function test_click() {
|
||||
let clicked = false
|
||||
componentUnderTest.clicked.connect(() => {
|
||||
clicked = true
|
||||
})
|
||||
mouseClick(componentUnderTest)
|
||||
compare(clicked, true)
|
||||
|
||||
clicked = false
|
||||
|
||||
const closeButton = findChild(componentUnderTest, "bannerCard_closeButton")
|
||||
|
||||
let closed = false
|
||||
componentUnderTest.close.connect(() => {
|
||||
closed = true
|
||||
})
|
||||
mouseClick(closeButton)
|
||||
compare(closed, true)
|
||||
compare(clicked, false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
import QtQuick 2.15
|
||||
import QtTest 1.15
|
||||
|
||||
import AppLayouts.Wallet.panels 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 600
|
||||
height: 400
|
||||
|
||||
Component {
|
||||
id: buyReceiveComponent
|
||||
BuyReceiveBanner {
|
||||
id: banner
|
||||
anchors.fill: parent
|
||||
|
||||
readonly property SignalSpy buyClickedSpy: SignalSpy { target: banner; signalName: "buyClicked" }
|
||||
readonly property SignalSpy receiveClickedSpy: SignalSpy { target: banner; signalName: "receiveClicked" }
|
||||
readonly property SignalSpy closeBuySpy: SignalSpy { target: banner; signalName: "closeBuy" }
|
||||
readonly property SignalSpy closeReceiveSpy: SignalSpy { target: banner; signalName: "closeReceive" }
|
||||
}
|
||||
}
|
||||
|
||||
TestCase {
|
||||
id: buyReceiveBannerTest
|
||||
when: windowShown
|
||||
|
||||
property BuyReceiveBanner componentUnderTest
|
||||
|
||||
function init() {
|
||||
componentUnderTest = createTemporaryObject(buyReceiveComponent, root)
|
||||
}
|
||||
|
||||
function test_empty() {
|
||||
verify(componentUnderTest.closeEnabled)
|
||||
verify(componentUnderTest.buyEnabled)
|
||||
verify(componentUnderTest.receiveEnabled)
|
||||
verify(componentUnderTest.anyVisibleItems)
|
||||
}
|
||||
|
||||
function test_geometry() {
|
||||
compare(componentUnderTest.width, root.width)
|
||||
compare(componentUnderTest.height, root.height)
|
||||
}
|
||||
|
||||
function test_buyGeometry() {
|
||||
const buyCard = findChild(componentUnderTest, "buyCard")
|
||||
verify(!!buyCard)
|
||||
verify(buyCard.visible)
|
||||
verify(buyCard.opacity > 0)
|
||||
verify(buyCard.width > 0)
|
||||
verify(buyCard.height > 0)
|
||||
verify(buyCard.x >= 0)
|
||||
verify(buyCard.x <= buyCard.parent.width - buyCard.width)
|
||||
verify(buyCard.y >= 0)
|
||||
verify(buyCard.y <= buyCard.parent.height - buyCard.height)
|
||||
}
|
||||
|
||||
function test_receiveGeometry() {
|
||||
const receiveCard = findChild(componentUnderTest, "receiveCard")
|
||||
verify(!!receiveCard)
|
||||
verify(receiveCard.visible)
|
||||
verify(receiveCard.opacity > 0)
|
||||
verify(receiveCard.width > 0)
|
||||
verify(receiveCard.height > 0)
|
||||
verify(receiveCard.x >= 0)
|
||||
verify(receiveCard.x <= receiveCard.parent.width - receiveCard.width)
|
||||
verify(receiveCard.y >= 0)
|
||||
verify(receiveCard.y <= receiveCard.parent.height - receiveCard.height)
|
||||
}
|
||||
|
||||
function test_clickBuy() {
|
||||
const buyCard = findChild(componentUnderTest, "buyCard")
|
||||
verify(!!buyCard)
|
||||
|
||||
compare(componentUnderTest.buyClickedSpy.count, 0)
|
||||
mouseClick(buyCard)
|
||||
compare(componentUnderTest.buyClickedSpy.count, 1)
|
||||
}
|
||||
|
||||
function test_receiveClicked() {
|
||||
const receiveCard = findChild(componentUnderTest, "receiveCard")
|
||||
verify(!!receiveCard)
|
||||
|
||||
compare(componentUnderTest.receiveClickedSpy.count, 0)
|
||||
mouseClick(receiveCard)
|
||||
compare(componentUnderTest.receiveClickedSpy.count, 1)
|
||||
}
|
||||
|
||||
function test_closeBuy() {
|
||||
const buyCard = findChild(componentUnderTest, "buyCard")
|
||||
verify(!!buyCard)
|
||||
const closeButton = findChild(buyCard, "bannerCard_closeButton")
|
||||
verify(!!closeButton)
|
||||
verify(closeButton.visible)
|
||||
|
||||
compare(componentUnderTest.closeBuySpy.count, 0)
|
||||
mouseClick(closeButton)
|
||||
compare(componentUnderTest.closeBuySpy.count, 1)
|
||||
}
|
||||
|
||||
function test_closeReceive() {
|
||||
const receiveCard = findChild(componentUnderTest, "receiveCard")
|
||||
verify(!!receiveCard)
|
||||
const closeButton = findChild(receiveCard, "bannerCard_closeButton")
|
||||
verify(!!closeButton)
|
||||
verify(closeButton.visible)
|
||||
|
||||
compare(componentUnderTest.closeReceiveSpy.count, 0)
|
||||
mouseClick(closeButton)
|
||||
compare(componentUnderTest.closeReceiveSpy.count, 1)
|
||||
}
|
||||
|
||||
function test_anyVisibleItemsChanged() {
|
||||
compare(componentUnderTest.anyVisibleItems, true)
|
||||
compare(componentUnderTest.buyEnabled, true)
|
||||
compare(componentUnderTest.receiveEnabled, true)
|
||||
|
||||
componentUnderTest.buyEnabled = false
|
||||
compare(componentUnderTest.anyVisibleItems, true)
|
||||
|
||||
componentUnderTest.receiveEnabled = false
|
||||
tryVerify(() => componentUnderTest.anyVisibleItems, false)
|
||||
}
|
||||
|
||||
function test_closeDisabled() {
|
||||
const buyCard = findChild(componentUnderTest, "buyCard")
|
||||
verify(!!buyCard)
|
||||
const closeButton = findChild(buyCard, "bannerCard_closeButton")
|
||||
verify(!!closeButton)
|
||||
verify(closeButton.visible)
|
||||
|
||||
componentUnderTest.closeEnabled = false
|
||||
verify(!closeButton.visible)
|
||||
|
||||
const receiveCard = findChild(componentUnderTest, "receiveCard")
|
||||
verify(!!receiveCard)
|
||||
const receiveCloseButton = findChild(receiveCard, "bannerCard_closeButton")
|
||||
verify(!!receiveCloseButton)
|
||||
verify(!receiveCloseButton.visible)
|
||||
}
|
||||
|
||||
function test_hideBuy() {
|
||||
const buyCard = findChild(componentUnderTest, "buyCard")
|
||||
verify(!!buyCard)
|
||||
verify(buyCard.visible)
|
||||
|
||||
componentUnderTest.buyEnabled = false
|
||||
tryVerify(() => !buyCard.visible)
|
||||
}
|
||||
|
||||
function test_hideReceive() {
|
||||
const receiveCard = findChild(componentUnderTest, "receiveCard")
|
||||
verify(!!receiveCard)
|
||||
verify(receiveCard.visible)
|
||||
|
||||
componentUnderTest.receiveEnabled = false
|
||||
tryVerify(() => !receiveCard.visible)
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
|
@ -0,0 +1,99 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property alias image: image.source
|
||||
property alias title: title.text
|
||||
property alias subTitle: subTitle.text
|
||||
property alias closeEnabled: closeButton.visible
|
||||
|
||||
signal clicked()
|
||||
signal close()
|
||||
|
||||
implicitHeight: 70
|
||||
implicitWidth: 400
|
||||
padding: Theme.halfPadding
|
||||
leftPadding: 20
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
enabled: !closeHandler.pressed
|
||||
onTapped: {
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
HoverHandler {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
background: Rectangle {
|
||||
id: background
|
||||
color: Theme.palette.background
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 7
|
||||
radius: 8
|
||||
spread: root.hovered ? 0.3 : 0
|
||||
color: Theme.palette.baseColor2
|
||||
}
|
||||
}
|
||||
contentItem: RowLayout {
|
||||
id: layout
|
||||
spacing: Theme.padding
|
||||
StatusImage {
|
||||
id: image
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
StatusBaseText {
|
||||
id: title
|
||||
Layout.fillWidth: true
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
font.weight: Font.Medium
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
StatusBaseText {
|
||||
id: subTitle
|
||||
Layout.fillWidth: true
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
StatusIcon {
|
||||
id: closeButton
|
||||
objectName: "bannerCard_closeButton"
|
||||
Layout.topMargin: 4
|
||||
Layout.rightMargin: 4
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
icon: "close"
|
||||
color: Theme.palette.baseColor1
|
||||
TapHandler {
|
||||
id: closeHandler
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onTapped: {
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ AccountHeaderGradient 1.0 AccountHeaderGradient.qml
|
|||
ActivityFilterTagItem 1.0 ActivityFilterTagItem.qml
|
||||
AssetSelector 1.0 AssetSelector.qml
|
||||
AssetSelectorCompact 1.0 AssetSelectorCompact.qml
|
||||
BannerCard 1.0 BannerCard.qml
|
||||
BuyCryptoProvidersDelegate 1.0 BuyCryptoProvidersDelegate.qml
|
||||
BuyCryptoProvidersLoadingDelegate 1.0 BuyCryptoProvidersLoadingDelegate.qml
|
||||
CollectibleBalanceTag 1.0 CollectibleBalanceTag.qml
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property bool closeEnabled: true
|
||||
property bool buyEnabled: true
|
||||
property bool receiveEnabled: true
|
||||
|
||||
readonly property bool anyVisibleItems: buyCard.visible || receiveCard.visible
|
||||
|
||||
signal buyClicked()
|
||||
signal receiveClicked()
|
||||
signal closeBuy()
|
||||
signal closeReceive()
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: layout
|
||||
spacing: Theme.padding
|
||||
|
||||
BannerCard {
|
||||
id: buyCard
|
||||
objectName: "buyCard"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: root.buyEnabled ? layout.width / layout.children.length : 0
|
||||
title: qsTr("Ways to buy crypto")
|
||||
subTitle: qsTr("Via card or bank transfer")
|
||||
image: Theme.png("wallet/wallet-green")
|
||||
closeEnabled: root.closeEnabled
|
||||
visible: Layout.preferredWidth > 0
|
||||
opacity: root.buyEnabled ? 1 : 0
|
||||
|
||||
onClose: root.closeBuy()
|
||||
onClicked: root.buyClicked()
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
Behavior on Layout.preferredWidth {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
}
|
||||
BannerCard {
|
||||
id: receiveCard
|
||||
objectName: "receiveCard"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: root.receiveEnabled ? layout.width / layout.children.length : 0
|
||||
title: qsTr("Receive crypto")
|
||||
subTitle: qsTr("Deposit to your Wallet address")
|
||||
image: Theme.png("wallet/flying-coin")
|
||||
closeEnabled: root.closeEnabled
|
||||
visible: Layout.preferredWidth > 0
|
||||
opacity: root.receiveEnabled ? 1 : 0
|
||||
|
||||
onClose: root.closeReceive()
|
||||
onClicked: root.receiveClicked()
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
Behavior on Layout.preferredWidth {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
ActivityFilterPanel 1.0 ActivityFilterPanel.qml
|
||||
BuyCryptoProvidersListPanel 1.0 BuyCryptoProvidersListPanel.qml
|
||||
BuyReceiveBanner 1.0 BuyReceiveBanner.qml
|
||||
ContractInfoButtonWithMenu 1.0 ContractInfoButtonWithMenu.qml
|
||||
DAppsWorkflow 1.0 DAppsWorkflow.qml
|
||||
ManageAssetsPanel 1.0 ManageAssetsPanel.qml
|
||||
|
|
Loading…
Reference in New Issue