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:
Lukáš Tinkl 2023-07-27 15:42:12 +02:00 committed by Lukáš Tinkl
parent 13228f4c28
commit bb2bbfb5b6
6 changed files with 84 additions and 31 deletions

View File

@ -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"
}
} }
} }
} }

View File

@ -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.

View File

@ -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
@ -172,7 +174,16 @@ 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
} }

View File

@ -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,30 +104,47 @@ 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
anchors.fill: parent anchors.fill: parent
sourceComponent: sectionComponent sourceComponent: sectionComponent
Binding { Binding {
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")
} }

View File

@ -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

View File

@ -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()
} }