1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

refactor wallet popup into generic tooltip component

This commit is contained in:
Matthias Kretschmann 2020-08-06 12:44:25 +02:00
parent a3d98477ee
commit a021fb3f13
Signed by: m
GPG Key ID: 606EEEF3C479A91F
7 changed files with 126 additions and 110 deletions

View File

@ -1,4 +1,4 @@
import React from 'react' import React, { ReactElement, ReactNode } from 'react'
import styles from './Label.module.css' import styles from './Label.module.css'
const Label = ({ const Label = ({
@ -7,9 +7,9 @@ const Label = ({
...props ...props
}: { }: {
required?: boolean required?: boolean
children: string children: ReactNode
htmlFor: string htmlFor: string
}) => ( }): ReactElement => (
<label <label
className={`${styles.label} ${required && styles.required}`} className={`${styles.label} ${required && styles.required}`}
title={required ? 'Required' : ''} title={required ? 'Required' : ''}

View File

@ -0,0 +1,41 @@
.tooltip {
display: inline-block;
}
.content {
composes: box from './Box.module.css';
padding: calc(var(--spacer) / 4);
min-width: 20rem;
max-width: 25rem;
font-size: var(--font-size-small);
}
.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);
}
.content[data-placement*='top'] > .arrow {
bottom: -4px;
}
.content[data-placement*='bottom'] > .arrow {
top: -4px;
}
.content[data-placement*='left'] > .arrow {
right: -4px;
}
.content[data-placement*='right'] > .arrow {
left: -4px;
}

View File

@ -1,24 +1,77 @@
import React, { ReactElement, forwardRef } from 'react' import React, { ReactElement, ReactNode } from 'react'
import Tippy from '@tippyjs/react' import loadable from '@loadable/component'
import { useSpring, animated } from 'react-spring'
import styles from './Tooltip.module.css'
export default function Tooltip({ const Tippy = loadable(() => import('@tippyjs/react/headless'))
content,
children const animation = {
}: { config: { tension: 400, friction: 20 },
content: string from: { transform: 'scale(0.5) translateY(-3rem)' },
children: ReactElement to: { transform: 'scale(1) translateY(0)' }
}) {
return (
<Tippy content={content}>
<CustomWrapper>{children}</CustomWrapper>
</Tippy>
)
} }
// Forward ref for Tippy.js // Forward ref for Tippy.js
// eslint-disable-next-line // eslint-disable-next-line
const CustomWrapper = forwardRef( const DefaultTrigger = React.forwardRef((props, ref: any) => {
({ children }: { children: ReactElement }, ref: any) => { return <i ref={ref}>Info</i>
return <div ref={ref}>{children}</div> })
export default function Tooltip({
content,
children,
trigger,
disabled
}: {
content: ReactNode
children?: ReactNode
trigger?: string
disabled?: boolean
}): ReactElement {
const [props, setSpring] = useSpring(() => animation.from)
function onMount() {
setSpring({
transform: 'scale(1) translateY(0)',
onRest: (): void => null,
config: animation.config
})
} }
)
function onHide({ unmount }: { unmount: any }) {
setSpring({
...animation.from,
onRest: unmount,
config: { ...animation.config, clamp: true }
})
}
return (
<Tippy
interactive
interactiveBorder={30}
zIndex={1}
trigger={trigger || 'mouseenter focus'}
disabled={disabled || null}
render={(attrs: any) => (
<animated.div style={props}>
<div className={styles.content} {...attrs}>
{content}
<div className={styles.arrow} data-popper-arrow />
</div>
</animated.div>
)}
appendTo={
typeof document !== 'undefined' && document.querySelector('body')
}
animation
onMount={onMount}
onHide={onHide}
fallback={
<div className={styles.tooltip}>{children || <DefaultTrigger />}</div>
}
>
<div className={styles.tooltip}>{children || <DefaultTrigger />}</div>
</Tippy>
)
}

View File

@ -10,6 +10,7 @@ import { isCorrectNetwork } from '../../../../utils/wallet'
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata' import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
import InputElement from '../../../atoms/Input/InputElement' import InputElement from '../../../atoms/Input/InputElement'
import Label from '../../../atoms/Input/Label' import Label from '../../../atoms/Input/Label'
import Tooltip from '../../../atoms/Tooltip'
export default function Advanced({ export default function Advanced({
ocean, ocean,
@ -95,7 +96,9 @@ export default function Advanced({
</div> </div>
<footer className={styles.summary}> <footer className={styles.summary}>
<Label htmlFor="liquidityProviderFee">Liquidity Provider Fee</Label> <Label htmlFor="liquidityProviderFee">
Liquidity Provider Fee <Tooltip content="Help Me" />
</Label>
<InputElement <InputElement
value={liquidityProviderFee} value={liquidityProviderFee}
name="liquidityProviderFee" name="liquidityProviderFee"

View File

@ -1,8 +1,5 @@
.details { .details {
composes: box from '../../atoms/Box.module.css'; padding: calc(var(--spacer) / 4);
padding: calc(var(--spacer) / 2) !important;
min-width: 20rem;
max-width: 25rem;
} }
.balance { .balance {
@ -31,33 +28,3 @@
font-size: var(--font-size-small); font-size: var(--font-size-small);
color: var(--color-secondary); color: var(--color-secondary);
} }
.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

@ -8,11 +8,11 @@ import { getInjectedProviderName } from 'web3modal'
import Conversion from '../../atoms/Price/Conversion' import Conversion from '../../atoms/Price/Conversion'
import { formatCurrency } from '@coingecko/cryptoformat' import { formatCurrency } from '@coingecko/cryptoformat'
export default function Details({ attrs }: { attrs: any }): ReactElement { export default function Details(): ReactElement {
const { balance, connect, logout, chainId } = useOcean() const { balance, connect, logout, chainId } = useOcean()
return ( return (
<div className={styles.details} {...attrs}> <div className={styles.details}>
<ul> <ul>
{Object.entries(balance).map(([key, value]) => ( {Object.entries(balance).map(([key, value]) => (
<li className={styles.balance} key={key}> <li className={styles.balance} key={key}>
@ -41,7 +41,6 @@ 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

@ -1,62 +1,15 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import loadable from '@loadable/component'
import { useSpring, animated } from 'react-spring'
import Account from './Account' import Account from './Account'
import Details from './Details' import Details from './Details'
import Tooltip from '../../atoms/Tooltip'
import { useOcean } from '@oceanprotocol/react' import { useOcean } from '@oceanprotocol/react'
const Tippy = loadable(() => import('@tippyjs/react/headless'))
const animation = {
config: { tension: 400, friction: 20 },
from: { transform: 'scale(0.5) translateY(-3rem)' },
to: { transform: 'scale(1) translateY(0)' }
}
export default function Wallet(): ReactElement { export default function Wallet(): ReactElement {
const { accountId, refreshBalance } = useOcean() const { accountId } = useOcean()
const [props, setSpring] = useSpring(() => animation.from)
// always refetch balance when popover is opened
function onMount() {
accountId && refreshBalance()
setSpring({
transform: 'scale(1) translateY(0)',
onRest: (): void => null,
config: animation.config
})
}
function onHide({ unmount }: { unmount: any }) {
setSpring({
...animation.from,
onRest: unmount,
config: { ...animation.config, clamp: true }
})
}
return ( return (
<Tippy <Tooltip content={<Details />} trigger="click focus" disabled={!accountId}>
interactive
interactiveBorder={30}
trigger="click focus"
zIndex={1}
render={(attrs: any) => (
<animated.div style={props}>
<Details attrs={attrs} />
</animated.div>
)}
appendTo={
typeof document !== 'undefined' && document.querySelector('body')
}
animation
onMount={onMount}
onHide={onHide}
disabled={!accountId}
fallback={<Account />}
>
<Account /> <Account />
</Tippy> </Tooltip>
) )
} }