mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-16 13:01:05 +02:00
ui: small visual adaptions after placeholder PR (#222)
* chore: harmonize sprite definitions * fix: prevent render errors on invalid token in CurrentWalletMagic screen * ui: add border-radius to input placeholder * fix: add relationship 'noopener' to external links on Send screen Co-authored-by: Đorđe Spasić <34274884+Djo1e@users.noreply.github.com>
This commit is contained in:
parent
bb007f841f
commit
34bfd0b3cd
10 changed files with 131 additions and 111 deletions
|
|
@ -44,16 +44,16 @@
|
|||
<path d="M8 9.5a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/>
|
||||
<path d="M9.5 2c-.9 0-1.75.216-2.501.6A5 5 0 0 1 13 7.5a6.5 6.5 0 1 1-13 0 .5.5 0 0 1 1 0 5.5 5.5 0 0 0 8.001 4.9A5 5 0 0 1 3 7.5a6.5 6.5 0 0 1 13 0 .5.5 0 0 1-1 0A5.5 5.5 0 0 0 9.5 2zM8 3.5a4 4 0 1 0 0 8 4 4 0 0 0 0-8z"/>
|
||||
</symbol>
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" id="welcome" aria-hidden="true" class="svg-inline--fa fa-door-open fa-w-20" data-icon="door-open" data-prefix="fas" focusable="false" role="img" viewBox="0 0 640 512">
|
||||
<symbol id="welcome" viewBox="0 0 640 512">
|
||||
<path fill="currentColor" d="M624 448h-80V113.45C544 86.19 522.47 64 496 64H384v64h96v384h144c8.84 0 16-7.16 16-16v-32c0-8.84-7.16-16-16-16zM312.24 1.01l-192 49.74C105.99 54.44 96 67.7 96 82.92V448H16c-8.84 0-16 7.16-16 16v32c0 8.84 7.16 16 16 16h336V33.18c0-21.58-19.56-37.41-39.76-32.17zM264 288c-13.25 0-24-14.33-24-32s10.75-32 24-32 24 14.33 24 32-10.75 32-24 32z"/>
|
||||
</symbol>
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" id="collab" aria-hidden="true" class="svg-inline--fa fa-compress-arrows-alt fa-w-16" data-icon="compress-arrows-alt" data-prefix="fas" focusable="false" role="img" viewBox="0 0 512 512">
|
||||
<symbol id="collab" viewBox="0 0 512 512">
|
||||
<path fill="currentColor" d="M200 288H88c-21.4 0-32.1 25.8-17 41l32.9 31-99.2 99.3c-6.2 6.2-6.2 16.4 0 22.6l25.4 25.4c6.2 6.2 16.4 6.2 22.6 0L152 408l31.1 33c15.1 15.1 40.9 4.4 40.9-17V312c0-13.3-10.7-24-24-24zm112-64h112c21.4 0 32.1-25.9 17-41l-33-31 99.3-99.3c6.2-6.2 6.2-16.4 0-22.6L481.9 4.7c-6.2-6.2-16.4-6.2-22.6 0L360 104l-31.1-33C313.8 55.9 288 66.6 288 88v112c0 13.3 10.7 24 24 24zm96 136l33-31.1c15.1-15.1 4.4-40.9-17-40.9H312c-13.3 0-24 10.7-24 24v112c0 21.4 25.9 32.1 41 17l31-32.9 99.3 99.3c6.2 6.2 16.4 6.2 22.6 0l25.4-25.4c6.2-6.2 6.2-16.4 0-22.6L408 360zM183 71.1L152 104 52.7 4.7c-6.2-6.2-16.4-6.2-22.6 0L4.7 30.1c-6.2 6.2-6.2 16.4 0 22.6L104 152l-33 31.1C55.9 198.2 66.6 224 88 224h112c13.3 0 24-10.7 24-24V88c0-21.3-25.9-32-41-16.9z"/>
|
||||
</symbol>
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" id="key" fill="currentColor" data-v-4fa90e7f="" viewBox="0 0 24 24">
|
||||
<symbol id="key" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M18.865 7.374c.74 2.968-1.163 5.998-4.25 6.767a6.01 6.01 0 01-1.155.172l-3.435 5.471a2 2 0 01-1.21.877l-1.974.492a1 1 0 01-1.212-.728l-.445-1.786a2 2 0 01.246-1.547l3.157-5.028a5.338 5.338 0 01-.9-1.903c-.74-2.968 1.162-5.998 4.249-6.768 3.087-.77 6.189 1.013 6.929 3.98zm-4.627 1.324c.685-.171 1.108-.844.944-1.504-.165-.66-.854-1.055-1.54-.884-.686.17-1.109.844-.944 1.503.164.66.854 1.056 1.54.885z" clip-rule="evenodd"/>
|
||||
</symbol>
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" id="handshake" aria-hidden="true" class="svg-inline--fa fa-handshake-slash fa-w-20" data-icon="handshake-slash" data-prefix="fas" focusable="false" role="img" viewBox="0 0 640 512">
|
||||
<symbol id="handshake" viewBox="0 0 640 512">
|
||||
<path fill="currentColor" d="M0,128.21V384H64a32,32,0,0,0,32-32V184L23.83,128.21ZM48,320.1a16,16,0,1,1-16,16A16,16,0,0,1,48,320.1Zm80,31.81h18.3l90.5,81.89a64,64,0,0,0,90-9.3l.2-.2,17.91,15.5a37.16,37.16,0,0,0,52.29-5.39l8.8-10.82L128,208.72Zm416-223.7V352.1a32,32,0,0,0,32,32h64V128.21ZM592,352.1a16,16,0,1,1,16-16A16,16,0,0,1,592,352.1ZM303.33,202.67l59.58-54.57a16,16,0,0,1,21.59,23.61L358.41,195.6,504,313.8a73.08,73.08,0,0,1,7.91,7.7V128L457.3,73.41A31.76,31.76,0,0,0,434.7,64H348.8a31.93,31.93,0,0,0-21.6,8.41l-88.07,80.64-25.64-19.81L289.09,64H205.3a32,32,0,0,0-22.6,9.41L162.36,93.72,45.47,3.38A16,16,0,0,0,23,6.19L3.38,31.46A16,16,0,0,0,6.19,53.91L594.53,508.63A16,16,0,0,0,617,505.82l19.65-25.27a16,16,0,0,0-2.82-22.45Z"/>
|
||||
</symbol>
|
||||
<symbol id="shield-outline" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
<symbol id="shield-filled" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M5 7c0-.276.225-.499.498-.535 2.149-.28 5.282-2.186 6.224-2.785a.516.516 0 01.556 0c.942.599 4.075 2.504 6.224 2.785.273.036.498.259.498.535v4.75c0 6.5-7 8.75-7 8.75s-7-2.25-7-8.75V7z"/>
|
||||
</symbol>
|
||||
<symbol id="shield-filled-loading" fill="#e9ecef" viewBox="0 0 24 24">
|
||||
<symbol id="shield-filled-loading" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M5 7c0-.276.225-.499.498-.535 2.149-.28 5.282-2.186 6.224-2.785a.516.516 0 01.556 0c.942.599 4.075 2.504 6.224 2.785.273.036.498.259.498.535v4.75c0 6.5-7 8.75-7 8.75s-7-2.25-7-8.75V7z"/>
|
||||
</symbol>
|
||||
<symbol id="wand" fill="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
<symbol id="caret-down" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M4.47 9.4a.75.75 0 011.06 0l6.364 6.364a.25.25 0 00.354 0L18.612 9.4a.75.75 0 011.06 1.06l-6.364 6.364a1.75 1.75 0 01-2.475 0L4.47 10.46a.75.75 0 010-1.06z" clip-rule="evenodd"/>
|
||||
</symbol>
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" id="mnemonic" fill="currentColor" viewBox="0 0 24 24">
|
||||
<symbol id="mnemonic" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M5 6.5A1.5 1.5 0 016.5 5h11A1.5 1.5 0 0119 6.5v11a1.5 1.5 0 01-1.5 1.5h-11A1.5 1.5 0 015 17.5v-11zm1.5 0H9V8H6.5V6.5zM9 9.667H6.5v1.5H9v-1.5zm-2.5 3.166H9v1.5H6.5v-1.5zM9 16H6.5v1.5H9V16zm1.75-9.5h2.5V8h-2.5V6.5zm2.5 3.167h-2.5v1.5h2.5v-1.5zm-2.5 3.166h2.5v1.5h-2.5v-1.5zM13.25 16h-2.5v1.5h2.5V16zM15 6.5h2.5V8H15V6.5zm2.5 3.167H15v1.5h2.5v-1.5zM15 12.833h2.5v1.5H15v-1.5zM17.5 16H15v1.5h2.5V16z" clip-rule="evenodd"/>
|
||||
</symbol>
|
||||
<symbol id="globe" fill="currentColor" viewBox="0 0 24 24">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 39 KiB |
|
|
@ -45,15 +45,7 @@ const formatSats = (value) => {
|
|||
return formatter.format(value)
|
||||
}
|
||||
|
||||
const BalanceComponent = ({ symbol, value, symbolIsPrefix, loading }) => {
|
||||
if (loading) {
|
||||
return (
|
||||
<rb.Placeholder as="p" animation="wave" className="mb-0">
|
||||
<rb.Placeholder className={styles['balance-component-placeholder']} />
|
||||
</rb.Placeholder>
|
||||
)
|
||||
}
|
||||
|
||||
const BalanceComponent = ({ symbol, value, symbolIsPrefix }) => {
|
||||
return (
|
||||
<span className="d-inline-flex align-items-center">
|
||||
{symbolIsPrefix && symbol}
|
||||
|
|
@ -75,15 +67,27 @@ const BalanceComponent = ({ symbol, value, symbolIsPrefix, loading }) => {
|
|||
* Possible options are `BTC` and `SATS` from `src/utils.js`
|
||||
* @param {showBalance}: A flag indicating whether to render or hide the balance.
|
||||
* Hidden balances are masked with `*****`.
|
||||
* @param {loading}: A loading flag that renders a placeholder while true.
|
||||
*/
|
||||
export default function Balance({ valueString, convertToUnit, showBalance = false, loading }) {
|
||||
export default function Balance({ valueString, convertToUnit, showBalance = false, loading = false }) {
|
||||
const [displayMode, setDisplayMode] = useState(DISPLAY_MODE_HIDDEN)
|
||||
|
||||
useEffect(() => {
|
||||
setDisplayMode(getDisplayMode(convertToUnit, showBalance))
|
||||
}, [convertToUnit, showBalance])
|
||||
|
||||
if (displayMode === DISPLAY_MODE_HIDDEN && !loading) {
|
||||
if (loading) {
|
||||
return (
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder
|
||||
data-testid="balance-component-placeholder"
|
||||
className={styles['balance-component-placeholder']}
|
||||
/>
|
||||
</rb.Placeholder>
|
||||
)
|
||||
}
|
||||
|
||||
if (displayMode === DISPLAY_MODE_HIDDEN) {
|
||||
return (
|
||||
<BalanceComponent
|
||||
symbol={
|
||||
|
|
@ -98,8 +102,8 @@ export default function Balance({ valueString, convertToUnit, showBalance = fals
|
|||
}
|
||||
|
||||
if (typeof valueString !== 'string') {
|
||||
if (!loading) console.warn('<Balance /> component expects string input')
|
||||
return <BalanceComponent symbol="" value={valueString} symbolIsPrefix={false} loading={loading} />
|
||||
console.warn('<Balance /> component expects string input')
|
||||
return <BalanceComponent symbol="" value={valueString} symbolIsPrefix={false} />
|
||||
}
|
||||
|
||||
// Treat integers as sats.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ import { BTC, SATS } from '../utils'
|
|||
import Balance from './Balance'
|
||||
|
||||
describe('<Balance />', () => {
|
||||
it('should render placeholder while loading', () => {
|
||||
render(<Balance loading={true} />)
|
||||
expect(screen.getByTestId('balance-component-placeholder')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render BTC using satscomma formatting', () => {
|
||||
render(<Balance valueString={'123.456'} convertToUnit={BTC} showBalance={true} />)
|
||||
expect(screen.getByText(`123.45 600 000`)).toBeInTheDocument()
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@ const WalletHeader = ({ name, balance, unit, showBalance, loading }) => {
|
|||
return (
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
{loading && (
|
||||
<rb.Placeholder as="p" animation="wave" className="mb-0">
|
||||
<rb.Placeholder className={styles['wallet-header-title']} />
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder className={styles['wallet-header-title-placeholder']} />
|
||||
</rb.Placeholder>
|
||||
)}
|
||||
{!loading && <h1 className="text-secondary fs-6">{walletDisplayName(name)}</h1>}
|
||||
{loading && (
|
||||
<rb.Placeholder as="p" animation="wave" className="mb-0">
|
||||
<rb.Placeholder className={styles['wallet-header-subtitle']} />
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder className={styles['wallet-header-subtitle-placeholder']} />
|
||||
</rb.Placeholder>
|
||||
)}
|
||||
{!loading && (
|
||||
<h2>
|
||||
<Balance valueString={balance} convertToUnit={unit} showBalance={showBalance || false} loading={loading} />
|
||||
<Balance valueString={balance} convertToUnit={unit} showBalance={showBalance || false} />
|
||||
</h2>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -34,23 +34,26 @@ const WalletHeader = ({ name, balance, unit, showBalance, loading }) => {
|
|||
}
|
||||
|
||||
const PrivacyLevels = ({ accounts, loading }) => {
|
||||
const sortedAccounts = accounts?.sort((lhs, rhs) => lhs.account - rhs.account)
|
||||
const numAccounts = sortedAccounts?.length
|
||||
const numPrivacyLevelsPalceholders = 5
|
||||
const sortedAccounts = (accounts || []).sort((lhs, rhs) => lhs.account - rhs.account)
|
||||
const numAccounts = sortedAccounts.length
|
||||
|
||||
return (
|
||||
<div className="d-flex justify-content-center">
|
||||
<div className="d-flex flex-column align-items-start" style={{ gap: '1rem' }}>
|
||||
{loading && [...new Array(5)].map((a, index) => <LoadingPrivacyLevel key={index} level={5} />)}
|
||||
{!loading &&
|
||||
sortedAccounts.map(({ account, account_balance: balance, branches }) => (
|
||||
<PrivacyLevel
|
||||
key={account}
|
||||
numAccounts={numAccounts}
|
||||
level={parseInt(account)}
|
||||
balance={balance}
|
||||
loading={loading}
|
||||
/>
|
||||
))}
|
||||
{loading
|
||||
? Array(numPrivacyLevelsPalceholders)
|
||||
.fill('')
|
||||
.map((_, index) => <LoadingPrivacyLevel key={index} level={numPrivacyLevelsPalceholders} />)
|
||||
: sortedAccounts.map(({ account, account_balance: balance }) => (
|
||||
<PrivacyLevel
|
||||
key={account}
|
||||
numAccounts={numAccounts}
|
||||
level={parseInt(account)}
|
||||
balance={balance}
|
||||
loading={loading}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -67,13 +70,13 @@ const LoadingPrivacyLevel = ({ level }) => {
|
|||
<div className="d-flex align-items-center">
|
||||
<div className="d-flex">{loadingShields}</div>
|
||||
<div className="ps-2">
|
||||
<Balance valueString={undefined} convertToUnit={undefined} showBalance={undefined} loading={true} />
|
||||
<Balance loading={true} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const PrivacyLevel = ({ numAccounts, level, balance, loading }) => {
|
||||
const PrivacyLevel = ({ numAccounts, level, balance }) => {
|
||||
const settings = useSettings()
|
||||
|
||||
const filledShields = Array(level + 1)
|
||||
|
|
@ -148,21 +151,27 @@ export default function CurrentWalletMagic() {
|
|||
</rb.Row>
|
||||
<rb.Row className="mt-4">
|
||||
<rb.Col>
|
||||
{/* Always receive on first mixdepth. */}
|
||||
<ExtendedLink
|
||||
disabled={isLoading}
|
||||
to={routes.receive}
|
||||
state={{ account: 0 }}
|
||||
className="btn btn-outline-dark w-100"
|
||||
>
|
||||
{t('current_wallet.button_deposit')}
|
||||
{/* Todo: Withdrawing needs to factor in the privacy levels as well.
|
||||
Depending on the mixdepth/account there will be different amounts available. */}
|
||||
<ExtendedLink to={routes.send} className="btn btn-outline-dark w-100" disabled={isLoading}>
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<Sprite symbol="send" width="24" height="24" />
|
||||
<div className="ps-1">{t('current_wallet.button_withdraw')}</div>
|
||||
</div>
|
||||
</ExtendedLink>
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
{/* Todo: Withdrawing needs to factor in the privacy levels as well.
|
||||
Depending on the mixdepth/account there will be different amounts available. */}
|
||||
<ExtendedLink disabled={isLoading} to={routes.send} className="btn btn-outline-dark w-100">
|
||||
{t('current_wallet.button_withdraw')}
|
||||
{/* Always receive on first mixdepth. */}
|
||||
<ExtendedLink
|
||||
to={routes.receive}
|
||||
state={{ account: 0 }}
|
||||
className="btn btn-outline-dark w-100"
|
||||
disabled={isLoading}
|
||||
>
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<Sprite symbol="receive" width="24" height="24" />
|
||||
<div className="ps-1">{t('current_wallet.button_deposit')}</div>
|
||||
</div>
|
||||
</ExtendedLink>
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.wallet-header-title {
|
||||
.wallet-header-title-placeholder {
|
||||
width: 5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.wallet-header-subtitle {
|
||||
.wallet-header-subtitle-placeholder {
|
||||
width: 12rem;
|
||||
height: 1.8rem;
|
||||
margin-bottom: 0.45rem;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const WalletPreview = ({ wallet, walletInfo, unit, showBalance }) => {
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Balance value="0.00000000" unit="BTC" showBalance={false} loading={true} />
|
||||
<Balance loading={true} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,12 +36,15 @@ export default function Receive() {
|
|||
|
||||
setAlert(null)
|
||||
setIsLoading(true)
|
||||
|
||||
Api.getAddressNew({ walletName, mixdepth: account, token, signal: abortCtrl.signal })
|
||||
.then((res) => (res.ok ? res.json() : Api.Helper.throwError(res, t('receive.error_loading_address_failed'))))
|
||||
.then((data) => setAddress(data.address))
|
||||
.catch((err) => {
|
||||
!abortCtrl.signal.aborted && setAlert({ variant: 'danger', message: err.message })
|
||||
})
|
||||
// show the loader a little longer to avoid flickering
|
||||
.then((_) => new Promise((r) => setTimeout(r, 200)))
|
||||
.finally(() => !abortCtrl.signal.aborted && setIsLoading(false))
|
||||
|
||||
return () => abortCtrl.abort()
|
||||
|
|
@ -106,8 +109,8 @@ export default function Receive() {
|
|||
<div className={styles['qr-container']}>
|
||||
{!isLoading && address && <BitcoinQR address={address} sats={amount} />}
|
||||
{(isLoading || !address) && (
|
||||
<rb.Placeholder as="p" animation="wave" className={styles['receive-placeholder-qr-container']}>
|
||||
<rb.Placeholder xs={12} className={styles['receive-placeholder-qr']} />
|
||||
<rb.Placeholder as="div" animation="wave" className={styles['receive-placeholder-qr-container']}>
|
||||
<rb.Placeholder className={styles['receive-placeholder-qr']} />
|
||||
</rb.Placeholder>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -115,7 +118,7 @@ export default function Receive() {
|
|||
{address && <rb.Card.Text className="text-center slashed-zeroes">{address}</rb.Card.Text>}
|
||||
{!address && (
|
||||
<rb.Placeholder as="p" animation="wave" className={styles['receive-placeholder-container']}>
|
||||
<rb.Placeholder xs={8} className={styles['receive-placeholder']} />
|
||||
<rb.Placeholder xs={12} sm={10} md={8} className={styles['receive-placeholder']} />
|
||||
</rb.Placeholder>
|
||||
)}
|
||||
<div className="d-flex justify-content-center" style={{ gap: '1rem' }}>
|
||||
|
|
@ -133,7 +136,7 @@ export default function Receive() {
|
|||
}
|
||||
)
|
||||
}}
|
||||
disabled={!address}
|
||||
disabled={!address || isLoading}
|
||||
>
|
||||
{showAddressCopiedConfirmation ? (
|
||||
<>
|
||||
|
|
@ -161,17 +164,14 @@ export default function Receive() {
|
|||
</rb.Card>
|
||||
</div>
|
||||
<div className={styles['settings-container']}>
|
||||
{!isLoading && (
|
||||
<rb.Button
|
||||
variant={`${settings.theme}`}
|
||||
className="ps-0 border-0 d-flex align-items-center"
|
||||
onClick={() => setShowSettings(!showSettings)}
|
||||
disabled={isLoading}
|
||||
>
|
||||
{t('receive.button_settings')}
|
||||
<Sprite symbol={`caret-${showSettings ? 'up' : 'down'}`} className="ms-1" width="20" height="20" />
|
||||
</rb.Button>
|
||||
)}
|
||||
<rb.Button
|
||||
variant={`${settings.theme}`}
|
||||
className="ps-0 border-0 d-flex align-items-center"
|
||||
onClick={() => setShowSettings(!showSettings)}
|
||||
>
|
||||
{t('receive.button_settings')}
|
||||
<Sprite symbol={`caret-${showSettings ? 'up' : 'down'}`} className="ms-1" width="20" height="20" />
|
||||
</rb.Button>
|
||||
</div>
|
||||
<rb.Form onSubmit={onSubmit} validated={validated} noValidate>
|
||||
{showSettings && (
|
||||
|
|
@ -183,7 +183,7 @@ export default function Receive() {
|
|||
defaultValue={account}
|
||||
onChange={(e) => setAccount(parseInt(e.target.value, 10))}
|
||||
required
|
||||
disabled={accounts.length === 0}
|
||||
disabled={isLoading || accounts.length === 0}
|
||||
>
|
||||
{accounts.map((val) => (
|
||||
<option key={val} value={val}>
|
||||
|
|
@ -203,6 +203,7 @@ export default function Receive() {
|
|||
value={amount}
|
||||
min={0}
|
||||
onChange={(e) => setAmount(e.target.value)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<rb.Form.Control.Feedback type="invalid">{t('receive.feedback_invalid_amount')}</rb.Form.Control.Feedback>
|
||||
</rb.Form.Group>
|
||||
|
|
@ -211,7 +212,7 @@ export default function Receive() {
|
|||
<hr />
|
||||
<rb.Button variant="outline-dark" type="submit" disabled={isLoading} className="mt-2" style={{ width: '100%' }}>
|
||||
{isLoading ? (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<rb.Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" className="me-2" />
|
||||
{t('receive.text_getting_address')}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
.settings-container {
|
||||
margin-top: 1.5rem;
|
||||
height: 2.25rem;
|
||||
}
|
||||
|
||||
.receive-placeholder-container {
|
||||
|
|
@ -20,13 +19,17 @@
|
|||
}
|
||||
|
||||
.receive-placeholder-qr-container {
|
||||
width: 13.5rem;
|
||||
margin-bottom: 0;
|
||||
width: 16.25rem;
|
||||
}
|
||||
|
||||
.receive-placeholder-qr {
|
||||
width: 13.5rem;
|
||||
width: 13.75rem;
|
||||
height: 13.75rem;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
margin: 1.25rem;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .receive-placeholder-qr {
|
||||
width: 16.25rem;
|
||||
height: 16.25rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,8 +125,5 @@ input::-webkit-inner-spin-button {
|
|||
|
||||
.send .input-loader {
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.form-group-without-coinjoin-option {
|
||||
margin-bottom: 3.25rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ export default function Send() {
|
|||
<a
|
||||
href="https://github.com/JoinMarket-Org/joinmarket-clientserver#wallet-features"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
frozen
|
||||
</a>
|
||||
|
|
@ -464,7 +464,7 @@ export default function Send() {
|
|||
<a
|
||||
href="https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/fidelity-bonds.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
time-locked
|
||||
</a>
|
||||
|
|
@ -475,7 +475,7 @@ export default function Send() {
|
|||
<a
|
||||
href="https://github.com/JoinMarket-Org/JoinMarket-Docs/blob/master/High-level-design.md#joinmarket-transaction-types"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
JoinMarket documentation
|
||||
</a>
|
||||
|
|
@ -514,31 +514,12 @@ export default function Send() {
|
|||
)}
|
||||
|
||||
<rb.Form onSubmit={onSubmit} noValidate id="send-form">
|
||||
<rb.Form.Group className="mb-4" controlId="destination">
|
||||
<rb.Form.Label>{t('send.label_recipient')}</rb.Form.Label>
|
||||
{isLoading ? (
|
||||
<rb.Placeholder as="p" animation="wave">
|
||||
<rb.Placeholder xs={12} className="input-loader" />
|
||||
</rb.Placeholder>
|
||||
) : (
|
||||
<rb.Form.Control
|
||||
name="destination"
|
||||
placeholder={t('send.placeholder_recipient')}
|
||||
className="slashed-zeroes"
|
||||
value={destination || ''}
|
||||
required
|
||||
onChange={(e) => setDestination(e.target.value)}
|
||||
isInvalid={destination !== null && !isValidAddress(destination)}
|
||||
/>
|
||||
)}
|
||||
<rb.Form.Control.Feedback type="invalid">{t('send.feedback_invalid_recipient')}</rb.Form.Control.Feedback>
|
||||
</rb.Form.Group>
|
||||
<rb.Form.Group className="mb-4 flex-grow-1" controlId="account">
|
||||
<rb.Form.Label>
|
||||
{settings.useAdvancedWalletMode ? t('send.label_account_dev_mode') : t('send.label_account')}
|
||||
</rb.Form.Label>
|
||||
{isLoading ? (
|
||||
<rb.Placeholder as="p" animation="wave">
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder xs={12} className="input-loader" />
|
||||
</rb.Placeholder>
|
||||
) : (
|
||||
|
|
@ -563,14 +544,11 @@ export default function Send() {
|
|||
</rb.Form.Select>
|
||||
)}
|
||||
</rb.Form.Group>
|
||||
<rb.Form.Group
|
||||
className={isCoinjoinOptionEnabled ? 'mb-4' : 'form-group-without-coinjoin-option'}
|
||||
controlId="amount"
|
||||
>
|
||||
<rb.Form.Group className={isSweep ? 'mb-0' : 'mb-4'} controlId="amount">
|
||||
<rb.Form.Label form="send-form">{t('send.label_amount')}</rb.Form.Label>
|
||||
<div className="position-relative">
|
||||
{isLoading ? (
|
||||
<rb.Placeholder as="p" animation="wave">
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder xs={12} className="input-loader" />
|
||||
</rb.Placeholder>
|
||||
) : (
|
||||
|
|
@ -609,9 +587,32 @@ export default function Send() {
|
|||
</rb.Form.Control.Feedback>
|
||||
{isSweep && frozenOrLockedWarning()}
|
||||
</rb.Form.Group>
|
||||
<rb.Form.Group className="mb-4" controlId="destination">
|
||||
<rb.Form.Label>{t('send.label_recipient')}</rb.Form.Label>
|
||||
{isLoading ? (
|
||||
<rb.Placeholder as="div" animation="wave">
|
||||
<rb.Placeholder xs={12} className="input-loader" />
|
||||
</rb.Placeholder>
|
||||
) : (
|
||||
<rb.Form.Control
|
||||
name="destination"
|
||||
placeholder={t('send.placeholder_recipient')}
|
||||
className="slashed-zeroes"
|
||||
value={destination || ''}
|
||||
required
|
||||
onChange={(e) => setDestination(e.target.value)}
|
||||
isInvalid={destination !== null && !isValidAddress(destination)}
|
||||
/>
|
||||
)}
|
||||
<rb.Form.Control.Feedback type="invalid">{t('send.feedback_invalid_recipient')}</rb.Form.Control.Feedback>
|
||||
</rb.Form.Group>
|
||||
{isCoinjoinOptionEnabled && (
|
||||
<rb.Form.Group controlId="isCoinjoin" className={`${isCoinjoin ? 'mb-3' : ''}`}>
|
||||
<ToggleSwitch label={t('send.toggle_coinjoin')} onToggle={(isToggled) => setIsCoinjoin(isToggled)} />
|
||||
<ToggleSwitch
|
||||
label={t('send.toggle_coinjoin')}
|
||||
initialValue={isCoinjoin}
|
||||
onToggle={(isToggled) => setIsCoinjoin(isToggled)}
|
||||
/>
|
||||
</rb.Form.Group>
|
||||
)}
|
||||
</rb.Form>
|
||||
|
|
@ -624,7 +625,7 @@ export default function Send() {
|
|||
)}
|
||||
<rb.Button variant="dark" type="submit" disabled={isSending || !formIsValid} className="mt-4" form="send-form">
|
||||
{isSending ? (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<rb.Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" className="me-2" />
|
||||
{t('send.text_sending')}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue