Skip to content

Commit 9e77c7f

Browse files
authored
Merge pull request #48 from lidofinance/fix/general-info
refactor: add AddressWithPopover in overview; add color in for health…
2 parents 53d6e85 + 97a9bc6 commit 9e77c7f

File tree

13 files changed

+177
-29
lines changed

13 files changed

+177
-29
lines changed

features/create-vault/create-vault-form/permissions/address-list/address-item/address-item.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface AddressItemProps {
2424
field: PermissionField;
2525
}
2626

27+
// TODO: use shared/components/AddressWithPopover component
2728
export const AddressItem: FC<AddressItemProps> = ({
2829
index,
2930
permission,

features/overview/components/balance/balance.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const sectionPayloadList: SectionPayload[] = [
1111
{
1212
title: 'Idle capital',
1313
key: 'balanceEth',
14-
actionText: 'Deposit to validators',
14+
actionText: 'Supply ETH',
1515
actionLink: '/supply/fund',
1616
},
1717
// TODO: add this after the metrics are implemented

features/overview/components/capacity/capacity.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,38 @@ const sectionPayloadList: SectionPayload[] = [
1616
},
1717
];
1818

19+
const getUtilizationRatioColor = (utilizationRatio: string) => {
20+
if (!utilizationRatio) return '';
21+
const utilizationRatioNumber = Number(utilizationRatio.split('%')[0]);
22+
23+
if (utilizationRatioNumber < 90) return '#53BA95';
24+
if (utilizationRatioNumber < 100) return '#ffbf00';
25+
if (utilizationRatioNumber === 100) return '#E14D4D';
26+
if (utilizationRatioNumber > 100) return 'darkRed';
27+
};
28+
1929
export const Capacity = () => {
2030
const { getVaultDataToRender } = useVaultOverview();
2131
const renderData = getVaultDataToRender(sectionPayloadList);
2232

2333
return (
2434
<OverviewSection title="stETH capacity utilization">
25-
{renderData.map((item) => (
26-
<OverviewItem
27-
key={item.title}
28-
title={item.title}
29-
content={item.payload}
30-
isLoading={item.isLoading}
31-
/>
32-
))}
35+
{renderData.map((item) => {
36+
const isUtilizationRatio = item.key === 'utilizationRatio';
37+
const color = isUtilizationRatio
38+
? getUtilizationRatioColor(item.payload)
39+
: undefined;
40+
41+
return (
42+
<OverviewItem
43+
key={item.title}
44+
title={item.title}
45+
content={item.payload}
46+
isLoading={item.isLoading}
47+
color={color}
48+
/>
49+
);
50+
})}
3351
</OverviewSection>
3452
);
3553
};

features/overview/components/general/address-section/address-section.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useVaultOverview } from 'features/overview/contexts';
22

3-
import { AddressBadge } from 'shared/components';
3+
import { AddressWithPopover } from 'shared/components';
44
import { Text } from '@lidofinance/lido-ui';
55
import { NodeOperator, Title, Wrapper } from './styles';
66

@@ -11,14 +11,14 @@ export const AddressSection = () => {
1111

1212
return (
1313
<Wrapper>
14-
<AddressBadge size="lg" address={address} />
14+
<AddressWithPopover size="lg" address={address} />
1515
<NodeOperator>
1616
<Title>
1717
<Text color="secondary" size="xxs">
1818
Node operator
1919
</Text>
2020
</Title>
21-
<AddressBadge weight={400} address={nodeOperator} />
21+
<AddressWithPopover weight={400} address={nodeOperator} />
2222
</NodeOperator>
2323
</Wrapper>
2424
);

features/overview/components/health/heath.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,37 @@ const sectionPayloadList: SectionPayload[] = [
2020
},
2121
];
2222

23+
const getHealthFactorColor = (healthFactor: string) => {
24+
if (!healthFactor) return '';
25+
const healthFactorNumber = Number(healthFactor.split('%')[0]);
26+
if (healthFactorNumber >= 125) return '#53BA95 ';
27+
if (healthFactorNumber >= 105) return '#ffbf00';
28+
if (healthFactorNumber >= 100) return '#E14D4D';
29+
return 'darkRed';
30+
};
31+
2332
export const Health = () => {
2433
const { getVaultDataToRender } = useVaultOverview();
2534
const renderData = getVaultDataToRender(sectionPayloadList);
2635

2736
return (
2837
<OverviewSection title="Vault health" titleTooltip="Lorem Ipsum">
29-
{renderData.map((item) => (
30-
<OverviewItem
31-
key={item.title}
32-
title={item.title}
33-
content={item.payload}
34-
isLoading={item.isLoading}
35-
/>
36-
))}
38+
{renderData.map((item) => {
39+
const isHealthy = item.key === 'healthFactor';
40+
const color = isHealthy
41+
? getHealthFactorColor(item.payload)
42+
: undefined;
43+
44+
return (
45+
<OverviewItem
46+
key={item.title}
47+
title={item.title}
48+
content={item.payload}
49+
isLoading={item.isLoading}
50+
color={color}
51+
/>
52+
);
53+
})}
3754
</OverviewSection>
3855
);
3956
};

features/overview/shared/overview-item/overview-item-value.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import { LoaderWrapper, ValueWrapper } from './styles';
66
export interface ItemValueProps {
77
content: string | number | undefined;
88
isLoading?: boolean;
9-
isSuccess?: boolean;
9+
color?: string;
1010
}
1111

1212
export const OverviewItemValue: FC<ItemValueProps> = (props) => {
13-
const { content, isSuccess, isLoading } = props;
14-
const contentColor = isSuccess ? 'success' : 'default';
13+
const { content, isLoading, color } = props;
1514

1615
return (
1716
<>
@@ -21,7 +20,7 @@ export const OverviewItemValue: FC<ItemValueProps> = (props) => {
2120
</LoaderWrapper>
2221
) : (
2322
<ValueWrapper>
24-
<Text size="lg" color={contentColor} strong>
23+
<Text size="lg" style={{ color }} strong>
2524
{content ?? '-'}
2625
</Text>
2726
</ValueWrapper>

features/overview/shared/overview-item/overview-item.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ export interface ItemProps {
1212
content: string | number | undefined;
1313
actionLink?: string;
1414
actionText?: string;
15-
isSuccess?: boolean;
1615
isLoading?: boolean;
16+
color?: string;
1717
}
1818

1919
export const OverviewItem: FC<ItemProps> = (props) => {
2020
const router = useRouter();
2121
const { activeVault } = useVaultInfo();
22-
const { title, content, isSuccess, actionLink, actionText, isLoading } =
23-
props;
22+
const { title, content, actionLink, actionText, isLoading, color } = props;
2423

2524
return (
2625
<ItemWrapper>
@@ -32,7 +31,7 @@ export const OverviewItem: FC<ItemProps> = (props) => {
3231
<OverviewItemValue
3332
content={content}
3433
isLoading={isLoading}
35-
isSuccess={isSuccess}
34+
color={color}
3635
/>
3736
{!!actionLink && !!actionText && (
3837
<Button

features/settings/permissions/components/address-list/address-item/address-item.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type AddressItemProps = {
2323
readonly?: boolean;
2424
};
2525

26+
// TODO: use shared/components/AddressWithPopover component
2627
export const AddressItem: FC<AddressItemProps> = ({
2728
index,
2829
field,

shared/components/address-badge/styles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const PillContainer = styled.div<PillProps>`
8484
background-color: ${getBgColor};
8585
white-space: nowrap;
8686
text-wrap: nowrap;
87+
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
8788
`;
8889

8990
export const AddressText = styled(Address)<InjectedProps>`
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { FC, useState, useRef, MouseEvent } from 'react';
2+
3+
import { Copy, External, ToastSuccess } from '@lidofinance/lido-ui';
4+
import {
5+
AddressBadge,
6+
AddressBadgeProps,
7+
AddressLinkEtherscan,
8+
ButtonLink,
9+
} from 'shared/components';
10+
11+
import {
12+
ActionGroup,
13+
ActionWrapper,
14+
PopoverContent,
15+
PopoverWrapper,
16+
} from './styles';
17+
18+
import { truncateAddress } from 'utils/truncate-address';
19+
import { Address } from 'viem';
20+
21+
export const AddressWithPopover: FC<AddressBadgeProps> = (props) => {
22+
const { address, onToggle, onClick, bgColor, crossedText } = props;
23+
const [showPopover, showPopoverVisibility] = useState(false);
24+
const badgeRef = useRef<HTMLDivElement>(null);
25+
26+
const handleShowPopover = () => {
27+
showPopoverVisibility(true);
28+
};
29+
30+
const handleCopyLink = () => {
31+
if (!address) return;
32+
void navigator.clipboard.writeText(address);
33+
ToastSuccess(`Address ${truncateAddress({ address })} have been copied`);
34+
};
35+
36+
const handleClosePopover = () => {
37+
showPopoverVisibility(false);
38+
};
39+
40+
const handleClick = (event: MouseEvent<HTMLDivElement>) => {
41+
handleShowPopover();
42+
onClick?.(event);
43+
};
44+
45+
return (
46+
<>
47+
<AddressBadge
48+
ref={badgeRef}
49+
crossedText={crossedText}
50+
bgColor={bgColor}
51+
address={address}
52+
isActive={showPopover}
53+
onToggle={onToggle}
54+
onClick={handleClick}
55+
/>
56+
{!!badgeRef?.current && (
57+
<PopoverWrapper
58+
anchorRef={{
59+
current: badgeRef.current,
60+
}}
61+
backdrop
62+
offset="xs"
63+
onClose={handleClosePopover}
64+
placement="topLeft"
65+
open={showPopover}
66+
>
67+
<PopoverContent>
68+
<AddressBadge address={address} symbols={21} />
69+
<ActionGroup>
70+
<ActionWrapper>
71+
<Copy fill="var(--lido-color-primary)" />
72+
<ButtonLink onClick={handleCopyLink}>Copy address</ButtonLink>
73+
</ActionWrapper>
74+
<ActionWrapper>
75+
<External fill="var(--lido-color-primary)" />
76+
{address && (
77+
<AddressLinkEtherscan address={address as Address} />
78+
)}
79+
</ActionWrapper>
80+
</ActionGroup>
81+
</PopoverContent>
82+
</PopoverWrapper>
83+
)}
84+
</>
85+
);
86+
};

0 commit comments

Comments
 (0)