From 95a066960cd8f5590b6ca44ba40e8fbd7a0f97c3 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sat, 18 Jul 2026 07:15:22 -0300 Subject: [PATCH] fix(liquidity): theme holding selectors --- .../liquidity/AmmSelectionComboBox.qml | 107 ++++++++++++++++++ .../LiquidityConfirmationSummary.qml | 17 +-- .../components/liquidity/TokenAmountInput.qml | 12 +- apps/amm/qml/pages/LiquidityPage.qml | 5 +- .../qml/tst_LiquidityConfirmationDialog.qml | 20 ++++ apps/amm/tests/qml/tst_TokenAmountInput.qml | 24 ++++ 6 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 apps/amm/qml/components/liquidity/AmmSelectionComboBox.qml diff --git a/apps/amm/qml/components/liquidity/AmmSelectionComboBox.qml b/apps/amm/qml/components/liquidity/AmmSelectionComboBox.qml new file mode 100644 index 0000000..7f6e7f7 --- /dev/null +++ b/apps/amm/qml/components/liquidity/AmmSelectionComboBox.qml @@ -0,0 +1,107 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Controls.Basic + +ComboBox { + id: root + + required property var theme + property var labelForOption: function(option) { return String(option || "") } + + implicitHeight: 34 + leftPadding: 10 + rightPadding: 28 + topPadding: 0 + bottomPadding: 0 + hoverEnabled: true + activeFocusOnTab: true + focusPolicy: Qt.StrongFocus + + contentItem: Text { + leftPadding: root.leftPadding + rightPadding: root.rightPadding + text: root.displayText + color: root.enabled ? root.theme.colors.textPrimary + : root.theme.colors.textPlaceholder + font.pixelSize: 11 + verticalAlignment: Text.AlignVCenter + elide: Text.ElideMiddle + } + + indicator: Text { + x: root.width - width - 10 + y: Math.round((root.height - height) / 2) + text: "\u25BE" + color: root.enabled ? root.theme.colors.textSecondary + : root.theme.colors.textPlaceholder + font.pixelSize: 10 + } + + background: Rectangle { + radius: 7 + color: !root.enabled + ? root.theme.colors.panelBg + : root.down + ? root.theme.colors.selection + : root.hovered || root.activeFocus + ? root.theme.colors.panelHoverBg + : root.theme.colors.panelBg + border.color: root.activeFocus ? root.theme.colors.ctaBg + : root.theme.colors.borderStrong + border.width: 1 + } + + delegate: ItemDelegate { + id: optionDelegate + + required property int index + required property var modelData + + width: ListView.view ? ListView.view.width : root.width + height: 34 + hoverEnabled: true + highlighted: root.highlightedIndex === optionDelegate.index + + contentItem: Text { + leftPadding: 8 + rightPadding: 8 + text: root.labelForOption(optionDelegate.modelData) + color: root.theme.colors.textPrimary + font.pixelSize: 11 + verticalAlignment: Text.AlignVCenter + elide: Text.ElideMiddle + } + + background: Rectangle { + radius: 5 + color: optionDelegate.highlighted || optionDelegate.hovered + ? root.theme.colors.panelHoverBg : "transparent" + } + } + + popup: Popup { + y: root.height + 4 + width: root.width + implicitHeight: Math.min(contentItem.implicitHeight + topPadding + bottomPadding, + 204) + padding: 4 + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: root.delegateModel + currentIndex: root.highlightedIndex + highlightMoveDuration: 0 + ScrollIndicator.vertical: ScrollIndicator { } + } + + background: Rectangle { + radius: 7 + color: root.theme.colors.cardBg + border.color: root.theme.colors.borderStrong + border.width: 1 + } + } +} diff --git a/apps/amm/qml/components/liquidity/LiquidityConfirmationSummary.qml b/apps/amm/qml/components/liquidity/LiquidityConfirmationSummary.qml index 7d6287f..61e5ca2 100644 --- a/apps/amm/qml/components/liquidity/LiquidityConfirmationSummary.qml +++ b/apps/amm/qml/components/liquidity/LiquidityConfirmationSummary.qml @@ -1,18 +1,23 @@ pragma ComponentBehavior: Bound import QtQuick -import QtQuick.Controls +import QtQuick.Controls.Basic import QtQuick.Layouts ColumnLayout { id: root property var snapshot: ({}) + property var theme: fallbackTheme signal snapshotEdited(var snapshot) spacing: 8 + AmmTheme { + id: fallbackTheme + } + function actionText(instruction) { if (instruction === "NewDefinition") return qsTr("Create pool") @@ -38,26 +43,22 @@ ColumnLayout { font.pixelSize: 12 } - ComboBox { + AmmSelectionComboBox { id: lpDestinationPicker objectName: "lpDestinationPicker" Layout.fillWidth: true + theme: root.theme model: root.destinationRows() enabled: model.length > 1 currentIndex: root.destinationIndex() displayText: currentIndex >= 0 ? model[currentIndex].label : qsTr("Select destination") + labelForOption: function(destination) { return destination.label } Accessible.name: qsTr("LP token destination") onActivated: function(index) { root.selectDestination(model[index]) } - - delegate: ItemDelegate { - required property var modelData - width: lpDestinationPicker.width - text: modelData.label - } } } diff --git a/apps/amm/qml/components/liquidity/TokenAmountInput.qml b/apps/amm/qml/components/liquidity/TokenAmountInput.qml index 1e47268..f46c2e6 100644 --- a/apps/amm/qml/components/liquidity/TokenAmountInput.qml +++ b/apps/amm/qml/components/liquidity/TokenAmountInput.qml @@ -1,7 +1,7 @@ pragma ComponentBehavior: Bound import QtQuick -import QtQuick.Controls +import QtQuick.Controls.Basic import QtQuick.Layouts import "../shared" @@ -92,11 +92,12 @@ AmmTokenAmountSurface { onClicked: tokenModal.open() } - ComboBox { + AmmSelectionComboBox { id: holdingPicker objectName: "holdingPicker" Layout.fillWidth: true + theme: root.theme visible: root.holdings.length > 1 enabled: root.holdingSelectionEnabled && root.holdings.length > 1 model: root.holdings @@ -104,16 +105,11 @@ AmmTokenAmountSurface { displayText: currentIndex >= 0 ? root.holdingLabel(root.holdings[currentIndex]) : qsTr("Select holding") + labelForOption: function(holding) { return root.holdingLabel(holding) } Accessible.name: qsTr("Wallet holding for %1").arg(root.label) onActivated: function(index) { root.holdingSelected(String(root.holdings[index].holdingId || "")) } - - delegate: ItemDelegate { - required property var modelData - width: holdingPicker.width - text: root.holdingLabel(modelData) - } } } } diff --git a/apps/amm/qml/pages/LiquidityPage.qml b/apps/amm/qml/pages/LiquidityPage.qml index d15bdba..4e42f71 100644 --- a/apps/amm/qml/pages/LiquidityPage.qml +++ b/apps/amm/qml/pages/LiquidityPage.qml @@ -16,6 +16,7 @@ Item { property var backend: null property var runtime: null readonly property NewPositionFlow flow: newPositionFlow + readonly property var ammTheme: theme readonly property int pageMargin: width < 640 ? 16 : 24 readonly property int contentMaxWidth: 1200 @@ -259,7 +260,9 @@ Item { Component { id: liquidityConfirmationSummary - LiquidityConfirmationSummary { } + LiquidityConfirmationSummary { + theme: root.ammTheme + } } TransactionConfirmationDialog { diff --git a/apps/amm/tests/qml/tst_LiquidityConfirmationDialog.qml b/apps/amm/tests/qml/tst_LiquidityConfirmationDialog.qml index ff5fb0a..3830865 100644 --- a/apps/amm/tests/qml/tst_LiquidityConfirmationDialog.qml +++ b/apps/amm/tests/qml/tst_LiquidityConfirmationDialog.qml @@ -59,4 +59,24 @@ TestCase { compare(editedSpy.signalArguments[0][0].quoteReady, false) editedSpy.target = null } + + function test_lpDestinationPickerUsesAmmTheme() { + var summary = createTemporaryObject(summaryComponent, testCase, { + "snapshot": { + "instruction": "AddLiquidity", + "request": ({ "schema": "new-position.v2" }), + "lpHoldingOptions": [{ + "holdingId": "44444444444444444444444444444444", + "balanceRaw": "7" + }], + "lpDestinationRequired": true, + "quoteReady": false + } + }) + verify(summary) + + var picker = findChild(summary, "lpDestinationPicker") + verify(picker) + compare(picker.background.color, summary.theme.colors.panelBg) + } } diff --git a/apps/amm/tests/qml/tst_TokenAmountInput.qml b/apps/amm/tests/qml/tst_TokenAmountInput.qml index 7a10ae3..27d7ae6 100644 --- a/apps/amm/tests/qml/tst_TokenAmountInput.qml +++ b/apps/amm/tests/qml/tst_TokenAmountInput.qml @@ -95,6 +95,30 @@ TestCase { compare(input.accessoryWidth, 180) } + function test_holdingPickerUsesAmmTheme() { + var input = createTemporaryObject(inputComponent, testCase, { + "visible": true, + "holdings": [{ + "holdingId": "11111111111111111111111111111111", + "balanceRaw": "1" + }, { + "holdingId": "22222222222222222222222222222222", + "balanceRaw": "2" + }], + "selectedHoldingId": "11111111111111111111111111111111" + }) + verify(input) + + var picker = findChild(input, "holdingPicker") + verify(picker) + compare(picker.background.color, input.theme.colors.panelBg) + + picker.forceActiveFocus() + tryCompare(picker, "activeFocus", true) + compare(String(picker.background.border.color).toLowerCase(), + String(input.theme.colors.ctaBg).toLowerCase()) + } + function test_disabledTokenIsRejectedByTypedInput() { var input = createTemporaryObject(inputComponent, testCase) verify(input)