feat: [UI - Swap] Create tag error component

- created a new component (`ErrorTag`) based on the existing
`InformationTag`, suitable for displaying a row of icon (optional), text
and (optional) button in red/danger color
- add ErrorTagPage.qml to StoryBook
- add some basic QML tests

- InformationTag: make more properties customizable, use the same
`bgRadius` consistently
- StatusSmartIdenticon: some fixes for the MouseArea hover/click
behavior

Fixes #14792
This commit is contained in:
Lukáš Tinkl 2024-05-21 20:48:07 +02:00 committed by Lukáš Tinkl
parent df3f9984a8
commit a2e85bb3eb
7 changed files with 252 additions and 27 deletions

View File

@ -0,0 +1,95 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import shared.controls 1.0
import Storybook 1.0
SplitView {
orientation: Qt.Horizontal
Logs { id: logs }
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
background: Rectangle {
color: Theme.palette.baseColor4
}
ErrorTag {
width: ctrlWidth.value || implicitWidth
anchors.centerIn: parent
text: ctrlText.text
buttonText: ctrlButtonText.text
asset.name: ctrlAssetName.text
loading: ctrlLoading.checked
onButtonClicked: logs.logEvent("ErrorTag::onButtonClicked", [], arguments)
}
}
LogsAndControlsPanel {
SplitView.fillHeight: true
SplitView.preferredWidth: 300
logsView.logText: logs.logText
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Label { text: "Text:" }
TextField {
Layout.fillWidth: true
id: ctrlText
text: "Insufficient funds to pay gas fees"
}
}
RowLayout {
Layout.fillWidth: true
Label { text: "Button text:" }
TextField {
Layout.fillWidth: true
id: ctrlButtonText
text: "Buy ETH"
}
}
RowLayout {
Layout.fillWidth: true
Label { text: "Asset name:" }
TextField {
Layout.fillWidth: true
id: ctrlAssetName
text: "warning"
}
}
RowLayout {
Layout.fillWidth: true
Label { text: "Width:" }
SpinBox {
id: ctrlWidth
from: 0
to: 400
value: 0 // 0 == implicitWidth
stepSize: 20
textFromValue: function(value, locale) { return value === 0 ? "Implicit" : value }
}
}
Switch {
id: ctrlLoading
text: "Loading"
}
Item { Layout.fillHeight: true }
}
}
}
// category: Controls
// https://www.figma.com/design/TS0eQX9dAZXqZtELiwKIoK/Swap---Milestone-1?node-id=3413-311788&t=D3qGKqNjDBuLEEaD-0

View File

@ -0,0 +1,68 @@
import QtQuick 2.15
import QtTest 1.15
import shared.controls 1.0
Item {
id: root
width: 600
height: 400
Component {
id: componentUnderTest
ErrorTag {
anchors.centerIn: parent
text: "Insufficient funds to pay gas fees"
}
}
SignalSpy {
id: signalSpy
target: controlUnderTest
signalName: "buttonClicked"
}
property ErrorTag controlUnderTest: null
TestCase {
name: "ErrorTag"
when: windowShown
function init() {
controlUnderTest = createTemporaryObject(componentUnderTest, root)
signalSpy.clear()
}
function test_basicGeometry() {
verify(!!controlUnderTest)
verify(controlUnderTest.width > 0)
verify(controlUnderTest.height > 0)
}
function test_noDefaultButton() {
verify(!!controlUnderTest)
const button = findChild(controlUnderTest, "rightComponentButton")
tryCompare(button, "visible", false)
}
function test_buttonClick() {
verify(!!controlUnderTest)
controlUnderTest.buttonText = "Buy crypto"
const button = findChild(controlUnderTest, "rightComponentButton")
verify(!!button)
tryCompare(button, "visible", true)
mouseClick(button)
tryCompare(signalSpy, "count", 1)
}
function test_loadingNotClickable() {
verify(!!controlUnderTest)
controlUnderTest.loading = true
const button = findChild(controlUnderTest, "rightComponentButton")
verify(!!button)
tryCompare(button, "visible", false)
mouseClick(button)
tryCompare(signalSpy, "count", 0)
}
}
}

View File

