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:
parent
a3d98477ee
commit
a021fb3f13
@ -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' : ''}
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user