feat(wallet): add a custom link component to match new design (#1355)

* feat(wallet): add custom link component

* feat(wallet): uniformize links

* feat(wallet): move link component to ts-packages

* feat(wallet): post merge fix

* ts-packages: build theme first, then react components

* Update README.md

Co-authored-by: Mark Sinclair <mmsinclair@gmail.com>
This commit is contained in:
Pierre Dommerc
2022-06-16 13:36:30 +02:00
committed by GitHub
parent 661a1420c1
commit b42472486f
18 changed files with 146 additions and 51 deletions
@@ -3,7 +3,6 @@ import {
Box,
Chip,
CircularProgress,
Link,
Table,
TableBody,
TableCell,
@@ -19,6 +18,7 @@ import { visuallyHidden } from '@mui/utils';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
import { DelegationWithEverything } from '@nymproject/types';
import { Link } from '@nymproject/react/link/Link';
import { format, formatDistanceToNow, parseISO } from 'date-fns';
import { styled } from '@mui/material/styles';
import { tableCellClasses } from '@mui/material/TableCell';
@@ -163,11 +163,8 @@ export const DelegationList: React.FC<{
<Link
target="_blank"
href={`${explorerUrl}/network-components/mixnode/${item.node_identity}`}
color="inherit"
underline="none"
>
{item.node_identity.slice(0, 6)}...{item.node_identity.slice(-6)}
</Link>
text={`${item.node_identity.slice(0, 6)}...${item.node_identity.slice(-6)}`}
/>
</Tooltip>
</TableCell>
<TableCell align="center">{!item.avg_uptime_percent ? '-' : `${item.avg_uptime_percent}%`}</TableCell>
@@ -1,5 +1,6 @@
import React from 'react';
import { Box, Button, CircularProgress, Link, Modal, Stack, Typography } from '@mui/material';
import { Box, Button, CircularProgress, Modal, Stack, Typography } from '@mui/material';
import { Link } from '@nymproject/react/link/Link';
import { modalStyle } from '../Modals/styles';
export type ActionType = 'delegate' | 'undelegate' | 'redeem' | 'redeem-all' | 'compound';
@@ -101,9 +102,13 @@ export const DelegationModal: React.FC<
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
Check the transaction {transactions.length > 1 ? 'hashes' : 'hash'}:
{transactions.map((transaction) => (
<Link key={transaction.hash} href={transaction.url} target="_blank" sx={{ ml: 1 }}>
{transaction.hash.slice(0, 6)}
</Link>
<Link
key={transaction.hash}
href={transaction.url}
target="_blank"
sx={{ ml: 1 }}
text={transaction.hash.slice(0, 6)}
/>
))}
</Typography>
)}
@@ -1,6 +1,7 @@
import React from 'react';
import { Box, Link, Typography } from '@mui/material';
import { Box, Typography } from '@mui/material';
import { DelegationWithEverything } from '@nymproject/types';
import { Link } from '@nymproject/react/link/Link';
import { DelegationList } from './DelegationList';
import { DelegationListItemActions } from './DelegationActions';
@@ -18,13 +19,7 @@ export const Delegations: React.FC<{
onItemActionClick={onDelegationItemActionClick}
/>
<Box sx={{ mt: 3 }}>
<Link
href={`${explorerUrl}/network-components/mixnodes/`}
target="_blank"
rel="noreferrer"
underline="hover"
color={(theme) => theme.palette.text.primary}
>
<Link href={`${explorerUrl}/network-components/mixnodes/`} target="_blank" rel="noreferrer">
Check the{' '}
<Typography color="primary.main" component="span">
list of mixnodes
@@ -2,7 +2,6 @@ import React, { FC } from 'react';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import {
Box,
Link,
Table,
TableBody,
TableCell,
@@ -17,6 +16,7 @@ import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard';
import { DelegationEvent } from '@nymproject/types';
import { ArrowDropDown } from '@mui/icons-material';
import { visuallyHidden } from '@mui/utils';
import { Link } from '@nymproject/react/link/Link';
type Order = 'asc' | 'desc';
@@ -138,11 +138,8 @@ export const PendingEvents: FC<{ pendingEvents: DelegationEvent[]; explorerUrl:
<Link
target="_blank"
href={`${explorerUrl}/network-components/mixnode/${item.node_identity}`}
color="inherit"
underline="none"
>
{item.node_identity.slice(0, 6)}...{item.node_identity.slice(-6)}
</Link>
text={`${item.node_identity.slice(0, 6)}...${item.node_identity.slice(-6)}`}
/>
</Tooltip>
</TableCell>
<TableCell>{!item.amount ? '-' : `${item.amount?.amount} ${item.amount?.denom}`}</TableCell>
+3
View File
@@ -90,6 +90,9 @@ export const Nav = () => {
<ListItemText
sx={{
color: location.pathname === route ? 'primary.main' : 'text.primary',
'& .MuiListItemText-primary': {
fontWeight: '600',
},
}}
primary={label}
/>
+7 -5
View File
@@ -1,6 +1,6 @@
import React, { useContext, useEffect } from 'react';
import { Alert, Button, Grid, Link, Typography } from '@mui/material';
import { OpenInNew } from '@mui/icons-material';
import { Alert, Grid, Typography } from '@mui/material';
import { Link } from '@nymproject/react/link/Link';
import { NymCard, ClientAddress } from '../../components';
import { AppContext, urls } from '../../context/main';
@@ -33,9 +33,11 @@ export const BalanceCard = () => {
</Grid>
{network && (
<Grid item>
<Link href={`${urls(network).blockExplorer}/account/${clientDetails?.client_address}`} target="_blank">
<Button endIcon={<OpenInNew />}>Last transactions</Button>
</Link>
<Link
href={`${urls(network).blockExplorer}/account/${clientDetails?.client_address}`}
target="_blank"
text="Last transactions"
/>
</Grid>
)}
</Grid>
+7 -4
View File
@@ -1,6 +1,7 @@
import React, { useContext, useState } from 'react';
import { Alert, AlertTitle, Box, Button, Link, Typography } from '@mui/material';
import { Alert, AlertTitle, Box, Button, Typography } from '@mui/material';
import { TransactionExecuteResult } from '@nymproject/types';
import { Link } from '@nymproject/react/link/Link';
import { DelegateForm } from './DelegateForm';
import { NymCard } from '../../components';
import { EnumRequestStatus, RequestStatus } from '../../components/RequestStatus';
@@ -76,9 +77,11 @@ export const Delegate = () => {
</NymCard>
<Typography sx={{ p: 3 }}>
Checkout the{' '}
<Link href={`${urls(network).networkExplorer}/network-components/mixnodes`} target="_blank">
list of mixnodes
</Link>{' '}
<Link
href={`${urls(network).networkExplorer}/network-components/mixnodes`}
target="_blank"
text="list of mixnodes"
/>{' '}
for uptime and performances to help make delegation decisions
</Typography>
</PageLayout>
+4 -8
View File
@@ -1,6 +1,7 @@
import React, { FC, useContext, useEffect, useState } from 'react';
import { Box, Button, Link, Paper, Stack, Typography } from '@mui/material';
import { Box, Button, Paper, Stack, Typography } from '@mui/material';
import { DelegationWithEverything, MajorCurrencyAmount } from '@nymproject/types';
import { Link } from '@nymproject/react/link/Link';
import { AppContext, urls } from 'src/context/main';
import { DelegationList } from 'src/components/Delegation/DelegationList';
import { PendingEvents } from 'src/components/Delegation/PendingEvents';
@@ -273,13 +274,8 @@ export const Delegation: FC = () => {
href={`${urls(network).networkExplorer}/network-components/mixnodes/`}
target="_blank"
rel="noreferrer"
underline="hover"
sx={{ color: 'primary.main', textDecorationColor: 'primary.main' }}
>
<Typography color="primary.main" variant="body2">
Network Explorer
</Typography>
</Link>
text="Network Explorer"
/>
</Box>
<Box display="flex" justifyContent="space-between" alignItems="center">
<RewardsSummary isLoading={isLoading} totalDelegation={totalDelegations} totalRewards={totalRewards} />
@@ -1,6 +1,7 @@
import React, { useContext } from 'react';
import { Box, CircularProgress, Link, Typography } from '@mui/material';
import { Box, CircularProgress, Typography } from '@mui/material';
import { TransactionDetails as TTransactionDetails } from '@nymproject/types';
import { Link } from '@nymproject/react/link/Link';
import { SendError } from './SendError';
import { AppContext, urls } from '../../context/main';
import { SuccessReponse } from '../../components';
@@ -38,9 +39,11 @@ export const SendConfirmation = ({
subtitle={
<>
Check the transaction hash{' '}
<Link href={`${urls(network).blockExplorer}/transactions/${data.tx_hash}`} target="_blank">
here
</Link>
<Link
href={`${urls(network).blockExplorer}/transactions/${data.tx_hash}`}
target="_blank"
text="here"
/>
</>
}
caption={
+7 -5
View File
@@ -1,6 +1,6 @@
import React, { useContext } from 'react';
import { OpenInNew } from '@mui/icons-material';
import { Button, Link, Stack, Typography } from '@mui/material';
import { Stack, Typography } from '@mui/material';
import { Link } from '@nymproject/react/link/Link';
import { urls, AppContext } from '../../context/main';
export const NodeStats = ({ mixnodeId }: { mixnodeId?: string }) => {
@@ -8,9 +8,11 @@ export const NodeStats = ({ mixnodeId }: { mixnodeId?: string }) => {
return (
<Stack spacing={2} sx={{ p: 4 }}>
<Typography>All your node stats are available on the link below</Typography>
<Link href={`${urls(network).networkExplorer}/network-components/mixnode/${mixnodeId}`} target="_blank">
<Button endIcon={<OpenInNew />}>Network Explorer</Button>
</Link>
<Link
href={`${urls(network).networkExplorer}/network-components/mixnode/${mixnodeId}`}
target="_blank"
text="Network Explorer"
/>
</Stack>
);
};
+1
View File
@@ -38,6 +38,7 @@ declare module '@mui/material/styles' {
dark: string;
muted: string;
};
linkHover: string;
}
interface NymPaletteVariant {
+6
View File
@@ -30,6 +30,7 @@ const nymPalette: NymPalette = {
dark: '#121726',
muted: '#7D7D7D',
},
linkHover: '#AF4D36',
};
const darkMode: NymPaletteVariant = {
@@ -235,6 +236,11 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
},
},
},
MuiLink: {
defaultProps: {
underline: 'none',
},
},
},
palette,
};
+3 -1
View File
@@ -13,7 +13,9 @@
"clean": "lerna run clean",
"build": "run-s build:types build:packages",
"build:types": "lerna run --scope @nymproject/types build --stream",
"build:packages": "lerna run --scope @nymproject/mui-theme --scope @nymproject/react --stream build",
"build:packages": "run-s build:packages:theme build:packages:react",
"build:packages:theme": "lerna run --scope @nymproject/mui-theme build",
"build:packages:react": "lerna run --scope @nymproject/react build",
"build:react-example": "lerna run --scope @nymproject/react-webpack-with-theme-example build --stream",
"build:playground": "lerna run --scope @nymproject/react storybook:build --stream",
"build:ci": "yarn build && run-p build:react-example build:playground && yarn build:ci:collect-artifacts",
@@ -18,6 +18,8 @@ export interface NymPalette {
muted: {
onDarkBg: string;
};
linkHover: string;
}
/**
@@ -79,6 +81,8 @@ export const nymPalette: NymPalette = {
muted: {
onDarkBg: '#666B77',
},
linkHover: '#AF4D36',
};
// -------------------------------------------------------------------------------------------------------------------
+5
View File
@@ -126,6 +126,11 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
},
},
},
MuiLink: {
defaultProps: {
underline: 'none',
},
},
},
palette,
};
+6
View File
@@ -50,3 +50,9 @@ This project uses [shared asset files](../../assets/README.md) such as favicons
## Publishing
This package is not published to NPM ... yet.
## TODO
- ugprade to React 18
- upgrade Storybook
- upgrade MUI
@@ -0,0 +1,26 @@
import * as React from 'react';
import { ComponentMeta } from '@storybook/react';
import { Typography } from '@mui/material';
import { Link as LinkIcon } from '@mui/icons-material';
import { Link } from './Link';
export default {
title: 'Basics/Link',
component: Link,
} as ComponentMeta<typeof Link>;
export const Default = () => <Link text="link" href="https://nymtech.net/" target="_blank" />;
export const NoIcon = () => <Link text="link" href="https://nymtech.net/" target="_blank" noIcon />;
export const WithCustomChildren = () => (
<Link href="https://nymtech.net/" target="_blank">
<LinkIcon />
</Link>
);
export const InTextExample = () => (
<Typography>
You can find the Nym website <Link href="https://nymtech.net/" target="_blank" text="here" />.
</Typography>
);
@@ -0,0 +1,42 @@
import * as React from 'react';
import { Box, Typography, Link as MUILink, LinkProps as MUILinkProps } from '@mui/material';
import { OpenInNew } from '@mui/icons-material';
export interface LinkProps {
text?: string;
icon?: React.ReactNode;
noIcon?: boolean;
}
export const Link = (props: MUILinkProps & LinkProps) => {
const { text, icon, underline, noIcon, children } = props;
let typoProps = {};
if (!noIcon) {
typoProps = { mr: 0.5 };
}
return (
<MUILink
{...props}
sx={{
display: 'inline-block',
':hover': {
color: (theme) => theme.palette.nym.linkHover,
},
}}
underline={underline || 'none'}
>
{children || (
<Box
sx={{
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
}}
>
<Typography sx={{ ...typoProps, fontWeight: 400 }}>{text}</Typography>
{!noIcon && (icon || <OpenInNew fontSize="inherit" />)}
</Box>
)}
</MUILink>
);
};