diff --git a/assets/avatar.com.svg.react b/assets/avatar.com.svg.react
new file mode 100644
index 00000000..85e2c590
--- /dev/null
+++ b/assets/avatar.com.svg.react
@@ -0,0 +1,4 @@
+
diff --git a/modules/delegation/providers/DelegateFromPublicListContext.tsx b/modules/delegation/providers/DelegateFromPublicListContext.tsx
new file mode 100644
index 00000000..36ba49f2
--- /dev/null
+++ b/modules/delegation/providers/DelegateFromPublicListContext.tsx
@@ -0,0 +1,50 @@
+import { createContext, FC, useCallback, useContext, useState } from 'react'
+import invariant from 'tiny-invariant'
+
+//
+// Data context
+//
+
+type Value = {
+ selectedPublicDelegate: string | undefined
+ onPublicDelegateSelect: (address: string) => () => void
+ onPublicDelegateReset: () => void
+}
+
+const DelegateFromPublicListContext = createContext(null)
+
+export const useDelegateFromPublicList = () => {
+ const value = useContext(DelegateFromPublicListContext)
+ invariant(
+ value,
+ 'useDelegateFromPublicList was used outside the DelegateFromPublicListContext provider',
+ )
+ return value
+}
+
+export const DelegateFromPublicListProvider: FC = ({ children }) => {
+ const [selectedPublicDelegate, setSelectedPublicDelegate] = useState()
+
+ const handleDelegatePick = useCallback(
+ (address: string) => () => {
+ setSelectedPublicDelegate(address)
+ },
+ [],
+ )
+
+ const handleDelegateReset = useCallback(() => {
+ setSelectedPublicDelegate(undefined)
+ }, [])
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/modules/delegation/providers/DelegationFormContext.tsx b/modules/delegation/providers/DelegationFormContext.tsx
index 7810d96b..fbbffbae 100644
--- a/modules/delegation/providers/DelegationFormContext.tsx
+++ b/modules/delegation/providers/DelegationFormContext.tsx
@@ -21,6 +21,7 @@ import { useDelegationFormSubmit } from '../hooks/useDelegationFormSubmit'
import { useDelegationRevoke } from '../hooks/useDelegationRevoke'
import { ToastSuccess } from '@lidofinance/lido-ui'
import { isValidAddress } from 'modules/shared/utils/addressValidation'
+import { useDelegateFromPublicList } from './DelegateFromPublicListContext'
//
// Data context
@@ -120,15 +121,15 @@ const useDelegationFormActions = (
//
export type DelegationFormProviderProps = {
mode: DelegationFormMode
- presetDelegateAddress?: string
}
export const DelegationFormProvider: FC = ({
children,
mode,
- presetDelegateAddress,
}) => {
const networkData = useDelegationFormNetworkData()
+ const { selectedPublicDelegate, onPublicDelegateReset } =
+ useDelegateFromPublicList()
const formObject = useForm({
defaultValues: { delegateAddress: '' },
@@ -138,14 +139,17 @@ export const DelegationFormProvider: FC = ({
useEffect(() => {
const currentValue = formObject.getValues('delegateAddress')
if (
- presetDelegateAddress &&
- isValidAddress(presetDelegateAddress) &&
- currentValue?.toLowerCase() !== presetDelegateAddress.toLowerCase()
+ selectedPublicDelegate &&
+ isValidAddress(selectedPublicDelegate) &&
+ currentValue?.toLowerCase() !== selectedPublicDelegate.toLowerCase()
) {
- formObject.setValue('delegateAddress', presetDelegateAddress)
+ formObject.setValue('delegateAddress', selectedPublicDelegate, {
+ shouldValidate: true,
+ })
+ onPublicDelegateReset()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [presetDelegateAddress])
+ }, [selectedPublicDelegate])
const {
isSubmitting,
diff --git a/modules/delegation/ui/DelegationForm/DelegationFormStyle.ts b/modules/delegation/ui/DelegationForm/DelegationFormStyle.ts
index 54e67188..65b656d0 100644
--- a/modules/delegation/ui/DelegationForm/DelegationFormStyle.ts
+++ b/modules/delegation/ui/DelegationForm/DelegationFormStyle.ts
@@ -1,4 +1,4 @@
-import styled from 'styled-components'
+import styled, { css } from 'styled-components'
import { Button, Text } from '@lidofinance/lido-ui'
export const DelegationFormControllerStyled = styled.form<{
@@ -9,11 +9,11 @@ export const DelegationFormControllerStyled = styled.form<{
${({ $customMode }) =>
$customMode &&
- `
- padding: 24px 16px;
- background-color: var(--lido-color-accentControlBg);
- border-radius: 20px;
- `}
+ css`
+ padding: 24px 16px;
+ background-color: var(--lido-color-accentControlBg);
+ border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px;
+ `}
`
export const DelegationSubtitleStyled = styled.div`
diff --git a/modules/delegation/ui/DelegationForm/DelegationFormSubtitle.tsx b/modules/delegation/ui/DelegationForm/DelegationFormSubtitle.tsx
index 0af0bac9..58b2a616 100644
--- a/modules/delegation/ui/DelegationForm/DelegationFormSubtitle.tsx
+++ b/modules/delegation/ui/DelegationForm/DelegationFormSubtitle.tsx
@@ -1,4 +1,4 @@
-import { Text } from '@lidofinance/lido-ui'
+import { Text, useBreakpoint } from '@lidofinance/lido-ui'
import { DelegationSubtitleStyled } from './DelegationFormStyle'
import { useDelegationFormData } from 'modules/delegation/providers/DelegationFormContext'
@@ -7,12 +7,13 @@ import SnapshotSvg from 'assets/snapshot.com.svg.react'
export function DelegationFormSubtitle() {
const { mode } = useDelegationFormData()
+ const isMobile = useBreakpoint('md')
if (mode === 'aragon') {
return (
-
+
On Aragon
@@ -23,7 +24,7 @@ export function DelegationFormSubtitle() {
return (
-
+
On Snapshot
diff --git a/modules/delegation/ui/DelegationSettings/DelegationSettings.tsx b/modules/delegation/ui/DelegationSettings/DelegationSettings.tsx
index ed9c097a..5b0e7946 100644
--- a/modules/delegation/ui/DelegationSettings/DelegationSettings.tsx
+++ b/modules/delegation/ui/DelegationSettings/DelegationSettings.tsx
@@ -1,58 +1,47 @@
-import { useCallback, useState } from 'react'
-import { Button, Text } from '@lidofinance/lido-ui'
+import { useState } from 'react'
+import { Button, Text, useBreakpoint } from '@lidofinance/lido-ui'
import { FormTitle, FormWrap, Wrap } from './DelegationSettingsStyle'
import { DelegationForm } from '../DelegationForm'
import { PublicDelegateList } from '../PublicDelegateList'
+import { DelegateFromPublicListProvider } from '../../providers/DelegateFromPublicListContext'
export function DelegationSettings() {
const [isSimpleModeOn, setIsSimpleModeOn] = useState(true)
- const [delegateFromPublicList, setDelegateFromPublicList] = useState()
-
- const handleDelegatePick = useCallback(
- (address: string) => () => {
- setDelegateFromPublicList(address)
- },
- [],
- )
+ const isMobile = useBreakpoint('md')
return (
-
-
-
- Delegation
-
- {!isSimpleModeOn && (
-
- )}
-
- {isSimpleModeOn ? (
- setIsSimpleModeOn(false)}
- />
- ) : (
- <>
+
+
+
+
+ Delegation
+
+ {!isSimpleModeOn && (
+
+ )}
+
+ {isSimpleModeOn ? (
setIsSimpleModeOn(false)}
/>
-
- >
- )}
-
-
+ ) : (
+ <>
+
+
+ >
+ )}
+
+
+
)
}
diff --git a/modules/delegation/ui/DelegationSettings/DelegationSettingsStyle.ts b/modules/delegation/ui/DelegationSettings/DelegationSettingsStyle.ts
index 9e945747..8ec2c3ba 100644
--- a/modules/delegation/ui/DelegationSettings/DelegationSettingsStyle.ts
+++ b/modules/delegation/ui/DelegationSettings/DelegationSettingsStyle.ts
@@ -1,4 +1,4 @@
-import { BREAKPOINT_MOBILE } from 'modules/globalStyles'
+import { BREAKPOINT_MD, BREAKPOINT_MOBILE } from 'modules/globalStyles'
import styled from 'styled-components'
export const Wrap = styled.div`
@@ -6,6 +6,7 @@ export const Wrap = styled.div`
gap: 20px;
justify-content: center;
align-items: flex-start;
+ flex-wrap: wrap;
& > div {
flex: 1;
@@ -22,7 +23,7 @@ export const Wrap = styled.div`
`
export const FormWrap = styled.div<{ $customizable: boolean }>`
- border-radius: 20px;
+ border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px;
background-color: var(--lido-color-foreground);
display: flex;
flex-direction: column;
@@ -35,6 +36,10 @@ export const FormWrap = styled.div<{ $customizable: boolean }>`
`
padding: 32px 24px;
`}
+
+ @media (max-width: ${BREAKPOINT_MD}) {
+ padding: 20px;
+ }
`
export const FormTitle = styled.div`
diff --git a/modules/delegation/ui/DelegatorsList/DelegatorsListStyle.ts b/modules/delegation/ui/DelegatorsList/DelegatorsListStyle.ts
index bd419488..44ee7d4e 100644
--- a/modules/delegation/ui/DelegatorsList/DelegatorsListStyle.ts
+++ b/modules/delegation/ui/DelegatorsList/DelegatorsListStyle.ts
@@ -2,7 +2,7 @@ import { Button } from '@lidofinance/lido-ui'
import styled from 'styled-components'
export const Wrap = styled.div<{ $empty?: boolean }>`
- border-radius: 20px;
+ border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px;
background-color: var(--lido-color-foreground);
padding: 32px;
display: flex;
diff --git a/modules/delegation/ui/PublicDelegateList/PublicDelegateAvatar.tsx b/modules/delegation/ui/PublicDelegateList/PublicDelegateAvatar.tsx
new file mode 100644
index 00000000..c864bdd1
--- /dev/null
+++ b/modules/delegation/ui/PublicDelegateList/PublicDelegateAvatar.tsx
@@ -0,0 +1,30 @@
+import Image from 'next/image'
+import { AvatarWrap } from './PublicDelegateListStyle'
+
+import AvatarSvg from 'assets/avatar.com.svg.react'
+
+type Props = {
+ avatarSrc: string | null | undefined
+}
+
+export function PublicDelegateAvatar({ avatarSrc }: Props) {
+ if (!avatarSrc) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+ src}
+ unoptimized
+ />
+
+ )
+}
diff --git a/modules/delegation/ui/PublicDelegateList/PublicDelegateList.tsx b/modules/delegation/ui/PublicDelegateList/PublicDelegateList.tsx
index 07f87a9d..edbb6b25 100644
--- a/modules/delegation/ui/PublicDelegateList/PublicDelegateList.tsx
+++ b/modules/delegation/ui/PublicDelegateList/PublicDelegateList.tsx
@@ -1,33 +1,20 @@
-import { Button, Text, trimAddress } from '@lidofinance/lido-ui'
-import Image from 'next/image'
+import { Text, useBreakpoint } from '@lidofinance/lido-ui'
import {
- DelegateInfo,
Header,
HeaderTitleWithIcon,
InnerWrap,
- ListItem,
Wrap,
- SocialButtons,
- AvatarWrap,
} from './PublicDelegateListStyle'
-import { ExternalLink } from 'modules/shared/ui/Common/ExternalLink'
import { useWeb3 } from 'modules/blockChain/hooks/useWeb3'
import { useProcessedPublicDelegatesList } from './useProcessedPublicDelegatesList'
import { PageLoader } from 'modules/shared/ui/Common/PageLoader'
-import { isValidAddress } from 'modules/shared/utils/addressValidation'
-import { formatBalance } from 'modules/blockChain/utils/formatBalance'
-import { AddressPop } from 'modules/shared/ui/Common/AddressPop'
+import { PublicDelegateListItem } from './PublicDelegateListItem'
import AragonSvg from 'assets/aragon.com.svg.react'
-import XSocialSvg from 'assets/x.social.com.svg.react'
-import LidoSocialSvg from 'assets/lido.social.com.svg.react'
-type Props = {
- onDelegatePick: (address: string) => () => void
-}
-
-export function PublicDelegateList({ onDelegatePick }: Props) {
+export function PublicDelegateList() {
const { isWalletConnected } = useWeb3()
+ const isMobile = useBreakpoint('md')
const { data, initialLoading } = useProcessedPublicDelegatesList()
@@ -41,75 +28,32 @@ export function PublicDelegateList({ onDelegatePick }: Props) {
return (
-
+
Public Delegate List
-
-
- Delegate
-
-
- VP
-
- From
-
-
-
- {data.map(delegate => (
-
-
-
- {delegate.avatar ? (
- src}
- unoptimized
- />
- ) : (
-
- )}
-
-
-
- {delegate.name}
-
-
-
- {isValidAddress(delegate.address)
- ? trimAddress(delegate.address, 6)
- : delegate.address}
-
-
-
-
-
- {delegate.delegatedVotingPower === 'N/A'
- ? delegate.delegatedVotingPower
- : formatBalance(delegate.delegatedVotingPower)}
+ {!isMobile && (
+
+
+ Delegate
- {delegate.delegatorsCount}
-
-
-
-
-
-
-
-
- {isWalletConnected && (
-
- )}
-
+
+ VP
+
+
+ From
+
+
+
+
+ )}
+ {data.map(delegate => (
+
))}
diff --git a/modules/delegation/ui/PublicDelegateList/PublicDelegateListItem.tsx b/modules/delegation/ui/PublicDelegateList/PublicDelegateListItem.tsx
new file mode 100644
index 00000000..09ac0cc5
--- /dev/null
+++ b/modules/delegation/ui/PublicDelegateList/PublicDelegateListItem.tsx
@@ -0,0 +1,128 @@
+import {
+ DelegateInfo,
+ DelegateNameAndAddress,
+ DelegateNumbersMobile,
+ HeaderTitleWithIcon,
+ ListItem,
+ SocialButtons,
+} from './PublicDelegateListStyle'
+import { ProcessedDelegate } from './useProcessedPublicDelegatesList'
+import { Button, Text, trimAddress } from '@lidofinance/lido-ui'
+import { AddressPop } from 'modules/shared/ui/Common/AddressPop'
+import { isValidAddress } from 'modules/shared/utils/addressValidation'
+import { formatBalance } from 'modules/blockChain/utils/formatBalance'
+import { ExternalLink } from 'modules/shared/ui/Common/ExternalLink'
+import { PublicDelegateAvatar } from './PublicDelegateAvatar'
+import { useDelegateFromPublicList } from 'modules/delegation/providers/DelegateFromPublicListContext'
+
+import XSocialSvg from 'assets/x.social.com.svg.react'
+import LidoSocialSvg from 'assets/lido.social.com.svg.react'
+import AragonSvg from 'assets/aragon.com.svg.react'
+
+type Props = {
+ delegate: ProcessedDelegate
+ isWalletConnected: boolean
+ isMobile: boolean
+}
+
+export function PublicDelegateListItem({
+ delegate,
+ isWalletConnected,
+ isMobile,
+}: Props) {
+ const { onPublicDelegateSelect } = useDelegateFromPublicList()
+
+ const addressToShow = isValidAddress(delegate.address)
+ ? trimAddress(delegate.address, 6)
+ : delegate.address
+
+ const balanceToShow =
+ delegate.delegatedVotingPower === 'N/A'
+ ? delegate.delegatedVotingPower
+ : formatBalance(delegate.delegatedVotingPower)
+
+ if (isMobile) {
+ return (
+
+
+
+
+
+ {delegate.name}
+
+
+
+ {addressToShow}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VP
+ {balanceToShow}
+
+
+ From {delegate.delegatorsCount}
+
+
+ {isWalletConnected && (
+
+ )}
+
+ )
+ }
+
+ return (
+
+
+
+
+
+ {delegate.name}
+
+
+
+ {addressToShow}
+
+
+
+
+ {balanceToShow}
+ {delegate.delegatorsCount}
+
+
+
+
+
+
+
+
+ {isWalletConnected && (
+
+ )}
+
+ )
+}
diff --git a/modules/delegation/ui/PublicDelegateList/PublicDelegateListStyle.ts b/modules/delegation/ui/PublicDelegateList/PublicDelegateListStyle.ts
index 0bd4766d..f6d0458c 100644
--- a/modules/delegation/ui/PublicDelegateList/PublicDelegateListStyle.ts
+++ b/modules/delegation/ui/PublicDelegateList/PublicDelegateListStyle.ts
@@ -1,37 +1,43 @@
import { Text } from '@lidofinance/lido-ui'
-import { BREAKPOINT_MOBILE } from 'modules/globalStyles'
+import { BREAKPOINT_MOBILE, BREAKPOINT_MD } from 'modules/globalStyles'
import styled from 'styled-components'
export const Wrap = styled.div`
padding: 32px 24px;
- border-radius: 20px;
+ border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px;
background-color: var(--lido-color-foreground);
display: flex;
flex-direction: column;
gap: 24px;
max-width: 542px;
- max-height: 492px;
- overflow: hidden;
+ min-width: 460px;
+
+ @media (max-width: ${BREAKPOINT_MOBILE}) {
+ min-width: unset;
+ max-height: unset;
+ }
+
+ @media (max-width: ${BREAKPOINT_MD}) {
+ padding: 20px;
+ }
`
export const InnerWrap = styled.div<{ $connected: boolean }>`
- border-radius: 20px;
+ border-radius: inherit;
border: 1px solid var(--lido-color-border);
display: flex;
flex-direction: column;
- overflow-y: auto;
- max-height: 310px;
- border-radius: inherit;
+ overflow-x: hidden;
& > div {
display: grid;
gap: 10px;
- grid-template-columns: 3fr 1fr 1fr 40px ${({ $connected }) =>
- $connected ? '2fr' : ''};
+ grid-template-columns: minmax(130px, 3fr) repeat(2, minmax(42px, 1fr)) 40px ${({
+ $connected,
+ }) => ($connected ? 'minmax(0, 85px)' : '')};
- @media (max-width: ${BREAKPOINT_MOBILE}) {
- grid-template-columns: 2fr ${({ $connected }) =>
- $connected ? '1fr' : ''};
+ @media (max-width: ${BREAKPOINT_MD}) {
+ display: flex;
}
}
`
@@ -43,14 +49,6 @@ export const Header = styled.div`
background-color: var(--lido-color-foreground);
z-index: 2;
border-bottom: 1px solid var(--lido-color-border);
-
- @media (max-width: ${BREAKPOINT_MOBILE}) {
- & > *:nth-child(2),
- & > *:nth-child(3),
- & > *:nth-child(4) {
- display: none;
- }
- }
`
export const HeaderTitleWithIcon = styled(Text).attrs({
@@ -70,18 +68,22 @@ export const ListItem = styled.div`
background-color: var(--lido-color-background);
}
- @media (max-width: ${BREAKPOINT_MOBILE}) {
- & > *:nth-child(2),
- & > *:nth-child(3),
- & > *:nth-child(4) {
- display: none;
- }
+ @media (max-width: ${BREAKPOINT_MD}) {
+ padding: 20px 12px;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ align-items: stretch;
}
`
export const DelegateInfo = styled.div`
display: flex;
align-items: center;
gap: 8px;
+
+ @media (max-width: ${BREAKPOINT_MD}) {
+ gap: 12px;
+ }
`
export const AvatarWrap = styled.div`
@@ -89,26 +91,23 @@ export const AvatarWrap = styled.div`
border-radius: 50%;
width: 28px;
height: 28px;
- background-color: var(--lido-color-primaryVisited);
overflow: hidden;
+ flex-shrink: 0;
& > img,
- div {
+ & > svg {
width: 100%;
height: 100%;
- object-fit: cover;
- display: block;
}
& > img[src=''] {
display: none;
}
-`
-export const Avatar = styled.img`
- border-radius: 50%;
- width: 28px;
- height: 28px;
+ @media (max-width: ${BREAKPOINT_MD}) {
+ width: 32px;
+ height: 32px;
+ }
`
export const SocialButtons = styled.div`
@@ -116,6 +115,48 @@ export const SocialButtons = styled.div`
gap: 6px;
& > span {
- max-height: 16px;
+ height: 16px;
+
+ & > svg path {
+ transition: fill ease ${({ theme }) => theme.duration.norm};
+ }
+
+ &:hover > svg path {
+ fill: var(--lido-color-primaryHover);
+ }
+ }
+
+ @media (max-width: ${BREAKPOINT_MD}) {
+ & > span {
+ height: 24px;
+ }
+
+ svg {
+ width: 24px;
+ height: 24px;
+ }
+ }
+`
+
+export const DelegateNameAndAddress = styled.div`
+ max-width: calc(100% - 36px);
+
+ & > p,
+ & > span {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100%;
}
+
+ @media (max-width: ${BREAKPOINT_MD}) {
+ max-width: 100%;
+ flex: 1;
+ }
+`
+
+export const DelegateNumbersMobile = styled.div`
+ display: inline-flex;
+ align-items: center;
+ gap: 32px;
`
diff --git a/modules/delegation/ui/PublicDelegateList/useProcessedPublicDelegatesList.ts b/modules/delegation/ui/PublicDelegateList/useProcessedPublicDelegatesList.ts
index b6ab280b..bdd3b7c9 100644
--- a/modules/delegation/ui/PublicDelegateList/useProcessedPublicDelegatesList.ts
+++ b/modules/delegation/ui/PublicDelegateList/useProcessedPublicDelegatesList.ts
@@ -10,7 +10,7 @@ import {
isValidEns,
} from 'modules/shared/utils/addressValidation'
-type ProcessedDelegate = typeof PUBLIC_DELEGATES[number] & {
+export type ProcessedDelegate = typeof PUBLIC_DELEGATES[number] & {
delegatorsCount: string
delegatedVotingPower: BigNumber | string
resolvedDelegateAddress: string | null
diff --git a/modules/globalStyles/index.ts b/modules/globalStyles/index.ts
index 4f6ac5eb..9ccb5913 100644
--- a/modules/globalStyles/index.ts
+++ b/modules/globalStyles/index.ts
@@ -1,6 +1,8 @@
+import { themeDefault } from '@lidofinance/lido-ui'
import { createGlobalStyle } from 'styled-components'
export const BREAKPOINT_MOBILE = '960px'
+export const BREAKPOINT_MD = themeDefault.breakpointsMap.md.width
export const GlobalStyle = createGlobalStyle`
*,
diff --git a/modules/shared/ui/Layout/Header/HeaderStyle.ts b/modules/shared/ui/Layout/Header/HeaderStyle.ts
index 2fa9d5df..824f00af 100644
--- a/modules/shared/ui/Layout/Header/HeaderStyle.ts
+++ b/modules/shared/ui/Layout/Header/HeaderStyle.ts
@@ -123,10 +123,6 @@ export const InputWrap = styled.div`
@media (max-width: 1060px) {
width: 200px;
}
-
- @media (max-width: 810px) {
- width: 200px;
- }
`
export const Network = styled.div`