From 871e76b7c218262a6069409fc6c3379f8990fae1 Mon Sep 17 00:00:00 2001 From: Andrei Radulescu Date: Mon, 9 Feb 2026 13:53:37 +0200 Subject: [PATCH 1/5] feat: add send to my wallets dropdown --- src/components/tx/SendModal.vue | 109 +++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/src/components/tx/SendModal.vue b/src/components/tx/SendModal.vue index fd0d803..cd5780c 100644 --- a/src/components/tx/SendModal.vue +++ b/src/components/tx/SendModal.vue @@ -11,13 +11,32 @@
- +
+ +
+
My wallets
+ +
+
{{error.$message}}
@@ -216,7 +235,9 @@ export default { passwordError: '', completedTx: null, - submitError: '' + submitError: '', + + showRecipientDropdown: false } }, validations() { @@ -239,7 +260,18 @@ export default { } }, computed: { - ...mapState(['address', 'balance', 'nextNonce']), + ...mapState(['address', 'balance', 'nextNonce', 'wallets', 'activeWalletId']), + otherWallets() { + return this.wallets.filter(w => w.id !== this.activeWalletId) + }, + filteredWallets() { + const query = this.recipient.trim().toLowerCase() + if (!query) return this.otherWallets + return this.otherWallets.filter(w => + w.name.toLowerCase().includes(query) || + w.address.toLowerCase().includes(query) + ) + }, amountParsed() { return parseAmount(this.amount) }, @@ -266,6 +298,24 @@ export default { this.reset() this.close() }, + onRecipientFocus() { + this.showRecipientDropdown = true + }, + onRecipientEsc() { + this.showRecipientDropdown = false + }, + onRecipientBlur() { + // Small delay so mousedown on dropdown item fires before hide + setTimeout(() => { this.showRecipientDropdown = false }, 150) + }, + selectRecipient(wallet) { + this.recipient = wallet.address + this.showRecipientDropdown = false + }, + truncateAddress(addr) { + if (!addr || addr.length < 11) return addr + return `${addr.slice(0, 6)}...${addr.slice(-4)}` + }, async checkPassword() { this.v$.password.$reset() if (await storage.comparePassword(this.password)) { @@ -298,6 +348,7 @@ export default { this.completedTx = null this.submitError = '' + this.showRecipientDropdown = false this.v$.$reset() }, @@ -370,4 +421,44 @@ export default { color: #0ecc5f; padding-left: 10px; } + +.recipient-input-wrap { + position: relative; +} + +.recipient-suggestions { + @apply absolute left-0 right-0 rounded-lg z-20 py-6; + top: 100%; + margin-top: 6px; + max-height: 160px; + overflow-y: auto; + background: #111; + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.8); +} + +.recipient-suggestions__header { + @apply px-12 text-gray-400; + padding-top: 4px; + padding-bottom: 8px; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.recipient-suggestions__item { + @apply flex items-center justify-between w-full px-12 py-10 text-gray transition-colors cursor-pointer; + @apply hover:text-white hover:bg-gray-700 hover:bg-opacity-25; + background: none; + border: none; + font-size: 13px; +} + +.recipient-suggestions__name { + @apply font-medium text-white text-sm leading-tight; +} + +.recipient-suggestions__address { + @apply font-mono text-sm text-gray-400 leading-tight; +} From 06ada472257f22e6155b9f8ed127893441d1ece7 Mon Sep 17 00:00:00 2001 From: Andrei Radulescu Date: Tue, 10 Feb 2026 17:10:19 +0200 Subject: [PATCH 2/5] fix: align send modal wallet dropdown styles with nav dropdown --- src/components/tx/SendModal.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/tx/SendModal.vue b/src/components/tx/SendModal.vue index cd5780c..ff70a8a 100644 --- a/src/components/tx/SendModal.vue +++ b/src/components/tx/SendModal.vue @@ -314,7 +314,7 @@ export default { }, truncateAddress(addr) { if (!addr || addr.length < 11) return addr - return `${addr.slice(0, 6)}...${addr.slice(-4)}` + return `${addr.slice(0, 7)}...${addr.slice(-4)}` }, async checkPassword() { this.v$.password.$reset() @@ -432,8 +432,8 @@ export default { margin-top: 6px; max-height: 160px; overflow-y: auto; - background: #111; - border: 1px solid rgba(255, 255, 255, 0.15); + background: #000; + border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.8); } @@ -459,6 +459,6 @@ export default { } .recipient-suggestions__address { - @apply font-mono text-sm text-gray-400 leading-tight; + @apply text-sm2 text-gray-400 leading-tight; } From c4c733e993d49d53cf4a565d345d63cbd0cd8bd6 Mon Sep 17 00:00:00 2001 From: Andrei Radulescu Date: Tue, 10 Feb 2026 17:29:05 +0200 Subject: [PATCH 3/5] refactor: extract shared truncateAddress utility --- src/components/tx/SendModal.vue | 7 ++----- src/components/wallet/WalletIndicator.vue | 7 ++----- src/components/wallet/WalletListItem.vue | 5 ++--- src/utils/form.js | 5 +++++ 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/tx/SendModal.vue b/src/components/tx/SendModal.vue index ff70a8a..064649c 100644 --- a/src/components/tx/SendModal.vue +++ b/src/components/tx/SendModal.vue @@ -206,7 +206,7 @@ import Modal from '../Modal.vue' import Radio from '../Radio.vue' import { helpers } from '@vuelidate/validators' import { mapState } from 'vuex' -import { parseAmount } from '../../utils/form' +import { parseAmount, truncateAddress } from '../../utils/form' import useVuelidate from '@vuelidate/core' const memoRegexp = /^[a-zA-Z0-9\s-]{0,32}$/ @@ -312,10 +312,7 @@ export default { this.recipient = wallet.address this.showRecipientDropdown = false }, - truncateAddress(addr) { - if (!addr || addr.length < 11) return addr - return `${addr.slice(0, 7)}...${addr.slice(-4)}` - }, + truncateAddress, async checkPassword() { this.v$.password.$reset() if (await storage.comparePassword(this.password)) { diff --git a/src/components/wallet/WalletIndicator.vue b/src/components/wallet/WalletIndicator.vue index 4b90dde..e8729a9 100644 --- a/src/components/wallet/WalletIndicator.vue +++ b/src/components/wallet/WalletIndicator.vue @@ -60,6 +60,7 @@