Skip to content

Commit

Permalink
feat: top nav account details
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodes05 committed Sep 19, 2023
1 parent 31dbf2d commit ab425f7
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 228 deletions.
19 changes: 18 additions & 1 deletion apps/oeth/src/components/Topnav.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useState } from 'react';

import {
alpha,
Box,
Expand All @@ -8,9 +10,11 @@ import {
useMediaQuery,
useTheme,
} from '@mui/material';
import { AccountDetails } from '@origin/oeth/shared';
import { OpenAccountModalButton } from '@origin/shared/providers';
import { useIntl } from 'react-intl';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { useAccount } from 'wagmi';

import { routes } from '../routes';

Expand All @@ -22,6 +26,9 @@ export function Topnav(props: BoxProps) {
const intl = useIntl();
const navigate = useNavigate();
const location = useLocation();
const { isConnected } = useAccount();
const [accountModalAnchor, setAccountModalAnchor] =
useState<HTMLButtonElement | null>(null);

return (
<Box
Expand Down Expand Up @@ -190,7 +197,17 @@ export function Topnav(props: BoxProps) {
? intl.formatMessage({ defaultMessage: 'IPFS' })
: intl.formatMessage({ defaultMessage: 'View on IPFS' })}
</MuiLink>
<OpenAccountModalButton />
<OpenAccountModalButton
onClick={(e) => {
if (isConnected) {
setAccountModalAnchor(e.currentTarget);
}
}}
/>
<AccountDetails
anchor={accountModalAnchor}
setAnchor={setAccountModalAnchor}
/>
</Box>
<Divider
sx={{
Expand Down
169 changes: 169 additions & 0 deletions libs/oeth/shared/src/components/AccountDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import React from 'react';

import {
alpha,
Box,
Button,
Divider,
Popover,
Stack,
Typography,
useTheme,
} from '@mui/material';
import { Icon, LinkIcon, MiddleTruncated } from '@origin/shared/components';
import { tokens } from '@origin/shared/contracts';
import { quantityFormat } from '@origin/shared/utils';
import { useIntl } from 'react-intl';
import { useAccount, useBalance, useDisconnect } from 'wagmi';

const values = ['eth', 'weth', 'reth', 'frxeth', 'sfrxeth', 'steth'];

const padding = { paddingInline: 2, paddingBlock: 3 };

interface Props {
anchor: HTMLElement | null;
setAnchor: (value: HTMLButtonElement | null) => void;
}

export function AccountDetails({ anchor, setAnchor }: Props) {
const intl = useIntl();
const { address, isConnected, connector } = useAccount();
const { disconnect } = useDisconnect();

const theme = useTheme();
const { data: eth } = useBalance({
address,
token: tokens.mainnet.ETH.address,
enabled: isConnected,
});
const { data: weth } = useBalance({
address,
token: tokens.mainnet.WETH.address,
enabled: isConnected,
});
const { data: reth } = useBalance({
address,
token: tokens.mainnet.rETH.address,
});
const { data: frxeth } = useBalance({
address,
token: tokens.mainnet.frxETH.address,
});
const { data: sfrxeth } = useBalance({
address,
token: tokens.mainnet.sfrxETH.address,
});
const { data: steth } = useBalance({
address,
token: tokens.mainnet.stETH.address,
});

function close() {
setAnchor(null);
}
if (!isConnected) return null;
const balance = {
eth: eth?.formatted || '0',
weth: weth?.formatted || '0',
reth: reth?.formatted || '0',
frxeth: frxeth?.formatted || '0',
sfrxeth: sfrxeth?.formatted || '0',
steth: steth?.formatted || '0',
};
return (
<Popover
open={!!anchor}
anchorEl={anchor}
onClose={close}
anchorOrigin={{
vertical: 50,
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
sx={{
'& .MuiPopover-paper': {
width: (theme) => ({
xs: '90vw',
md: `min(${theme.typography.pxToRem(250)}, 90vw)`,
}),
[theme.breakpoints.down('md')]: {
left: '0 !important',
right: 0,
marginInline: 'auto',
},
},
}}
>
<Box>
<Stack
component={Typography}
color="primary.contrastText"
justifyContent="space-between"
alignItems="center"
direction="row"
sx={padding}
>
Account
<Button
variant="contained"
sx={{
borderRadius: 7,
paddingInline: 2.375,
paddingBlock: 1.25,
fontSize: '0.75rem',
lineHeight: '0.75rem',
'&:hover': {
background: (theme) => alpha(theme.palette.common.white, 0.05),
},
}}
color="secondary"
disableElevation
onClick={() => {
disconnect();
close();
}}
>
Disconnect
</Button>
</Stack>
<Divider />
<Stack
alignItems="center"
gap={1.5}
sx={padding}
direction="row"
color="primary.contrastText"
>
<Icon src={`/images/${connector.id.toLowerCase()}-icon.svg`} />

<MiddleTruncated>{address}</MiddleTruncated>
<LinkIcon
url={`https://etherscan.io/address/${address}`}
sx={{ transform: 'translateY(5%)' }}
/>
</Stack>
<Divider />
<Stack sx={padding} gap={2}>
{values.map((value) => (
<Stack
key={value}
component={Typography}
direction="row"
alignItems="center"
color="primary.contrastText"
gap={1}
>
<Icon src={`/images/currency/${value}-icon-small.svg`} />
{intl.formatNumber(+balance[value], quantityFormat)}
&nbsp;
{value}
</Stack>
))}
</Stack>
</Box>
</Popover>
);
}
2 changes: 2 additions & 0 deletions libs/oeth/shared/src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './ApyHeader';
export * from './AccountDetails';
Empty file.
2 changes: 1 addition & 1 deletion libs/oeth/shared/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './components/ApyHeader';
export * from './components';
export * from './clients';
export * from './generated/graphql';
10 changes: 8 additions & 2 deletions libs/shared/components/src/LinkIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ interface Props extends LinkProps {
size?: string;
}

export function LinkIcon({ url, size = '0.875rem', ...rest }: Props) {
export function LinkIcon({
url,
size = '0.875rem',
target = '_blank',
rel = 'noopener noreferrer nofollow',
...rest
}: Props) {
return (
<Link href={url} {...rest}>
<Link href={url} target={target} rel={rel} {...rest}>
<Box
component="img"
src="/images/link-icon-purple.svg"
Expand Down
14 changes: 6 additions & 8 deletions libs/shared/components/src/top-nav/ConnectedButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { MiddleTruncated } from '../MiddleTruncated';
import { Icon } from './Icon';
import { styles } from './utils';

import type { ButtonProps, SxProps, Theme } from '@mui/material';
import type { ButtonProps } from '@mui/material';

import type { Connected } from './types';

Expand Down Expand Up @@ -156,18 +156,16 @@ export type ConnectButtonProps = {
connected: boolean;
} & ButtonProps;

export function ConnectButton({ connected, ...rest }: ConnectButtonProps) {
export function ConnectButton({ connected, sx, ...rest }: ConnectButtonProps) {
return (
<Button
sx={
sx={Object.assign(
{
...styles,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
paddingInline: { xs: 1, sm: 3 },
paddingInlineStart: { xs: 1, sm: connected ? 1 : 3 },
borderRadius: 25,
background: (theme) =>
connected
? `linear-gradient(0deg, ${alpha(
Expand All @@ -190,9 +188,9 @@ export function ConnectButton({ connected, ...rest }: ConnectButtonProps) {
},
minWidth: 0,
gap: 1.5,
...rest?.sx,
} as SxProps<Theme>
}
},
sx || {},
)}
disableElevation
disableRipple
disableTouchRipple
Expand Down
8 changes: 2 additions & 6 deletions libs/shared/providers/src/wagmi/components/AddressLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,15 @@ export const AddressLabel = ({
chainId: mainnet.id,
});

const fontFamily = monospace ? 'monospace' : 'inherit';

return enableEnsName ? (
isEnsNameLoading ? (
<Skeleton sx={{ minWidth: 100, ...rest?.sx }} />
) : (
<MiddleTruncated textProps={{ fontFamily, ...rest }}>
<MiddleTruncated textProps={{ ...rest }}>
{ensName ?? address}
</MiddleTruncated>
)
) : (
<MiddleTruncated textProps={{ fontFamily, ...rest }}>
{address}
</MiddleTruncated>
<MiddleTruncated textProps={{ ...rest }}>{address}</MiddleTruncated>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Box, useMediaQuery, useTheme } from '@mui/material';
import { ConnectButton as CustomButton } from '@origin/shared/components';
import { ConnectButton } from '@rainbow-me/rainbowkit';
import { useIntl } from 'react-intl';
import Jazzicon, { jsNumberForAddress } from 'react-jazzicon';
import { useAccount, useEnsAvatar, useEnsName } from 'wagmi';

import { AddressLabel } from './AddressLabel';

Expand All @@ -16,7 +19,15 @@ export const OpenAccountModalButton = ({
connectLabel,
...props
}: OpenAccountModalButtonProps) => {
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down('md'));
const intl = useIntl();
const { address, isConnected } = useAccount();
const { data: ensName } = useEnsName({ address, enabled: isConnected });
const { data: ensAvatar } = useEnsAvatar({
name: ensName,
enabled: !!ensName,
});

const handleClick =
(handler: () => void) => (evt: MouseEvent<HTMLButtonElement>) => {
Expand All @@ -28,14 +39,7 @@ export const OpenAccountModalButton = ({

return (
<ConnectButton.Custom>
{({
account,
chain,
openChainModal,
openConnectModal,
openAccountModal,
mounted,
}) => {
{({ account, chain, openChainModal, openConnectModal, mounted }) => {
if (!mounted || !account || !chain) {
return (
<CustomButton
Expand Down Expand Up @@ -72,12 +76,40 @@ export const OpenAccountModalButton = ({
if (props?.onClick) {
props.onClick(evt);
}
openAccountModal();
}}
sx={{
maxWidth: '10rem',
[theme.breakpoints.down('md')]: {
'& > div:last-of-type': {
display: 'none',
},
},
}}
>
{ensAvatar ? (
<Box
component={'img'}
src={ensAvatar}
sx={{
width: (theme) => theme.spacing(3),
height: (theme) => theme.spacing(3),
}}
/>
) : (
<Jazzicon
diameter={24}
paperStyles={!isSmall ? { width: '6.875rem' } : {}}
seed={jsNumberForAddress(address)}
/>
)}

<AddressLabel
address={account.address as HexAddress}
enableEnsName
fontFamily="Inter"
fontStyle="normal"
fontWeight={500}
fontSize="1rem"
/>
</CustomButton>
);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "18.2.0",
"react-intl": "^6.4.6",
"react-jazzicon": "^1.0.4",
"react-router-dom": "6.16.0",
"react-tracked": "^1.7.11",
"tslib": "^2.6.2",
Expand Down
Loading

0 comments on commit ab425f7

Please sign in to comment.