Skip to content

Commit 0a85d27

Browse files
authored
Feat: NFT page redesign (safe-global#1479)
* Prototype: nfts table OpenSea preview Loading Add send batch button Selected items count Rm OpenSea preview Rm Send NFT Rm NFTs loading in the send modal Rm new props in EnhancedTable Batch send Infinite scroll + filter Add icons Selection send form Layout Icon margin Refactor config Add Atomic0 links Add one-time tooltip Mobile CSS Make send form sticky; filter by address Don't stretch previews Adjust font Replace loading spinner with skeletons Hide tooltip if no links Fix children, initial loader, and grid alignement Add tx modal titles Rm "Send NFT" from new tx modal; track Send Restore NFT button, hide it on the NFTs page * Sticky send form * Rm scroll in nft review modal * Don't show empty rows
1 parent bb6fa15 commit 0a85d27

File tree

30 files changed

+697
-434
lines changed

30 files changed

+697
-434
lines changed

public/images/common/arrow-nw.svg

Lines changed: 3 additions & 0 deletions
Loading

public/images/common/nft-atomic0.svg

Lines changed: 4 additions & 0 deletions
Loading

public/images/common/nft-blur.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 6 additions & 0 deletions
Loading

public/images/common/nft-opensea.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

src/components/address-book/AddressBookTable/index.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import EnhancedTable from '@/components/common/EnhancedTable'
21
import { useMemo, useState } from 'react'
2+
import { Box } from '@mui/material'
3+
import EnhancedTable from '@/components/common/EnhancedTable'
34
import type { AddressEntry } from '@/components/address-book/EntryDialog'
45
import EntryDialog from '@/components/address-book/EntryDialog'
56
import ExportDialog from '@/components/address-book/ExportDialog'
@@ -11,7 +12,6 @@ import IconButton from '@mui/material/IconButton'
1112
import Tooltip from '@mui/material/Tooltip'
1213
import RemoveDialog from '@/components/address-book/RemoveDialog'
1314
import useIsGranted from '@/hooks/useIsGranted'
14-
import NewTxModal from '@/components/tx/modals/NewTxModal'
1515
import EthHashInfo from '@/components/common/EthHashInfo'
1616
import AddressBookHeader from '../AddressBookHeader'
1717
import useAddressBook from '@/hooks/useAddressBook'
@@ -21,9 +21,9 @@ import SvgIcon from '@mui/material/SvgIcon'
2121
import PagePlaceholder from '@/components/common/PagePlaceholder'
2222
import NoEntriesIcon from '@/public/images/address-book/no-entries.svg'
2323
import { useCurrentChain } from '@/hooks/useChains'
24-
2524
import tableCss from '@/components/common/EnhancedTable/styles.module.css'
26-
import { Box } from '@mui/material'
25+
import TokenTransferModal from '@/components/tx/modals/TokenTransferModal'
26+
import { SendAssetsField } from '@/components/tx/modals/TokenTransferModal/SendAssetsForm'
2727

2828
const headCells = [
2929
{ id: 'name', label: 'Name' },
@@ -160,7 +160,12 @@ const AddressBookTable = () => {
160160
{open[ModalType.REMOVE] && <RemoveDialog handleClose={handleClose} address={defaultValues?.address || ''} />}
161161

162162
{/* Send funds modal */}
163-
{selectedAddress && <NewTxModal onClose={() => setSelectedAddress(undefined)} recipient={selectedAddress} />}
163+
{selectedAddress && (
164+
<TokenTransferModal
165+
onClose={() => setSelectedAddress(undefined)}
166+
initialData={[{ [SendAssetsField.recipient]: selectedAddress }]}
167+
/>
168+
)}
164169
</>
165170
)
166171
}

src/components/balances/TokenMenu/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const TokenMenu = ({
2525
<Box className={css.stickyBox}>
2626
<Box className={css.hideTokensHeader}>
2727
<VisibilityOffOutlined />
28-
<Typography>
28+
<Typography variant="body2" lineHeight="inherit">
2929
{selectedAssetCount} {selectedAssetCount === 1 ? 'token' : 'tokens'} selected
3030
</Typography>
3131
</Box>

src/components/common/ExternalLink/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ReactElement } from 'react'
12
import { OpenInNewRounded } from '@mui/icons-material'
23
import { Box, Link, type LinkProps } from '@mui/material'
34

@@ -9,7 +10,9 @@ const ExternalLink = ({
910
noIcon = false,
1011
children,
1112
...props
12-
}: Omit<LinkProps, 'target' | 'rel'> & { noIcon?: boolean }) => {
13+
}: Omit<LinkProps, 'target' | 'rel'> & { noIcon?: boolean }): ReactElement => {
14+
if (!props.href) return <>{children}</>
15+
1316
return (
1417
<Link rel="noreferrer noopener" target="_blank" {...props}>
1518
<Box display="inline-flex" alignItems="center" gap={0.2} component="span">

src/components/common/ImageFallback/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
import type { ReactElement } from 'react'
12
import { useState } from 'react'
23

34
type ImageFallbackProps = React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> & {
45
fallbackSrc: string
6+
fallbackComponent?: ReactElement
57
}
68

7-
const ImageFallback = ({ src, fallbackSrc, ...props }: ImageFallbackProps): React.ReactElement => {
9+
const ImageFallback = ({ src, fallbackSrc, fallbackComponent, ...props }: ImageFallbackProps): React.ReactElement => {
810
const [isError, setIsError] = useState<boolean>(false)
911

12+
if (isError && fallbackComponent) return fallbackComponent
13+
1014
return <img {...props} alt={props.alt} src={isError ? fallbackSrc : src} onError={() => setIsError(true)} />
1115
}
1216

src/components/common/OnboardingTooltip/index.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import type { ReactElement } from 'react'
12
import useLocalStorage from '@/services/local-storage/useLocalStorage'
3+
import type { TooltipProps } from '@mui/material'
24
import { Box, Button, SvgIcon, Tooltip } from '@mui/material'
35
import InfoIcon from '@/public/images/notifications/info.svg'
4-
import React from 'react'
56
import { useDarkMode } from '@/hooks/useDarkMode'
67

78
/**
@@ -14,13 +15,15 @@ export const OnboardingTooltip = ({
1415
text,
1516
initiallyShown = true,
1617
className,
18+
placement,
1719
}: {
18-
children: React.ReactElement
20+
children: ReactElement // NB: this has to be an actual HTML element, otherwise the Tooltip will not work
1921
widgetLocalStorageId: string
2022
text: string
2123
initiallyShown?: boolean
2224
className?: string
23-
}): React.ReactElement => {
25+
placement?: TooltipProps['placement']
26+
}): ReactElement => {
2427
const [widgetHidden = !initiallyShown, setWidgetHidden] = useLocalStorage<boolean>(widgetLocalStorageId)
2528
const isDarkMode = useDarkMode()
2629

@@ -32,6 +35,7 @@ export const OnboardingTooltip = ({
3235
className,
3336
}}
3437
open
38+
placement={placement}
3539
arrow
3640
title={
3741
<Box display="flex" alignItems="center" gap={1} padding={1}>

src/components/nfts/NftCard/index.tsx

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/components/nfts/NftCard/styles.module.css

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)