Skip to content

Commit

Permalink
feat(frontend): add locked balance tooltip (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitayutanov authored Dec 5, 2024
1 parent 7809040 commit 7d1fa86
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 111 deletions.
2 changes: 2 additions & 0 deletions frontend/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Input, Checkbox, Radio, Select, Textarea } from './form';
import { Container, Footer, Header, ErrorBoundary, PrivateRoute, Skeleton, TruncatedText } from './layout';
import { LinkButton } from './link-button';
import { NetworkCard } from './network-card';
import { Tooltip } from './tooltip';

export {
Header,
Expand All @@ -22,4 +23,5 @@ export {
LinkButton,
Card,
CopyButton,
Tooltip,
};
3 changes: 3 additions & 0 deletions frontend/src/components/tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Tooltip } from './tooltip';

export { Tooltip };
59 changes: 59 additions & 0 deletions frontend/src/components/tooltip/tooltip.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.container,
.skeleton {
flex-shrink: 0;
}

.container {
display: flex;

position: relative;

svg {
transition: 0.25s opacity;

&:hover {
opacity: 0.75;
}
}

&:hover {
.tooltip {
opacity: 1;
}
}
}

.tooltip {
position: absolute;

padding: 10px 16px;

display: flex;
flex-direction: column;
gap: 4px;

font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #fff;
white-space: nowrap;

background-color: #000;
border-radius: 4px;
box-shadow: 0px 8px 16px 0px rgba(#000, 0.24);

opacity: 0;
pointer-events: none;
transition: 0.25s opacity;
}

.top {
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
}

.bottom-end {
top: calc(100% + 8px);
right: 0;
}
40 changes: 40 additions & 0 deletions frontend/src/components/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ReactNode } from 'react';

import { SVGComponent } from '@/types';
import { cx } from '@/utils';

import { Skeleton } from '../layout';

import QuestionSVG from './question.svg?react';
import styles from './tooltip.module.scss';

type BaseProps = {
text?: string;
children?: ReactNode;
position?: 'top' | 'bottom-end';
SVG?: SVGComponent;
};

type TextProps = BaseProps & { text: string };
type ChildrenProps = BaseProps & { children: ReactNode };
type Props = TextProps | ChildrenProps;

function Tooltip({ text, children, position = 'top', SVG = QuestionSVG }: Props) {
return (
<div className={styles.container}>
<SVG />

<div className={cx(styles.tooltip, styles[position])}>
{text ? <p className={styles.heading}>{text}</p> : children}
</div>
</div>
);
}

function TooltipSkeleton({ disabled }: { disabled?: boolean }) {
return <Skeleton width="14px" height="14px" borderRadius="50%" className={styles.skeleton} disabled={disabled} />;
}

Tooltip.Skeleton = TooltipSkeleton;

export { Tooltip };
Original file line number Diff line number Diff line change
@@ -1,82 +1,7 @@
.container,
.skeleton {
flex-shrink: 0;
}

.container {
display: flex;

position: relative;

svg {
cursor: pointer;
transition: 0.25s opacity;

&:hover {
opacity: 0.75;
}
}

&:hover {
.tooltip {
opacity: 1;
}
}
}

.tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translate(-50%, -4px);

padding: 8px 12px;

display: flex;
flex-direction: column;
gap: 4px;

background-color: #fff;
border-radius: 6px;
box-shadow: 0px 0px 28px 0px #00000033;

opacity: 0;
pointer-events: none;
transition: 0.25s opacity;

&::before {
content: '';

position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;

width: calc(100% - 12px);
height: calc(100% - 8px);
margin: auto;

background-image: linear-gradient(164.33deg, rgba(14, 211, 163, 0.1) 9.48%, rgba(242, 242, 242, 0.1) 31.6%);
border-radius: inherit;
}
}

.heading,
.subheading {
white-space: nowrap;
}

.heading {
font-weight: 500;
opacity: 0.9;
}

.subheading {
opacity: 0.75;
}

.disabled {
opacity: 0.25;
pointer-events: none;
opacity: 0.85;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { formatUnits, parseUnits } from 'viem';

import { Skeleton } from '@/components';
import { Tooltip } from '@/components';
import { isUndefined } from '@/utils';

import QuestionSVG from '../../assets/question.svg?react';

import styles from './ft-allowance-tip.module.scss';

type Props = {
Expand All @@ -19,16 +17,7 @@ type Props = {
function FTAllowanceTip({ allowance, decimals, symbol, amount, isVaraNetwork, isLoading }: Props) {
const isEmpty = isUndefined(allowance) || !decimals || !symbol;

if (isLoading || isEmpty)
return (
<Skeleton
width="14px"
height="14px"
borderRadius="50%"
className={styles.skeleton}
disabled={!isLoading && isEmpty}
/>
);
if (isLoading || isEmpty) return <Tooltip.Skeleton disabled={!isLoading && isEmpty} />;

const formattedAllowance = formatUnits(allowance, decimals);
const contractName = isVaraNetwork ? 'VFT Manager' : 'ETH Bridging Payment';
Expand All @@ -46,19 +35,15 @@ function FTAllowanceTip({ allowance, decimals, symbol, amount, isVaraNetwork, is
};

return (
<div className={styles.container}>
<QuestionSVG />

<div className={styles.tooltip}>
<p className={styles.heading}>
{allowance > 0
? `You have already approved ${formattedAllowance} ${symbol} to the ${contractName} contract.`
: `You don't have any approved tokens to the ${contractName} contract yet.`}
</p>

<p className={styles.subheading}>{getSubheading()}</p>
</div>
</div>
<Tooltip>
<p className={styles.heading}>
{allowance > 0
? `You have already approved ${formattedAllowance} ${symbol} to the ${contractName} contract.`
: `You don't have any approved tokens to the ${contractName} contract yet.`}
</p>

<p className={styles.subheading}>{getSubheading()}</p>
</Tooltip>
);
}

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/features/token-tracker/assets/warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.container {
display: flex;
align-items: flex-start;
gap: 4px;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useAccount } from '@gear-js/react-hooks';

import { Tooltip } from '@/components';
import { WRAPPED_VARA_CONTRACT_ADDRESS } from '@/consts';
import { useVaraFTBalance, useEthAccount, useModal, useTokens } from '@/hooks';

import WarningSVG from '../../assets/warning.svg?react';
import { TokenTrackerModal } from '../token-tracker-modal';

import styles from './token-tracker.module.scss';

function TokenTracker() {
const { account } = useAccount();
const ethAccount = useEthAccount();
Expand All @@ -18,15 +22,17 @@ function TokenTracker() {

return (
<>
<button type="button" onClick={open}>
My Tokens
</button>

{isOpen && (
// TODO: remove assertion after @gear-js/vara-ui heading is updated to accept ReactNode.
// fast fix for now, cuz major font update was made without a fallback,
<TokenTrackerModal lockedBalance={varaLockedBalance} close={close} />
)}
<div className={styles.container}>
<button type="button" onClick={open}>
My Tokens
</button>

{Boolean(varaLockedBalance.value) && (
<Tooltip SVG={WarningSVG} text="You have tokens available to unlock" position="bottom-end" />
)}
</div>

{isOpen && <TokenTrackerModal lockedBalance={varaLockedBalance} close={close} />}
</>
);
}
Expand Down

0 comments on commit 7d1fa86

Please sign in to comment.