Skip to content

Commit a80591b

Browse files
MarkNerdi996Tuditi
andauthored
UI/split send button (#4891)
* ui: add split send button * enhancement: store selected send option * ui: disable dropdown if only 1 option * chore: restructure features Co-authored-by: Tuditi <[email protected]>
1 parent 531d997 commit a80591b

File tree

6 files changed

+205
-8
lines changed

6 files changed

+205
-8
lines changed
Lines changed: 189 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,63 @@
11
<script lang="typescript">
22
import { localize } from '@core/i18n'
33
import { resetLedgerPreparedOutput, resetShowInternalVerificationPopup } from '@core/ledger'
4-
import { resetNewTransactionDetails } from '@core/wallet'
4+
import { resetNewTransactionDetails, selectedSendOptionIndex } from '@core/wallet'
55
import { openPopup } from '@lib/popup'
6-
import { OnboardingButton } from 'shared/components/atoms'
6+
import { appSettings } from '@core/app'
7+
import { Text, FontWeight, TextType, Icon, Modal } from 'shared/components'
8+
import { Icon as IconEnum } from '@auxiliary/icon'
9+
import features from '@features/features'
10+
11+
let modal: Modal = undefined
12+
let isModalOpened: boolean = false
13+
14+
$: darkModeEnabled = $appSettings.darkMode
15+
$: selectedOption = buttonOptions[$selectedSendOptionIndex]
16+
$: hasMultipleOptions = buttonOptions.length > 1
17+
18+
const buttonOptions = [
19+
{
20+
title: localize('general.sendFunds'),
21+
description: localize('general.sendTokensToAddress'),
22+
action: onL1SendClick,
23+
},
24+
...(features.wallet.sendAndReceive.nft.enabled
25+
? [
26+
{
27+
title: localize('general.sendNft'),
28+
description: localize('general.sendNftToAddress'),
29+
action: onNftSendClick,
30+
},
31+
]
32+
: []),
33+
]
34+
35+
function openModal(): void {
36+
isModalOpened = true
37+
modal?.open()
38+
}
39+
40+
function onSelection(index: number): void {
41+
$selectedSendOptionIndex = index
42+
isModalOpened = false
43+
modal?.close()
44+
}
745
846
function onSendClick(): void {
47+
selectedOption.action()
48+
}
49+
50+
function onL1SendClick(): void {
51+
resetNewTransactionDetails()
52+
resetLedgerPreparedOutput()
53+
resetShowInternalVerificationPopup()
54+
openPopup({
55+
type: 'sendForm',
56+
overflow: true,
57+
})
58+
}
59+
60+
function onNftSendClick(): void {
961
resetNewTransactionDetails()
1062
resetLedgerPreparedOutput()
1163
resetShowInternalVerificationPopup()
@@ -16,8 +68,138 @@
1668
}
1769
</script>
1870

19-
<OnboardingButton
20-
primaryText={localize('general.sendFunds')}
21-
secondaryText={localize('general.sendTokensToAddress')}
22-
onClick={onSendClick}
23-
/>
71+
<div class="relative">
72+
<div class="button-container flex flex-row justify-between rounded-xl" class:darkmode={darkModeEnabled}>
73+
<button
74+
class="px-4 py-3.5 text-center flex flex-row justify-between w-full"
75+
on:click|stopPropagation={onSendClick}
76+
>
77+
<span class="flex flex-col justify-center items-start">
78+
<Text
79+
type={TextType.p}
80+
color="gray-800"
81+
darkColor="white"
82+
fontSize="14"
83+
fontWeight={FontWeight.semibold}
84+
lineHeight="5"
85+
>{selectedOption.title}
86+
</Text>
87+
<Text
88+
type={TextType.p}
89+
color="gray-600"
90+
darkColor="gray-400"
91+
fontSize="12"
92+
fontWeight={FontWeight.normal}
93+
lineHeight="3.5"
94+
>{selectedOption.description}
95+
</Text>
96+
</span>
97+
{#if !hasMultipleOptions}
98+
<Icon icon={IconEnum.ChevronRight} classes="text-gray-500 h-full" />
99+
{/if}
100+
</button>
101+
{#if hasMultipleOptions}
102+
<button class="p-4" on:click={openModal}>
103+
<Icon
104+
icon={isModalOpened ? IconEnum.ChevronUp : IconEnum.ChevronDown}
105+
classes={isModalOpened ? 'text-blue-500' : 'text-gray-500'}
106+
/>
107+
</button>
108+
{/if}
109+
</div>
110+
111+
<Modal
112+
bind:this={modal}
113+
position={{ left: '0', top: 'calc(100% + 8px)' }}
114+
classes="w-full"
115+
on:close={() => (isModalOpened = false)}
116+
>
117+
<action-picker-modal class="max-h-64 flex flex-col space-y-1 scrollable-y">
118+
{#each buttonOptions as option, index}
119+
<button
120+
on:click={() => onSelection(index)}
121+
class="w-full flex flex-row flex-1 justify-between items-center px-2 py-3 space-x-2 rounded-lg hover:bg-blue-50 dark:hover:bg-gray-800 dark:hover:bg-opacity-20"
122+
>
123+
<div class="flex w-4 justify-center items-center">
124+
{#if $selectedSendOptionIndex === index}
125+
<Icon icon={IconEnum.Checkmark} classes="text-blue-500" width="16" height="16" />
126+
{/if}
127+
</div>
128+
<Text type={TextType.p} fontWeight={FontWeight.medium} color="gray-800" classes="w-full text-left"
129+
>{option.title}</Text
130+
>
131+
</button>
132+
{/each}
133+
</action-picker-modal>
134+
</Modal>
135+
</div>
136+
137+
<style type="text/scss">
138+
.button-container {
139+
min-width: 200px;
140+
@apply border;
141+
@apply border-solid;
142+
@apply border-gray-300;
143+
@apply bg-white;
144+
@apply text-left;
145+
span {
146+
min-height: 36px;
147+
}
148+
&.darkmode {
149+
@apply border-gray-700;
150+
@apply bg-transparent;
151+
152+
button {
153+
&:hover,
154+
&:focus,
155+
&:active {
156+
@apply bg-gray-700;
157+
@apply bg-opacity-20;
158+
@apply border-opacity-50;
159+
}
160+
&:disabled {
161+
@apply bg-gray-700;
162+
@apply bg-opacity-10;
163+
@apply border-gray-700;
164+
@apply border-opacity-10;
165+
}
166+
167+
&:last-child {
168+
@apply border-gray-700;
169+
}
170+
}
171+
}
172+
173+
button {
174+
&:hover {
175+
@apply bg-blue-50;
176+
@apply border-gray-500;
177+
}
178+
179+
&:active,
180+
&:focus {
181+
@apply bg-blue-100;
182+
@apply border-blue-400;
183+
}
184+
&:disabled {
185+
:global(svg) {
186+
@apply text-gray-500;
187+
}
188+
@apply pointer-events-none;
189+
@apply bg-gray-50;
190+
}
191+
192+
&:first-child {
193+
border-top-left-radius: 0.75rem;
194+
border-bottom-left-radius: 0.75rem;
195+
}
196+
197+
&:last-child {
198+
border-left: 1px solid;
199+
@apply border-gray-300;
200+
border-top-right-radius: 0.75rem;
201+
border-bottom-right-radius: 0.75rem;
202+
}
203+
}
204+
}
205+
</style>

packages/shared/features/features.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ const features = {
100100
},
101101
sendAndReceive: {
102102
enabled: true,
103+
nft: {
104+
enabled: false,
105+
},
103106
},
104107
assets: {
105108
enabled: true,

packages/shared/lib/core/account/actions/setSelectedAccount.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { activeAccounts, updateActiveProfile } from '@core/profile'
2+
import { resetSendOptionIndex } from '@core/wallet'
23
import { get } from 'svelte/store'
34
import { selectedAccount, selectedAccountIndex } from '../stores'
45

@@ -8,6 +9,7 @@ export function setSelectedAccount(index: number): void {
89
selectedAccountIndex.set(index)
910
selectedAccount.set(account)
1011
updateActiveProfile({ lastUsedAccountIndex: index })
12+
resetSendOptionIndex()
1113
} else {
1214
throw new Error(`Account with ID ${index} cannot be found!`)
1315
}

packages/shared/lib/core/wallet/stores/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * from './new-transaction-details.store'
66
export * from './persisted-assets.store'
77
export * from './selected-account-activities.store'
88
export * from './selected-account-assets.store'
9+
export * from './selected-send-option.store'
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { writable } from 'svelte/store'
2+
3+
export const selectedSendOptionIndex = writable<number>(0)
4+
5+
export function resetSendOptionIndex(): void {
6+
selectedSendOptionIndex.set(0)
7+
}

packages/shared/locales/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1117,10 +1117,12 @@
11171117
"moveFunds": "Internal Transfer",
11181118
"sendTo": "Send To",
11191119
"sendFunds": "Send funds",
1120+
"sendTokensToAddress": "Send tokens to an address",
11201121
"sendToAddress": "Send to address",
1122+
"sendNft": "Send NFT",
1123+
"sendNftToAddress": "Send NFT to an address",
11211124
"scanQrOrPaste": "Scan a QR code or paste an Address",
11221125
"moveFundsBetweenAccounts": "Move funds between wallets",
1123-
"sendTokensToAddress": "Send tokens to an address",
11241126
"manageAccount": "Manage Wallet",
11251127
"customizeAcount": "Customize your wallet",
11261128
"account": "Wallet",

0 commit comments

Comments
 (0)