@ -1,15 +1,15 @@
import QtQuick 2.13
import QtQuick.Controls 2.12
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
import StatusQ.Core.Theme 0.1
import QtGraphicalEffects 1.12
/*!
\qmltype LoadingComponent
\inherits Control
\inqmlmodule StatusQ.Components
\since StatusQ.Components 0.1
\brief A componet that can be used to adding a loading state to a widget
\brief A component that can be used to adding a loading state to a widget
Example:
\qml
@ -48,6 +48,7 @@ Control {
color: Theme.palette.statusLoadingHighlight
radius: root.radius
visible: false
LinearGradient {
id: gradient
width: 100
@ -62,7 +63,7 @@ Control {
GradientStop { position: 0.8; color: "transparent"}
}
rotation: 20
NumberAnimation on x {
XAnimator on x {
id: animation
easing.type: Easing.Linear
loops: Animation.Infinite

View File

@ -38,6 +38,7 @@ Loader {
property bool hoverEnabled: false
readonly property bool hovered: (sourceComponent === roundedIcon && item) ?
item.hovered : false
signal clicked(var mouse)
Component {
@ -91,18 +92,15 @@ Loader {
asset.bgBorderWidth: root.asset.bgBorderWidth
asset.bgBorderColor: root.asset.bgBorderColor
signal clicked(var mouse)
property alias hovered: mouseArea.containsMouse
readonly property alias hovered: mouseArea.containsMouse
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: root.hoverEnabled
cursorShape: loading ? Qt.ArrowCursor
: Qt.PointingHandCursor
onClicked: parent.clicked(mouse)
cursorShape: !loading && root.hoverEnabled ? Qt.PointingHandCursor : undefined
onClicked: root.clicked(mouse)
}
}
}
@ -168,14 +166,4 @@ Loader {
width: root.asset.isImage ? root.asset.width : root.asset.bgWidth
}
}
Connections {
target: item
enabled: status === Loader.Ready
ignoreUnknownSignals: true
function onClicked(mouse) {
root.clicked(mouse)
}
}
}

View File

@ -0,0 +1,69 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import shared.controls 1.0
InformationTag {
id: root
property string text
property string buttonText
signal buttonClicked()
implicitHeight: 33
leftPadding: 10
rightPadding: 4
verticalPadding: 4
spacing: 6
backgroundColor: Theme.palette.dangerColor3
bgBorderColor: Theme.palette.dangerColor2
QtObject {
id: priv
readonly property int fontPixelSize: Theme.tertiaryTextFontSize
readonly property color foregroundColor: Theme.palette.dangerColor1
}
asset {
name: "warning"
color: priv.foregroundColor
}
tagPrimaryLabel.text: root.text
tagPrimaryLabel.color: priv.foregroundColor
tagPrimaryLabel.font.pixelSize: priv.fontPixelSize
tagPrimaryLabel.elide: Text.ElideRight
// NB: regular binding won't work as `tagPrimaryLabel` is an alias
Binding {
target: tagPrimaryLabel
property: "Layout.fillWidth"
value: true
}
rightComponent: StatusButton {
objectName: "rightComponentButton"
horizontalPadding: 8
width: visible || root.loading ? implicitWidth : 0
visible: !!text
size: StatusBaseButton.Size.Tiny
font.pixelSize: priv.fontPixelSize
type: StatusBaseButton.Type.Danger
normalColor: priv.foregroundColor
hoverColor: Theme.palette.hoverColor(normalColor)
textColor: Theme.palette.white
radius: root.bgRadius
text: root.buttonText
onClicked: root.buttonClicked()
}
}

View File

@ -1,6 +1,6 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.14
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
@ -18,20 +18,23 @@ Control {
property alias rightComponent: rightComponent.sourceComponent
property bool loading: false
property int secondarylabelMaxWidth: 100
property color backgroundColor: "transparent"
property color bgBorderColor: Theme.palette.baseColor2
property real bgRadius: 36
property Component customBackground: Component {
Rectangle {
color: root.backgroundColor
border.width: 1
border.color: Theme.palette.baseColor2
radius: 36
border.color: root.bgBorderColor
radius: root.bgRadius
}
}
QtObject {
id: d
property var loadingComponent: Component { LoadingComponent {} }
property var loadingComponent: Component { LoadingComponent { radius: root.bgRadius } }
}
horizontalPadding: 12

View File

@ -12,6 +12,7 @@ CurrencyAmountInput 1.0 CurrencyAmountInput.qml
EmojiHash 1.0 EmojiHash.qml
EmptyShapeRectangleFooterListView 1.0 EmptyShapeRectangleFooterListView.qml
ErrorDetails 1.0 ErrorDetails.qml
ErrorTag 1.0 ErrorTag.qml
FoldableHeader 1.0 FoldableHeader.qml
FormGroup 1.0 FormGroup.qml
GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml