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:
@@ -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>
|
||||
|
||||
@@ -90,6 +90,9 @@ export const Nav = () => {
|
||||
<ListItemText
|
||||
sx={{
|
||||
color: location.pathname === route ? 'primary.main' : 'text.primary',
|
||||
'& .MuiListItemText-primary': {
|
||||
fontWeight: '600',
|
||||
},
|
||||
}}
|
||||
primary={label}
|
||||
/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Vendored
+1
@@ -38,6 +38,7 @@ declare module '@mui/material/styles' {
|
||||
dark: string;
|
||||
muted: string;
|
||||
};
|
||||
linkHover: string;
|
||||
}
|
||||
|
||||
interface NymPaletteVariant {
|
||||
|
||||
@@ -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
@@ -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',
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -126,6 +126,11 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiLink: {
|
||||
defaultProps: {
|
||||
underline: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
palette,
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user