fix: Review scrolling behavior for holdings dropdown
- remove padding and use margins so that the listview can span the whole width while having the scrollbar neatly next to it - make the section header both inline and floatable (which makes it always visible, even when scrolled away) - fix the special search results "section" to behave the same way - sort the results by category and name - expose the `allTokensMode` for easy testing with storybook Closes #10201
This commit is contained in:
parent
13228f4c28
commit
bb2bbfb5b6
|
@ -52,6 +52,8 @@ SplitView {
|
||||||
parent: container
|
parent: container
|
||||||
anchors.centerIn: container
|
anchors.centerIn: container
|
||||||
|
|
||||||
|
allTokensMode: ctrlAllTokensMode.checked
|
||||||
|
|
||||||
CollectiblesModel {
|
CollectiblesModel {
|
||||||
id: collectiblesModel
|
id: collectiblesModel
|
||||||
}
|
}
|
||||||
|
@ -162,6 +164,11 @@ SplitView {
|
||||||
text: "Airdrop mode"
|
text: "Airdrop mode"
|
||||||
checked: false
|
checked: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: ctrlAllTokensMode
|
||||||
|
text: "All tokens mode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import StatusQ.Core.Theme 0.1
|
||||||
/*!
|
/*!
|
||||||
\qmltype StatusDropdown
|
\qmltype StatusDropdown
|
||||||
\inherits Popup
|
\inherits Popup
|
||||||
\inqmlmodule StatusQ.Popups
|
\inqmlmodule StatusQ.Controls
|
||||||
\since StatusQ.Popups 0.1
|
\since StatusQ.Controls 0.1
|
||||||
\brief The StatusDropdown provides a template for creating dropdowns.
|
\brief The StatusDropdown provides a template for creating dropdowns.
|
||||||
|
|
||||||
NOTE: Each consumer needs to set the x and y postion of the dropdown.
|
NOTE: Each consumer needs to set the x and y postion of the dropdown.
|
||||||
|
|
|
@ -14,6 +14,7 @@ import shared.controls 1.0
|
||||||
import shared.panels 1.0
|
import shared.panels 1.0
|
||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
import SortFilterProxyModel 0.2
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
@ -75,6 +76,7 @@ Item {
|
||||||
|
|
||||||
readonly property int filterItemsHeight: 36
|
readonly property int filterItemsHeight: 36
|
||||||
readonly property int filterPopupWidth: 233
|
readonly property int filterPopupWidth: 233
|
||||||
|
readonly property int padding: Style.current.halfPadding
|
||||||
|
|
||||||
// Internal management properties
|
// Internal management properties
|
||||||
property bool isFilterOptionVisible: false
|
property bool isFilterOptionVisible: false
|
||||||
|
@ -173,6 +175,15 @@ Item {
|
||||||
|
|
||||||
expression: getCategoryLabelForType(model.category, root.type)
|
expression: getCategoryLabelForType(model.category, root.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sorters: [
|
||||||
|
RoleSorter {
|
||||||
|
roleName: "category"
|
||||||
|
},
|
||||||
|
RoleSorter {
|
||||||
|
roleName: "name"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +266,7 @@ Item {
|
||||||
icon.name: "filter"
|
icon.name: "filter"
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: d.padding
|
||||||
anchors.bottom: parent.top
|
anchors.bottom: parent.top
|
||||||
anchors.bottomMargin: 3
|
anchors.bottomMargin: 3
|
||||||
|
|
||||||
|
@ -384,6 +396,8 @@ Item {
|
||||||
id: searcher
|
id: searcher
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: d.padding
|
||||||
|
Layout.rightMargin: d.padding
|
||||||
Layout.topMargin: root.state === d.depth1_ListState ? 0 : 8
|
Layout.topMargin: root.state === d.depth1_ListState ? 0 : 8
|
||||||
|
|
||||||
visible: d.availableData
|
visible: d.availableData
|
||||||
|
@ -426,6 +440,8 @@ Item {
|
||||||
id: tokenGroupItem
|
id: tokenGroupItem
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: d.padding
|
||||||
|
Layout.rightMargin: d.padding
|
||||||
|
|
||||||
name: qsTr("Any %1").arg(d.currentItemName)
|
name: qsTr("Any %1").arg(d.currentItemName)
|
||||||
iconSource: d.currentItemSource
|
iconSource: d.currentItemSource
|
||||||
|
@ -450,6 +466,7 @@ Item {
|
||||||
id: assetsListView
|
id: assetsListView
|
||||||
|
|
||||||
ListDropdownContent {
|
ListDropdownContent {
|
||||||
|
id: assetDelegate
|
||||||
availableData: d.availableData
|
availableData: d.availableData
|
||||||
noDataText: root.noDataText
|
noDataText: root.noDataText
|
||||||
areHeaderButtonsVisible: root.state === d.depth1_ListState
|
areHeaderButtonsVisible: root.state === d.depth1_ListState
|
||||||
|
@ -482,7 +499,7 @@ Item {
|
||||||
onImplicitHeightChanged: root.layoutChanged()
|
onImplicitHeightChanged: root.layoutChanged()
|
||||||
|
|
||||||
Binding on implicitHeight {
|
Binding on implicitHeight {
|
||||||
value: contentHeight
|
value: contentHeight + d.padding
|
||||||
//avoid too many changes of the implicit height
|
//avoid too many changes of the implicit height
|
||||||
delayed: true
|
delayed: true
|
||||||
}
|
}
|
||||||
|
@ -493,6 +510,7 @@ Item {
|
||||||
id: collectiblesListView
|
id: collectiblesListView
|
||||||
|
|
||||||
ListDropdownContent {
|
ListDropdownContent {
|
||||||
|
id: collectibleDelegate
|
||||||
availableData: d.availableData
|
availableData: d.availableData
|
||||||
noDataText: root.noDataText
|
noDataText: root.noDataText
|
||||||
areHeaderButtonsVisible: root.state === d.depth1_ListState
|
areHeaderButtonsVisible: root.state === d.depth1_ListState
|
||||||
|
@ -540,7 +558,7 @@ Item {
|
||||||
}
|
}
|
||||||
onImplicitHeightChanged: root.layoutChanged()
|
onImplicitHeightChanged: root.layoutChanged()
|
||||||
Binding on implicitHeight {
|
Binding on implicitHeight {
|
||||||
value: contentHeight
|
value: contentHeight + d.padding
|
||||||
//avoid too many changes of the implicit height
|
//avoid too many changes of the implicit height
|
||||||
delayed: true
|
delayed: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,11 @@ StatusListView {
|
||||||
implicitWidth: 273
|
implicitWidth: 273
|
||||||
implicitHeight: Math.min(contentHeight, root.maxHeight)
|
implicitHeight: Math.min(contentHeight, root.maxHeight)
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
clip: true
|
leftMargin: d.padding
|
||||||
|
rightMargin: 14 // scrollbar width
|
||||||
|
|
||||||
header: ColumnLayout {
|
header: ColumnLayout {
|
||||||
width: root.width
|
width: root.availableWidth
|
||||||
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ StatusListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: TokenItem {
|
delegate: TokenItem {
|
||||||
width: ListView.view.width
|
width: root.availableWidth
|
||||||
|
|
||||||
name: model.name
|
name: model.name
|
||||||
shortName: model.shortName ?? ""
|
shortName: model.shortName ?? ""
|
||||||
|
@ -103,11 +104,15 @@ StatusListView {
|
||||||
|
|
||||||
section.property: root.searchMode || !root.areSectionsVisible
|
section.property: root.searchMode || !root.areSectionsVisible
|
||||||
? "" : "categoryLabel"
|
? "" : "categoryLabel"
|
||||||
section.criteria: ViewSection.FullString
|
section.delegate: ColumnLayout {
|
||||||
|
width: root.availableWidth
|
||||||
|
height: root.searchMode || root.areSectionsVisible ? d.sectionHeight : 0
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
section.delegate: Item {
|
Rectangle {
|
||||||
width: ListView.view.width
|
Layout.fillWidth: true
|
||||||
height: d.sectionHeight
|
Layout.fillHeight: true
|
||||||
|
color: Theme.palette.statusListItem.backgroundColor
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: loader
|
id: loader
|
||||||
|
@ -118,15 +123,28 @@ StatusListView {
|
||||||
target: loader.item
|
target: loader.item
|
||||||
property: "section"
|
property: "section"
|
||||||
value: section
|
value: section
|
||||||
|
when: !root.searchMode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// floating divider
|
||||||
|
Rectangle {
|
||||||
|
visible: parent.y === root.contentY && (root.searchMode || root.areSectionsVisible)
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: -d.padding
|
||||||
|
Layout.rightMargin: -d.padding*2
|
||||||
|
Layout.preferredHeight: 4
|
||||||
|
color: Theme.palette.directColor8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: footerComponent
|
id: footerComponent
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: ListView.view ? ListView.view.width : 0
|
width: ListView.view ? ListView.view.width - Style.current.smallPadding : 0
|
||||||
height: d.sectionHeight
|
height: d.sectionHeight
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
@ -167,6 +185,7 @@ StatusListView {
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
|
readonly property int padding: Style.current.halfPadding
|
||||||
readonly property int sectionHeight: 34
|
readonly property int sectionHeight: 34
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +199,7 @@ StatusListView {
|
||||||
if(!root.availableData)
|
if(!root.availableData)
|
||||||
return root.noDataText
|
return root.noDataText
|
||||||
if(root.count)
|
if(root.count)
|
||||||
return qsTr("Search result")
|
return qsTr("Search results")
|
||||||
return qsTr("No results")
|
return qsTr("No results")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,12 @@ Control {
|
||||||
|
|
||||||
signal itemClicked
|
signal itemClicked
|
||||||
|
|
||||||
leftPadding: 6 // by design
|
padding: 6 // by design
|
||||||
implicitHeight: 45 // by design
|
implicitHeight: 44 // by design
|
||||||
spacing: 8 // by design
|
spacing: 8 // by design
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
|
color: mouseArea.containsMouse ? Theme.palette.statusListItem.highlightColor : "transparent"
|
||||||
|
radius: 8
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
@ -82,7 +83,6 @@ Control {
|
||||||
icon: root.selected && !root.showSubItemsIcon ? "checkmark" : "tiny/chevron-right"
|
icon: root.selected && !root.showSubItemsIcon ? "checkmark" : "tiny/chevron-right"
|
||||||
visible: root.selected || root.showSubItemsIcon
|
visible: root.selected || root.showSubItemsIcon
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.rightMargin: 16
|
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
width: 16
|
width: 16
|
||||||
height: 16
|
height: 16
|
||||||
|
|
|
@ -29,6 +29,8 @@ StatusDropdown {
|
||||||
property string noDataTextForAssets: qsTr("No assets found")
|
property string noDataTextForAssets: qsTr("No assets found")
|
||||||
property string noDataTextForCollectibles: qsTr("No collectibles found")
|
property string noDataTextForCollectibles: qsTr("No collectibles found")
|
||||||
|
|
||||||
|
property alias allTokensMode: d.allTokensMode
|
||||||
|
|
||||||
property var usedTokens: []
|
property var usedTokens: []
|
||||||
property var usedEnsNames: []
|
property var usedEnsNames: []
|
||||||
|
|
||||||
|
@ -118,8 +120,7 @@ StatusDropdown {
|
||||||
// By design values:
|
// By design values:
|
||||||
readonly property int padding: 8
|
readonly property int padding: 8
|
||||||
readonly property int defaultWidth: 289
|
readonly property int defaultWidth: 289
|
||||||
readonly property int extendedContentHeight: 380
|
readonly property int tabBarHeight: 36
|
||||||
readonly property int tabBarHeigh: 36
|
|
||||||
readonly property int tabBarTextSize: 13
|
readonly property int tabBarTextSize: 13
|
||||||
readonly property int backButtonWidth: 56
|
readonly property int backButtonWidth: 56
|
||||||
readonly property int backButtonHeight: 24
|
readonly property int backButtonHeight: 24
|
||||||
|
@ -152,9 +153,11 @@ StatusDropdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
width: d.defaultWidth
|
width: d.defaultWidth
|
||||||
padding: d.padding
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
topPadding: d.padding
|
||||||
bottomInset: d.bottomInset
|
bottomInset: d.bottomInset
|
||||||
bottomPadding: d.padding + d.bottomInset
|
bottomPadding: d.bottomInset + (loader.sourceComponent == listLayout ? 0 : d.padding)
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
|
@ -167,6 +170,8 @@ StatusDropdown {
|
||||||
|
|
||||||
Layout.preferredWidth: d.backButtonWidth
|
Layout.preferredWidth: d.backButtonWidth
|
||||||
Layout.preferredHeight: d.backButtonHeight
|
Layout.preferredHeight: d.backButtonHeight
|
||||||
|
Layout.leftMargin: d.padding
|
||||||
|
Layout.rightMargin: d.padding
|
||||||
visible: statesStack.size > 1
|
visible: statesStack.size > 1
|
||||||
spacing: 0
|
spacing: 0
|
||||||
leftPadding: 4
|
leftPadding: 4
|
||||||
|
@ -180,8 +185,10 @@ StatusDropdown {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
|
|
||||||
visible: !backButton.visible
|
visible: !backButton.visible
|
||||||
Layout.preferredHeight: d.tabBarHeigh
|
Layout.preferredHeight: d.tabBarHeight
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: d.padding
|
||||||
|
Layout.rightMargin: d.padding
|
||||||
currentIndex: d.holdingTypes.indexOf(d.currentHoldingType)
|
currentIndex: d.holdingTypes.indexOf(d.currentHoldingType)
|
||||||
state: d.currentHoldingType
|
state: d.currentHoldingType
|
||||||
states: [
|
states: [
|
||||||
|
@ -222,6 +229,8 @@ StatusDropdown {
|
||||||
Loader {
|
Loader {
|
||||||
id: loader
|
id: loader
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: loader.sourceComponent == listLayout ? 0 : d.padding
|
||||||
|
Layout.rightMargin: loader.sourceComponent == listLayout ? 0 : d.padding
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
onItemChanged: d.forceLayout()
|
onItemChanged: d.forceLayout()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue