From 28676eeb594bcee19dc01aba9203c286db1d7752 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 15:42:27 +0200 Subject: [PATCH 01/13] Extract shortenEthAddress --- packages/frontend/src/components/bids/BidsListEntry.tsx | 5 ++--- packages/frontend/src/utils/formatters/shortenEthAddress.ts | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 packages/frontend/src/utils/formatters/shortenEthAddress.ts diff --git a/packages/frontend/src/components/bids/BidsListEntry.tsx b/packages/frontend/src/components/bids/BidsListEntry.tsx index 71fe2cad..33731c18 100644 --- a/packages/frontend/src/components/bids/BidsListEntry.tsx +++ b/packages/frontend/src/components/bids/BidsListEntry.tsx @@ -2,8 +2,9 @@ import { AddressColumn, BidColumn, PlaceColumn } from '@/components/bids/BidsCol import styled, { css } from 'styled-components' import { Bid } from '@/types/bid' import { Colors } from '@/styles/colors' -import { formatEther, Hex } from 'viem' +import { formatEther } from 'viem' import { useExplorerAddressLink } from '@/blockchain/hooks/useExplorerAddressLink' +import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; interface Props { bid: Bid @@ -29,8 +30,6 @@ export const BidsListEntry = ({ bid, isUser, view = 'full' }: Props) => { ) } -const shortenEthAddress = (address: Hex) => `${address.substring(0, 6)}......${address.substring(address.length - 4)}` - const BidsEntryRow = styled.div<{ isUser?: boolean }>` display: grid; grid-template-columns: 1fr 1fr 2fr; diff --git a/packages/frontend/src/utils/formatters/shortenEthAddress.ts b/packages/frontend/src/utils/formatters/shortenEthAddress.ts new file mode 100644 index 00000000..e403716b --- /dev/null +++ b/packages/frontend/src/utils/formatters/shortenEthAddress.ts @@ -0,0 +1,3 @@ +import { Hex } from "viem"; + +export const shortenEthAddress = (address: Hex) => `${address.substring(0, 6)}......${address.substring(address.length - 4)}` From 19c305ab9dc3ebaa4ba88c1af8d6fb7da951eeaa Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 15:43:48 +0200 Subject: [PATCH 02/13] Add tooltip --- packages/frontend/package.json | 2 + .../src/components/tooltip/Tooltip.tsx | 48 +++ .../src/components/tooltip/TooltipButton.tsx | 35 ++ .../src/components/tooltip/TooltipLink.tsx | 37 ++ pnpm-lock.yaml | 405 ++++++++++++++++++ 5 files changed, 527 insertions(+) create mode 100644 packages/frontend/src/components/tooltip/Tooltip.tsx create mode 100644 packages/frontend/src/components/tooltip/TooltipButton.tsx create mode 100644 packages/frontend/src/components/tooltip/TooltipLink.tsx diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 9110b34f..614bc21b 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -15,7 +15,9 @@ }, "dependencies": { "@radix-ui/react-accordion": "^1.1.2", + "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-separator": "^1.0.3", + "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/react-query": "^5.28.9", "@web3modal/wagmi": "^4.1.9", "moment": "^2.29.1", diff --git a/packages/frontend/src/components/tooltip/Tooltip.tsx b/packages/frontend/src/components/tooltip/Tooltip.tsx new file mode 100644 index 00000000..f6080895 --- /dev/null +++ b/packages/frontend/src/components/tooltip/Tooltip.tsx @@ -0,0 +1,48 @@ +import * as TooltipPrimitive from '@radix-ui/react-tooltip' +import { ReactNode } from 'react' +import styled from 'styled-components' +import { Colors } from "@/styles/colors"; + +interface TooltipProps { + side?: 'top' | 'right' | 'bottom' | 'left' + tooltip: ReactNode + children: ReactNode + onOpenChange?: (open: boolean) => void +} + +export const Tooltip = ({ side = 'bottom', tooltip, children, onOpenChange }: TooltipProps) => { + return ( + + e.preventDefault()}> + {children} + + + {tooltip} + + + + ) +} + +const TooltipTriggerContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: fit-content; + height: fit-content; + cursor: help; +` + +const TooltipContent = styled(TooltipPrimitive.Content)` + display: flex; + flex-direction: column; + width: fit-content; + padding: 8px 42px; + background-color: ${Colors.Black}; + font-size: 12px; + line-height: 14px; + color: ${Colors.White}; +` +const Arrow = styled(TooltipPrimitive.Arrow)` + fill: ${Colors.Black}; +` diff --git a/packages/frontend/src/components/tooltip/TooltipButton.tsx b/packages/frontend/src/components/tooltip/TooltipButton.tsx new file mode 100644 index 00000000..7d02197e --- /dev/null +++ b/packages/frontend/src/components/tooltip/TooltipButton.tsx @@ -0,0 +1,35 @@ +import { ReactNode, MouseEvent } from 'react' +import styled from 'styled-components' +import { Colors } from "@/styles/colors"; +import { Button } from "@/components/buttons"; + +interface TooltipButtonProps { + color?: string + label?: string + children?: ReactNode + onClick?: (event?: MouseEvent) => void + onMouseDown?: (event?: MouseEvent) => void +} + +export const TooltipButton = ({ color = Colors.Grey, label, children, ...props }: TooltipButtonProps) => { + return ( + + {children} + + ) +} + +const TooltipButtonComponent = styled(Button)>` + color: ${({ color }) => color}; + background-color: ${Colors.White}; + width: max-content; + height: 100%; + padding: ${({ label }) => (label ? '4px 12px 4px 4px' : '0')}; + transition: all 0.25s ease; + + &:hover, + &:focus-visible { + color: ${Colors.BlueDark}; + background-color: ${Colors.GreenLight}; + } +` diff --git a/packages/frontend/src/components/tooltip/TooltipLink.tsx b/packages/frontend/src/components/tooltip/TooltipLink.tsx new file mode 100644 index 00000000..265f983e --- /dev/null +++ b/packages/frontend/src/components/tooltip/TooltipLink.tsx @@ -0,0 +1,37 @@ +import { ReactNode } from 'react' +import styled from 'styled-components' +import { Colors } from "@/styles/colors"; + +interface TooltipLinkProps { + color?: string + children?: ReactNode + href: string + label?: string +} + +export const TooltipLink = ({ color = Colors.Grey, href, children, label }: TooltipLinkProps) => { + return ( + + {children} + + ) +} + +const TooltipLinkComponent = styled.a>` + display: flex; + align-items: center; + width: max-content; + padding: ${({ label }) => (label ? '4px 12px 4px 4px' : '0')}; + background-color: transparent; + color: ${({ color }) => color}; + outline: none; + user-select: none; + text-decoration: none; + transition: all 0.25s ease; + + &:hover, + &:focus-visible { + color: ${Colors.BlueDark}; + background-color: ${Colors.GreenLight}; + } +` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c41e3e4b..31c26000 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,9 +116,15 @@ importers: '@radix-ui/react-accordion': specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-dialog': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-separator': specifier: ^1.0.3 version: 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-tooltip': + specifier: ^1.0.7 + version: 1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-query': specifier: ^5.28.9 version: 5.29.2(react@18.2.0) @@ -950,6 +956,34 @@ packages: engines: {node: '>=14'} dev: true + /@floating-ui/core@1.6.0: + resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/dom@1.6.3: + resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + /@gnosis.pm/safe-core-sdk-types@0.1.1: resolution: {integrity: sha512-PghXGDaI5Foq37nZGmI90U2OKMeGtxh5KqkDqou9aFHwGVa/nf9HRQPxG9/XUzcyfe9OlKttDlJnR3XnC3dSDw==} deprecated: Package no longer supported. It has been migrated to @safe-global/safe-core-sdk-types. Please, update your dependencies. @@ -1950,6 +1984,27 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} peerDependencies: @@ -2030,6 +2085,40 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + aria-hidden: 1.2.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.74)(react@18.2.0) + dev: false + /@radix-ui/react-direction@1.0.1(@types/react@18.2.74)(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: @@ -2044,6 +2133,68 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@types/react': 18.2.74 + react: 18.2.0 + dev: false + + /@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-id@1.0.1(@types/react@18.2.74)(react@18.2.0): resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} peerDependencies: @@ -2059,6 +2210,57 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} peerDependencies: @@ -2138,6 +2340,38 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.74)(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -2167,6 +2401,21 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + react: 18.2.0 + dev: false + /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.74)(react@18.2.0): resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} peerDependencies: @@ -2181,6 +2430,63 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-rect@1.0.1(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.74 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-size@1.0.1(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + react: 18.2.0 + dev: false + + /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/rect@1.0.1: + resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} + dependencies: + '@babel/runtime': 7.24.4 + dev: false + /@react-native-async-storage/async-storage@1.23.1: resolution: {integrity: sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==} peerDependencies: @@ -3999,6 +4305,13 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /aria-hidden@1.2.4: + resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} + engines: {node: '>=10'} + dependencies: + tslib: 2.6.2 + dev: false + /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} dependencies: @@ -6190,6 +6503,10 @@ packages: hasBin: true dev: false + /detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + dev: false + /diff@3.5.0: resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} engines: {node: '>=0.3.1'} @@ -8310,6 +8627,11 @@ packages: has-symbols: 1.0.3 hasown: 2.0.2 + /get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + dev: false + /get-port-please@3.1.2: resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} dev: false @@ -12145,6 +12467,58 @@ packages: react: 18.2.0 dev: false + /react-remove-scroll-bar@2.3.6(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.74 + react: 18.2.0 + react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.2.0) + tslib: 2.6.2 + dev: false + + /react-remove-scroll@2.5.5(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.74 + react: 18.2.0 + react-remove-scroll-bar: 2.3.6(@types/react@18.2.74)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.2.0) + tslib: 2.6.2 + use-callback-ref: 1.3.2(@types/react@18.2.74)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.74)(react@18.2.0) + dev: false + + /react-style-singleton@2.2.1(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.74 + get-nonce: 1.0.1 + invariant: 2.2.4 + react: 18.2.0 + tslib: 2.6.2 + dev: false + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -14303,6 +14677,37 @@ packages: querystring: 0.2.0 dev: true + /use-callback-ref@1.3.2(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.74 + react: 18.2.0 + tslib: 2.6.2 + dev: false + + /use-sidecar@1.1.2(@types/react@18.2.74)(react@18.2.0): + resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.74 + detect-node-es: 1.1.0 + react: 18.2.0 + tslib: 2.6.2 + dev: false + /use-sync-external-store@1.2.0(react@18.2.0): resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: From e42c823132ad4b988d21292d47e230699b32360a Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 15:51:18 +0200 Subject: [PATCH 03/13] Add CopyButton --- packages/frontend/package.json | 1 + .../src/components/buttons/CopyButton.tsx | 42 +++++++++++++++++++ pnpm-lock.yaml | 13 ++++++ 3 files changed, 56 insertions(+) create mode 100644 packages/frontend/src/components/buttons/CopyButton.tsx diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 614bc21b..bf61ee80 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -20,6 +20,7 @@ "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/react-query": "^5.28.9", "@web3modal/wagmi": "^4.1.9", + "copy-to-clipboard": "^3.3.3", "moment": "^2.29.1", "moment-timezone": "^0.5.34", "next": "14.1.4", diff --git a/packages/frontend/src/components/buttons/CopyButton.tsx b/packages/frontend/src/components/buttons/CopyButton.tsx new file mode 100644 index 00000000..69a899d3 --- /dev/null +++ b/packages/frontend/src/components/buttons/CopyButton.tsx @@ -0,0 +1,42 @@ +import { ReactNode, useState } from 'react' +import copyToClipboard from 'copy-to-clipboard' +import styled from 'styled-components' +import { CopyIcon } from "@/components/icons"; +import { Tooltip, TooltipButton } from "@/components/tooltip"; + +interface CopyButtonProps { + value: string + text?: ReactNode + side?: 'top' | 'right' | 'bottom' | 'left' + size?: number + color?: string + label?: string +} + +export const CopyButton = ({ value, text, side, size, color, label }: CopyButtonProps) => { + const [tooltipText, setTooltipText] = useState(text) + const copy = () => { + copyToClipboard(value) + setTooltipText('Copied!') + } + + return ( + !value && setTooltipText(text)}> + + + {label && ( + + {label} + + )} + + + ) +} + +const CopyButtonLabel = styled.span>` + font-weight: 400; + font-size: 14px; + line-height: ${({ size }) => size}; + color: ${({ color }) => color}; +` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31c26000..418a61b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -131,6 +131,9 @@ importers: '@web3modal/wagmi': specifier: ^4.1.9 version: 4.1.9(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)(viem@2.9.16) + copy-to-clipboard: + specifier: ^3.3.3 + version: 3.3.3 moment: specifier: ^2.29.1 version: 2.30.1 @@ -6010,6 +6013,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + /core-js-pure@3.21.1: resolution: {integrity: sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==} deprecated: core-js-pure@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js-pure. @@ -14131,6 +14140,10 @@ packages: safe-regex: 1.1.0 dev: true + /toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} From 35174e53ea51a08c64b4ffa743e5616628ac42aa Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 15:52:22 +0200 Subject: [PATCH 04/13] Add RedirectButton --- .../src/components/buttons/RedirectButton.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 packages/frontend/src/components/buttons/RedirectButton.tsx diff --git a/packages/frontend/src/components/buttons/RedirectButton.tsx b/packages/frontend/src/components/buttons/RedirectButton.tsx new file mode 100644 index 00000000..a5f18df4 --- /dev/null +++ b/packages/frontend/src/components/buttons/RedirectButton.tsx @@ -0,0 +1,31 @@ +import { ReactNode } from 'react' +import styled from 'styled-components' +import { Tooltip, TooltipLink } from "@/components/tooltip"; +import { RedirectIcon } from "@/components/icons"; + +interface RedirectTooltipProps { + link: string + tooltip: string | ReactNode + side?: 'top' | 'right' | 'bottom' | 'left' + size?: number + color?: string + label?: string +} + +export const RedirectButton = ({ link, tooltip, side, size, color, label }: RedirectTooltipProps) => { + return ( + + + + {label && {label}} + + + ) +} + +const RedirectButtonLabel = styled.span>` + font-weight: 400; + font-size: 14px; + line-height: ${({ size }) => size}; + color: ${({ color }) => color}; +` From be11c5fb28886e41429a479b12126ef1c45cd828 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 15:53:57 +0200 Subject: [PATCH 05/13] Allow for passing undefined address in useExplorerAddressLink --- .../frontend/src/blockchain/hooks/useExplorerAddressLink.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/blockchain/hooks/useExplorerAddressLink.ts b/packages/frontend/src/blockchain/hooks/useExplorerAddressLink.ts index cbde45e2..7746971d 100644 --- a/packages/frontend/src/blockchain/hooks/useExplorerAddressLink.ts +++ b/packages/frontend/src/blockchain/hooks/useExplorerAddressLink.ts @@ -1,12 +1,12 @@ import { Hex } from 'viem' import { useChainId, useChains } from 'wagmi' -export const useExplorerAddressLink = (address: Hex): string | undefined => { +export const useExplorerAddressLink = (address: Hex | undefined): string | undefined => { const chains = useChains() const chainId = useChainId() const currentChain = chains.find((chain) => chain.id === chainId) - if (!currentChain || !currentChain.blockExplorers?.default) { + if (!currentChain || !currentChain.blockExplorers?.default || !address) { return undefined } return `${currentChain.blockExplorers.default.url}/address/${address}` From f9e922fec06a3aca08beebe65070b2472eb492ef Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:31:50 +0200 Subject: [PATCH 06/13] Add modal --- .../frontend/src/components/topBar/Modal.tsx | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 packages/frontend/src/components/topBar/Modal.tsx diff --git a/packages/frontend/src/components/topBar/Modal.tsx b/packages/frontend/src/components/topBar/Modal.tsx new file mode 100644 index 00000000..ba005808 --- /dev/null +++ b/packages/frontend/src/components/topBar/Modal.tsx @@ -0,0 +1,70 @@ +import * as Dialog from '@radix-ui/react-dialog' +import { ReactNode, useCallback } from 'react' +import styled from 'styled-components' +import { CloseButton } from "@/components/buttons/CloseButton"; +import { Colors, hexOpacity } from "@/styles/colors"; + +export interface ModalProps { + isShown: boolean | undefined + onRequestClose: () => void + title?: string + children: ReactNode +} + +export const Modal = ({ isShown, onRequestClose, title, children }: ModalProps) => { + const closeModal = useCallback(() => isShown && onRequestClose(), [isShown, onRequestClose]) + + return ( + + + + +
+ {title} + +
+ {children} +
+
+
+
+ ) +} + +const Overlay = styled(Dialog.Overlay)` + background-color: ${hexOpacity(Colors.Blue, 0.8)}; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: grid; + place-items: center; + z-index: 100; +` + +const Content = styled(Dialog.Content)` + display: flex; + flex-direction: column; + align-items: center; + row-gap: 24px; + width: 408px; + padding: 24px; + background-color: ${Colors.White}; +` + +const Header = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + overflow: hidden; +` + +const Title = styled(Dialog.Title)` + font-family: 'Space Mono', 'Roboto Mono', monospace; + font-weight: 700; + font-size: 16px; + line-height: 24px; + color: ${Colors.Black}; +` From c9ad105608ad2b1b4ce59e1fb7830927e6ff15a2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:32:05 +0200 Subject: [PATCH 07/13] USe tooltip provider in tooltip --- .../src/components/tooltip/Tooltip.tsx | 20 ++++++++++--------- .../frontend/src/components/tooltip/index.ts | 3 +++ 2 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 packages/frontend/src/components/tooltip/index.ts diff --git a/packages/frontend/src/components/tooltip/Tooltip.tsx b/packages/frontend/src/components/tooltip/Tooltip.tsx index f6080895..d4e0de0b 100644 --- a/packages/frontend/src/components/tooltip/Tooltip.tsx +++ b/packages/frontend/src/components/tooltip/Tooltip.tsx @@ -12,15 +12,17 @@ interface TooltipProps { export const Tooltip = ({ side = 'bottom', tooltip, children, onOpenChange }: TooltipProps) => { return ( - - e.preventDefault()}> - {children} - - - {tooltip} - - - + + + e.preventDefault()}> + {children} + + + {tooltip} + + + + ) } diff --git a/packages/frontend/src/components/tooltip/index.ts b/packages/frontend/src/components/tooltip/index.ts new file mode 100644 index 00000000..c699fcc5 --- /dev/null +++ b/packages/frontend/src/components/tooltip/index.ts @@ -0,0 +1,3 @@ +export * from './Tooltip' +export * from './TooltipButton' +export * from './TooltipLink' From 9dd276ba88b45d25b299bf4c60394f93ad750e80 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:32:22 +0200 Subject: [PATCH 08/13] Add AccountButton --- .../src/components/topBar/AccountButton.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/frontend/src/components/topBar/AccountButton.tsx diff --git a/packages/frontend/src/components/topBar/AccountButton.tsx b/packages/frontend/src/components/topBar/AccountButton.tsx new file mode 100644 index 00000000..e7ecec99 --- /dev/null +++ b/packages/frontend/src/components/topBar/AccountButton.tsx @@ -0,0 +1,25 @@ +import { useAccount } from "wagmi"; +import { useState } from "react"; +import { Button } from "@/components/buttons/Button"; +import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; +import { ConnectWalletButton } from "@/components/buttons/ConnectWalletButton"; +import { AccountDetailModal } from "@/components/topBar/AccountDetailModal"; + +export const AccountButton = () => { + const { address } = useAccount() + const [isModalOpen, setIsModalOpen] = useState(false) + + return ( + <> + {address ? ( + + ) : ( + + )} + {address && isModalOpen && + setIsModalOpen(false)}/>} + + ) +} From ccb5a8fdaf0f6dbd7b072f7bd541a3858dc4b4bd Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:32:36 +0200 Subject: [PATCH 09/13] Add AccountDetailModal --- .../components/topBar/AccountDetailModal.tsx | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 packages/frontend/src/components/topBar/AccountDetailModal.tsx diff --git a/packages/frontend/src/components/topBar/AccountDetailModal.tsx b/packages/frontend/src/components/topBar/AccountDetailModal.tsx new file mode 100644 index 00000000..5d62ab03 --- /dev/null +++ b/packages/frontend/src/components/topBar/AccountDetailModal.tsx @@ -0,0 +1,122 @@ +import { useRef, useState } from 'react' +import styled from 'styled-components' +import { useWeb3Modal } from "@web3modal/wagmi/react"; +import { useAccount, useChainId, useDisconnect } from "wagmi"; +import { Colors } from "@/styles/colors"; +import { Button } from "@/components/buttons"; +import { Modal } from "@/components/topBar/Modal"; +import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; +import { CopyButton } from "@/components/buttons/CopyButton"; +import { RedirectButton } from "@/components/buttons/RedirectButton"; +import { useExplorerAddressLink } from "@/blockchain/hooks/useExplorerAddressLink"; + +export interface ModalProps { + isShown: boolean | undefined + onRequestClose: () => void +} + +export const AccountDetailModal = ({ isShown, onRequestClose }: ModalProps) => { + const {open, close} = useWeb3Modal() + const { connector, address } = useAccount() + const accountIconRef = useRef(null) + const chainId = useChainId() + const [wallet, setWallet] = useState('-') + const explorerLink = useExplorerAddressLink(address) + const {disconnect} = useDisconnect() + // const { isBraveWallet } = useWhichWallet() + + // useEffect(() => { + // setWallet(getWalletName(web3Modal.cachedProvider, isBraveWallet)) + // if (account && accountIconRef.current) { + // accountIconRef.current.innerHTML = '' + // accountIconRef.current.appendChild(Jazzicon(40, parseInt(account.slice(2, 10), 16))) + // } + // // eslint-disable-next-line react-hooks/exhaustive-deps + // }, [account]) + // + // const onDisconnect = useCallback(() => { + // onRequestClose() + // localStorage.removeItem('walletconnect') + // removeWalletLinkStorage() + // web3Modal.clearCachedProvider() + // deactivate() + // }, [onRequestClose, deactivate, web3Modal]) + + return ( + + + + Connected with {wallet} + + {address && ( + <> + + + {shortenEthAddress(address)} + + + + + + + + )} + + + + ) +} + +const AccountIcon = styled.div` + display: flex; + place-items: center; + height: 40px; + width: 40px; + background-color: ${Colors.Blue}; + border-radius: 50%; +` + +const AccountAddress = styled.p` + font-family: 'Space Mono', 'Roboto Mono', monospace; + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: ${Colors.Black}; +` + +const ConnectedWallet = styled.p` + font-weight: 400; + font-size: 14px; + line-height: 32px; + color: ${Colors.Grey}; +` + +const ContentRow = styled.div` + display: flex; + justify-content: center; + align-items: center; + column-gap: 16px; +` + +const ContentWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + row-gap: 20px; + padding: 20px; + border: 1px solid #e7eaf3; +` From d04e4744af9f995f95f8d164738b33abe79f4fdf Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:32:47 +0200 Subject: [PATCH 10/13] Add TopBar as layout --- .../frontend/src/components/topBar/TopBar.tsx | 30 +++++++++++++++++++ packages/frontend/src/pages/_app.tsx | 15 ++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 packages/frontend/src/components/topBar/TopBar.tsx diff --git a/packages/frontend/src/components/topBar/TopBar.tsx b/packages/frontend/src/components/topBar/TopBar.tsx new file mode 100644 index 00000000..2e43a1b6 --- /dev/null +++ b/packages/frontend/src/components/topBar/TopBar.tsx @@ -0,0 +1,30 @@ +import styled from 'styled-components' +import { Logo } from "@/components/icons"; +import { Colors } from "@/styles/colors"; +import { AccountButton } from "@/components/topBar/AccountButton"; + +export const TopBar = () => { + return ( + + + + + + + ) +} + +const TopBarContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 8px 68px; + background-color: ${Colors.White}; + position: sticky; + top: 0; + z-index: 99; +` +const HomeLink = styled.a` + line-height: 1; +` diff --git a/packages/frontend/src/pages/_app.tsx b/packages/frontend/src/pages/_app.tsx index cc412c0b..196534c2 100644 --- a/packages/frontend/src/pages/_app.tsx +++ b/packages/frontend/src/pages/_app.tsx @@ -2,14 +2,25 @@ import { GlobalStyles } from '@/styles/GobalStyles' import type { AppProps } from 'next/app' import { BlockchainProviders } from '@/providers/wagmi' import { BidsProvider } from '@/providers/BidsProvider/provider' +import { ReactNode } from "react"; +import { TopBar } from "@/components/topBar/TopBar"; export default function App({ Component, pageProps }: AppProps) { return ( - - + + + + ) } + +const Layout = ({ children }: { children: ReactNode }) => ( + <> + +
{children}
+ +) From 520a5d1302aed91a618a23c33bae3cd58adfc9e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:52:44 +0200 Subject: [PATCH 11/13] Adjust AccountDetailModal to wagmi hooks --- .../components/topBar/AccountDetailModal.tsx | 54 +++++-------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/packages/frontend/src/components/topBar/AccountDetailModal.tsx b/packages/frontend/src/components/topBar/AccountDetailModal.tsx index 5d62ab03..24bc306f 100644 --- a/packages/frontend/src/components/topBar/AccountDetailModal.tsx +++ b/packages/frontend/src/components/topBar/AccountDetailModal.tsx @@ -1,7 +1,5 @@ -import { useRef, useState } from 'react' import styled from 'styled-components' -import { useWeb3Modal } from "@web3modal/wagmi/react"; -import { useAccount, useChainId, useDisconnect } from "wagmi"; +import { useAccount, useDisconnect } from "wagmi"; import { Colors } from "@/styles/colors"; import { Button } from "@/components/buttons"; import { Modal } from "@/components/topBar/Modal"; @@ -16,44 +14,26 @@ export interface ModalProps { } export const AccountDetailModal = ({ isShown, onRequestClose }: ModalProps) => { - const {open, close} = useWeb3Modal() const { connector, address } = useAccount() - const accountIconRef = useRef(null) - const chainId = useChainId() - const [wallet, setWallet] = useState('-') const explorerLink = useExplorerAddressLink(address) - const {disconnect} = useDisconnect() - // const { isBraveWallet } = useWhichWallet() + const { disconnectAsync } = useDisconnect() - // useEffect(() => { - // setWallet(getWalletName(web3Modal.cachedProvider, isBraveWallet)) - // if (account && accountIconRef.current) { - // accountIconRef.current.innerHTML = '' - // accountIconRef.current.appendChild(Jazzicon(40, parseInt(account.slice(2, 10), 16))) - // } - // // eslint-disable-next-line react-hooks/exhaustive-deps - // }, [account]) - // - // const onDisconnect = useCallback(() => { - // onRequestClose() - // localStorage.removeItem('walletconnect') - // removeWalletLinkStorage() - // web3Modal.clearCachedProvider() - // deactivate() - // }, [onRequestClose, deactivate, web3Modal]) + const onDisconnect = async () => { + await disconnectAsync() + onRequestClose() + } return ( - Connected with {wallet} + Connected with {connector?.name} {address && ( <> - - + {shortenEthAddress(address)} - + { label=" View in block explorer" side="top" /> - { )} - ) } -const AccountIcon = styled.div` - display: flex; - place-items: center; - height: 40px; - width: 40px; - background-color: ${Colors.Blue}; - border-radius: 50%; -` - const AccountAddress = styled.p` font-family: 'Space Mono', 'Roboto Mono', monospace; font-weight: 400; @@ -112,6 +82,10 @@ const ContentRow = styled.div` column-gap: 16px; ` +const CenteredContentRow = styled(ContentRow)` + width: 100%; +` + const ContentWrapper = styled.div` display: flex; flex-direction: column; From 6cb4fc83001f306f43adf6935085eb953017d3f4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:53:12 +0200 Subject: [PATCH 12/13] Lint --- .../src/components/bids/BidsListEntry.tsx | 2 +- .../src/components/buttons/CopyButton.tsx | 4 ++-- .../src/components/buttons/RedirectButton.tsx | 4 ++-- .../src/components/tooltip/Tooltip.tsx | 4 ++-- .../src/components/tooltip/TooltipButton.tsx | 4 ++-- .../src/components/tooltip/TooltipLink.tsx | 2 +- .../src/components/topBar/AccountButton.tsx | 19 ++++++++++--------- .../components/topBar/AccountDetailModal.tsx | 16 ++++++++-------- .../frontend/src/components/topBar/Modal.tsx | 4 ++-- .../frontend/src/components/topBar/TopBar.tsx | 6 +++--- packages/frontend/src/pages/_app.tsx | 8 ++++---- .../src/utils/formatters/shortenEthAddress.ts | 5 +++-- 12 files changed, 40 insertions(+), 38 deletions(-) diff --git a/packages/frontend/src/components/bids/BidsListEntry.tsx b/packages/frontend/src/components/bids/BidsListEntry.tsx index 33731c18..0a74b893 100644 --- a/packages/frontend/src/components/bids/BidsListEntry.tsx +++ b/packages/frontend/src/components/bids/BidsListEntry.tsx @@ -4,7 +4,7 @@ import { Bid } from '@/types/bid' import { Colors } from '@/styles/colors' import { formatEther } from 'viem' import { useExplorerAddressLink } from '@/blockchain/hooks/useExplorerAddressLink' -import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; +import { shortenEthAddress } from '@/utils/formatters/shortenEthAddress' interface Props { bid: Bid diff --git a/packages/frontend/src/components/buttons/CopyButton.tsx b/packages/frontend/src/components/buttons/CopyButton.tsx index 69a899d3..79d2c6d2 100644 --- a/packages/frontend/src/components/buttons/CopyButton.tsx +++ b/packages/frontend/src/components/buttons/CopyButton.tsx @@ -1,8 +1,8 @@ import { ReactNode, useState } from 'react' import copyToClipboard from 'copy-to-clipboard' import styled from 'styled-components' -import { CopyIcon } from "@/components/icons"; -import { Tooltip, TooltipButton } from "@/components/tooltip"; +import { CopyIcon } from '@/components/icons' +import { Tooltip, TooltipButton } from '@/components/tooltip' interface CopyButtonProps { value: string diff --git a/packages/frontend/src/components/buttons/RedirectButton.tsx b/packages/frontend/src/components/buttons/RedirectButton.tsx index a5f18df4..d06f9588 100644 --- a/packages/frontend/src/components/buttons/RedirectButton.tsx +++ b/packages/frontend/src/components/buttons/RedirectButton.tsx @@ -1,7 +1,7 @@ import { ReactNode } from 'react' import styled from 'styled-components' -import { Tooltip, TooltipLink } from "@/components/tooltip"; -import { RedirectIcon } from "@/components/icons"; +import { Tooltip, TooltipLink } from '@/components/tooltip' +import { RedirectIcon } from '@/components/icons' interface RedirectTooltipProps { link: string diff --git a/packages/frontend/src/components/tooltip/Tooltip.tsx b/packages/frontend/src/components/tooltip/Tooltip.tsx index d4e0de0b..69940085 100644 --- a/packages/frontend/src/components/tooltip/Tooltip.tsx +++ b/packages/frontend/src/components/tooltip/Tooltip.tsx @@ -1,7 +1,7 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip' import { ReactNode } from 'react' import styled from 'styled-components' -import { Colors } from "@/styles/colors"; +import { Colors } from '@/styles/colors' interface TooltipProps { side?: 'top' | 'right' | 'bottom' | 'left' @@ -19,7 +19,7 @@ export const Tooltip = ({ side = 'bottom', tooltip, children, onOpenChange }: To {tooltip} - + diff --git a/packages/frontend/src/components/tooltip/TooltipButton.tsx b/packages/frontend/src/components/tooltip/TooltipButton.tsx index 7d02197e..be46c4b3 100644 --- a/packages/frontend/src/components/tooltip/TooltipButton.tsx +++ b/packages/frontend/src/components/tooltip/TooltipButton.tsx @@ -1,7 +1,7 @@ import { ReactNode, MouseEvent } from 'react' import styled from 'styled-components' -import { Colors } from "@/styles/colors"; -import { Button } from "@/components/buttons"; +import { Colors } from '@/styles/colors' +import { Button } from '@/components/buttons' interface TooltipButtonProps { color?: string diff --git a/packages/frontend/src/components/tooltip/TooltipLink.tsx b/packages/frontend/src/components/tooltip/TooltipLink.tsx index 265f983e..d7b73a3f 100644 --- a/packages/frontend/src/components/tooltip/TooltipLink.tsx +++ b/packages/frontend/src/components/tooltip/TooltipLink.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react' import styled from 'styled-components' -import { Colors } from "@/styles/colors"; +import { Colors } from '@/styles/colors' interface TooltipLinkProps { color?: string diff --git a/packages/frontend/src/components/topBar/AccountButton.tsx b/packages/frontend/src/components/topBar/AccountButton.tsx index e7ecec99..9d13fa3e 100644 --- a/packages/frontend/src/components/topBar/AccountButton.tsx +++ b/packages/frontend/src/components/topBar/AccountButton.tsx @@ -1,9 +1,9 @@ -import { useAccount } from "wagmi"; -import { useState } from "react"; -import { Button } from "@/components/buttons/Button"; -import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; -import { ConnectWalletButton } from "@/components/buttons/ConnectWalletButton"; -import { AccountDetailModal } from "@/components/topBar/AccountDetailModal"; +import { useAccount } from 'wagmi' +import { useState } from 'react' +import { Button } from '@/components/buttons/Button' +import { shortenEthAddress } from '@/utils/formatters/shortenEthAddress' +import { ConnectWalletButton } from '@/components/buttons/ConnectWalletButton' +import { AccountDetailModal } from '@/components/topBar/AccountDetailModal' export const AccountButton = () => { const { address } = useAccount() @@ -16,10 +16,11 @@ export const AccountButton = () => { {shortenEthAddress(address)} ) : ( - + + )} + {address && isModalOpen && ( + setIsModalOpen(false)} /> )} - {address && isModalOpen && - setIsModalOpen(false)}/>} ) } diff --git a/packages/frontend/src/components/topBar/AccountDetailModal.tsx b/packages/frontend/src/components/topBar/AccountDetailModal.tsx index 24bc306f..1e72820a 100644 --- a/packages/frontend/src/components/topBar/AccountDetailModal.tsx +++ b/packages/frontend/src/components/topBar/AccountDetailModal.tsx @@ -1,12 +1,12 @@ import styled from 'styled-components' -import { useAccount, useDisconnect } from "wagmi"; -import { Colors } from "@/styles/colors"; -import { Button } from "@/components/buttons"; -import { Modal } from "@/components/topBar/Modal"; -import { shortenEthAddress } from "@/utils/formatters/shortenEthAddress"; -import { CopyButton } from "@/components/buttons/CopyButton"; -import { RedirectButton } from "@/components/buttons/RedirectButton"; -import { useExplorerAddressLink } from "@/blockchain/hooks/useExplorerAddressLink"; +import { useAccount, useDisconnect } from 'wagmi' +import { Colors } from '@/styles/colors' +import { Button } from '@/components/buttons' +import { Modal } from '@/components/topBar/Modal' +import { shortenEthAddress } from '@/utils/formatters/shortenEthAddress' +import { CopyButton } from '@/components/buttons/CopyButton' +import { RedirectButton } from '@/components/buttons/RedirectButton' +import { useExplorerAddressLink } from '@/blockchain/hooks/useExplorerAddressLink' export interface ModalProps { isShown: boolean | undefined diff --git a/packages/frontend/src/components/topBar/Modal.tsx b/packages/frontend/src/components/topBar/Modal.tsx index ba005808..8a4827aa 100644 --- a/packages/frontend/src/components/topBar/Modal.tsx +++ b/packages/frontend/src/components/topBar/Modal.tsx @@ -1,8 +1,8 @@ import * as Dialog from '@radix-ui/react-dialog' import { ReactNode, useCallback } from 'react' import styled from 'styled-components' -import { CloseButton } from "@/components/buttons/CloseButton"; -import { Colors, hexOpacity } from "@/styles/colors"; +import { CloseButton } from '@/components/buttons/CloseButton' +import { Colors, hexOpacity } from '@/styles/colors' export interface ModalProps { isShown: boolean | undefined diff --git a/packages/frontend/src/components/topBar/TopBar.tsx b/packages/frontend/src/components/topBar/TopBar.tsx index 2e43a1b6..72d44ba5 100644 --- a/packages/frontend/src/components/topBar/TopBar.tsx +++ b/packages/frontend/src/components/topBar/TopBar.tsx @@ -1,7 +1,7 @@ import styled from 'styled-components' -import { Logo } from "@/components/icons"; -import { Colors } from "@/styles/colors"; -import { AccountButton } from "@/components/topBar/AccountButton"; +import { Logo } from '@/components/icons' +import { Colors } from '@/styles/colors' +import { AccountButton } from '@/components/topBar/AccountButton' export const TopBar = () => { return ( diff --git a/packages/frontend/src/pages/_app.tsx b/packages/frontend/src/pages/_app.tsx index 196534c2..8543e67c 100644 --- a/packages/frontend/src/pages/_app.tsx +++ b/packages/frontend/src/pages/_app.tsx @@ -2,14 +2,14 @@ import { GlobalStyles } from '@/styles/GobalStyles' import type { AppProps } from 'next/app' import { BlockchainProviders } from '@/providers/wagmi' import { BidsProvider } from '@/providers/BidsProvider/provider' -import { ReactNode } from "react"; -import { TopBar } from "@/components/topBar/TopBar"; +import { ReactNode } from 'react' +import { TopBar } from '@/components/topBar/TopBar' export default function App({ Component, pageProps }: AppProps) { return ( - + @@ -20,7 +20,7 @@ export default function App({ Component, pageProps }: AppProps) { const Layout = ({ children }: { children: ReactNode }) => ( <> - +
{children}
) diff --git a/packages/frontend/src/utils/formatters/shortenEthAddress.ts b/packages/frontend/src/utils/formatters/shortenEthAddress.ts index e403716b..cb277d9f 100644 --- a/packages/frontend/src/utils/formatters/shortenEthAddress.ts +++ b/packages/frontend/src/utils/formatters/shortenEthAddress.ts @@ -1,3 +1,4 @@ -import { Hex } from "viem"; +import { Hex } from 'viem' -export const shortenEthAddress = (address: Hex) => `${address.substring(0, 6)}......${address.substring(address.length - 4)}` +export const shortenEthAddress = (address: Hex) => + `${address.substring(0, 6)}......${address.substring(address.length - 4)}` From f705f2f4619fd616f4fb3da2f14503d9230fb1f8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Tarczynski Date: Mon, 22 Apr 2024 16:55:24 +0200 Subject: [PATCH 13/13] Move modal to correct condition in AccountButton --- .../frontend/src/components/topBar/AccountButton.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/topBar/AccountButton.tsx b/packages/frontend/src/components/topBar/AccountButton.tsx index 9d13fa3e..b70ba408 100644 --- a/packages/frontend/src/components/topBar/AccountButton.tsx +++ b/packages/frontend/src/components/topBar/AccountButton.tsx @@ -12,15 +12,15 @@ export const AccountButton = () => { return ( <> {address ? ( - + <> + + {isModalOpen && setIsModalOpen(false)} />} + ) : ( )} - {address && isModalOpen && ( - setIsModalOpen(false)} /> - )} ) }