1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-11-15 01:34:57 +01:00

refined wallet interactions

This commit is contained in:
Matthias Kretschmann 2020-07-09 12:27:59 +02:00
parent 829b9b8ce6
commit 970624e652
Signed by: m
GPG Key ID: 606EEEF3C479A91F
9 changed files with 135 additions and 35 deletions

View File

@ -1,4 +1,4 @@
import React, { ReactNode, FormEvent } from 'react' import React, { ReactNode, FormEvent, ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import classNames from 'classnames/bind' import classNames from 'classnames/bind'
import styles from './Button.module.css' import styles from './Button.module.css'
@ -27,7 +27,7 @@ export default function Button({
size, size,
style, style,
...props ...props
}: ButtonProps) { }: ButtonProps): ReactElement {
const styleClasses = cx({ const styleClasses = cx({
button: true, button: true,
primary: style === 'primary', primary: style === 'primary',

View File

@ -9,7 +9,6 @@
/* yellow triangle */ /* yellow triangle */
.warning { .warning {
composes: status;
border-radius: 0; border-radius: 0;
background: none; background: none;
width: 0; width: 0;
@ -21,7 +20,6 @@
/* red square */ /* red square */
.error { .error {
composes: status;
border-radius: 0; border-radius: 0;
background: var(--brand-alert-red); background: var(--brand-alert-red);
text-transform: capitalize; text-transform: capitalize;

View File

@ -1,13 +1,22 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import classNames from 'classnames/bind'
import styles from './Status.module.css' import styles from './Status.module.css'
export default function Status({ state }: { state?: string }): ReactElement { const cx = classNames.bind(styles)
const classes =
state === 'error'
? styles.error
: state === 'warning'
? styles.warning
: styles.status
return <i className={classes} /> export default function Status({
state,
className
}: {
state?: string
className?: string
}): ReactElement {
const styleClasses = cx({
status: true,
warning: state === 'warning',
error: state === 'error',
[className]: className
})
return <i className={styleClasses} />
} }

View File

@ -1,14 +1,24 @@
.wallet { .button {
font-family: var(--font-family-base);
font-weight: var(--font-weight-bold);
font-size: var(--font-size-small);
text-transform: uppercase;
border: 1px solid var(--brand-grey-lighter); border: 1px solid var(--brand-grey-lighter);
border-radius: var(--border-radius); border-radius: var(--border-radius);
padding: calc(var(--spacer) / 8) calc(var(--spacer) / 4); padding: calc(var(--spacer) / 6) calc(var(--spacer) / 4);
white-space: nowrap;
background: none;
color: var(--brand-grey);
margin: 0;
transition: border 0.2s ease-out;
cursor: pointer;
} }
.address { .button:hover,
font-size: var(--font-size-small); .button:focus {
font-family: var(--font-family-monospace); transform: none;
white-space: nowrap; outline: 0;
margin-bottom: calc(var(--spacer) / 8); border-color: var(--brand-grey-light);
} }
.blockies { .blockies {
@ -20,3 +30,29 @@
vertical-align: middle; vertical-align: middle;
margin-right: calc(var(--spacer) / 6); margin-right: calc(var(--spacer) / 6);
} }
.address {
text-transform: none;
border-right: 1px solid var(--brand-grey-lighter);
padding-right: calc(var(--spacer) / 4);
}
.button svg {
width: 1em;
height: 1em;
fill: var(--brand-grey-lighter);
display: inline-block;
vertical-align: middle;
margin-left: calc(var(--spacer) / 4);
transition: transform 0.2s ease-out;
}
.wallet[aria-expanded='true'] .button svg {
transform: rotate(180deg);
}
.status {
margin-left: calc(var(--spacer) / 4);
position: relative;
top: 1px;
}

View File

@ -1,28 +1,51 @@
import React from 'react' import React from 'react'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
import styles from './Account.module.css' import styles from './Account.module.css'
import { useWeb3 } from '@oceanprotocol/react' import { useWeb3, useOcean } from '@oceanprotocol/react'
import { toDataUrl } from 'ethereum-blockies' import { toDataUrl } from 'ethereum-blockies'
import { ReactComponent as Caret } from '../../../images/caret.svg'
import Status from '../../atoms/Status'
function accountTruncate(account: string) {
const middle = account.substring(6, 38)
const truncated = account.replace(middle, '…')
return truncated
}
// Forward ref for Tippy.js // Forward ref for Tippy.js
// eslint-disable-next-line // eslint-disable-next-line
const Account = React.forwardRef((props, ref: any) => { const Account = React.forwardRef((props, ref: any) => {
const { account, web3Connect } = useWeb3() const { account, web3Connect, ethProviderStatus } = useWeb3()
const { status } = useOcean()
const blockies = account && toDataUrl(account) const blockies = account && toDataUrl(account)
const hasSuccess = ethProviderStatus === 1 && status === 1
return ( return account ? (
<div className={styles.wallet} ref={ref}> <button className={styles.button} aria-label="Account" ref={ref}>
{account ? ( {blockies && (
<div className={styles.address}> <img
<img className={styles.blockies} src={blockies} alt="Blockies" /> className={styles.blockies}
{`${account.substring(0, 12)}...`} src={blockies}
</div> alt="Blockies"
) : ( aria-hidden="true"
<Button style="text" size="small" onClick={() => web3Connect.connect()}> />
Activate Wallet
</Button>
)} )}
</div> <span className={styles.address}>{accountTruncate(account)}</span>
{!hasSuccess && (
<Status className={styles.status} state="warning" aria-hidden />
)}
<Caret aria-hidden="true" />
</button>
) : (
<button
className={styles.button}
onClick={() => web3Connect.connect()}
// Need the `ref` here although we do not want
// the Tippy to show in this state.
ref={ref}
>
Activate Wallet
</button>
) )
}) })

View File

@ -21,3 +21,33 @@
display: inline-block; display: inline-block;
margin-left: 0.1rem; margin-left: 0.1rem;
} }
.arrow,
.arrow::before {
position: absolute;
width: 1.2rem;
height: 1.2rem;
z-index: -1;
}
.arrow::before {
content: '';
transform: rotate(45deg);
background: var(--brand-grey-lighter);
}
.details[data-placement*='top'] > .arrow {
bottom: -4px;
}
.details[data-placement*='bottom'] > .arrow {
top: -4px;
}
.details[data-placement*='left'] > .arrow {
right: -4px;
}
.details[data-placement*='right'] > .arrow {
left: -4px;
}

View File

@ -12,8 +12,8 @@ export default function Details({ attrs }: { attrs: any }): ReactElement {
const oceanBalanceText = formatNumber(Number(balanceInOcean)) const oceanBalanceText = formatNumber(Number(balanceInOcean))
return ( return (
<div className={styles.details}> <div className={styles.details} {...attrs}>
<ul {...attrs}> <ul>
<li className={styles.balance}> <li className={styles.balance}>
OCEAN <span>{oceanBalanceText}</span> OCEAN <span>{oceanBalanceText}</span>
</li> </li>
@ -31,6 +31,7 @@ export default function Details({ attrs }: { attrs: any }): ReactElement {
</li> </li>
</ul> </ul>
<Web3Feedback /> <Web3Feedback />
<div className={styles.arrow} data-popper-arrow />
</div> </div>
) )
} }

View File

@ -4,6 +4,7 @@ import { useSpring, animated } from 'react-spring'
import { useWeb3 } from '@oceanprotocol/react' import { useWeb3 } from '@oceanprotocol/react'
import Account from './Account' import Account from './Account'
import Details from './Details' import Details from './Details'
import styles from './index.module.css'
const Tippy = loadable(() => import('@tippyjs/react/headless')) const Tippy = loadable(() => import('@tippyjs/react/headless'))
@ -40,6 +41,7 @@ export default function Wallet(): ReactElement {
<Tippy <Tippy
interactive interactive
interactiveBorder={30} interactiveBorder={30}
trigger="click focus"
render={(attrs: any) => ( render={(attrs: any) => (
<animated.div style={props}> <animated.div style={props}>
<Details attrs={attrs} /> <Details attrs={attrs} />

1
src/images/caret.svg Normal file
View File

@ -0,0 +1 @@
<svg height="22" viewBox="0 0 32 22" width="32" xmlns="http://www.w3.org/2000/svg"><path d="m32 6.016-5.672-5.664s-3.4426667 3.43431597-10.328 10.3029479l-10.327-10.3109479-5.673 5.672 16 15.984z"/></svg>

After

Width:  |  Height:  |  Size: 204 B