Skip to content

Commit 6d1201c

Browse files
authored
Merge pull request #1287 from kleros/feat(web)/desktop-staking-flow-design
feat(web): staking flow desktop figma style
2 parents f845a26 + 5fc1a7e commit 6d1201c

File tree

7 files changed

+176
-65
lines changed

7 files changed

+176
-65
lines changed
Lines changed: 19 additions & 0 deletions
Loading

web/src/components/Field.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const FieldContainer = styled.div<FieldContainerProps>`
99
justify-content: flex-start;
1010
white-space: nowrap;
1111
width: 100%;
12-
1312
.value {
1413
flex-grow: 1;
1514
text-align: end;
@@ -28,7 +27,6 @@ const FieldContainer = styled.div<FieldContainerProps>`
2827
cursor: pointer;
2928
}
3029
}
31-
3230
${({ isList }) =>
3331
isList &&
3432
css`
@@ -42,8 +40,8 @@ const FieldContainer = styled.div<FieldContainerProps>`
4240
`
4341
)}
4442
`};
45-
${({ isOverview }) =>
46-
isOverview &&
43+
${({ isOverview, isJurorBalance }) =>
44+
(isOverview || isJurorBalance) &&
4745
css`
4846
${landscapeStyle(
4947
() => css`
@@ -66,6 +64,7 @@ type FieldContainerProps = {
6664
width?: string;
6765
isList?: boolean;
6866
isOverview?: boolean;
67+
isJurorBalance?: boolean;
6968
};
7069

7170
interface IField {
@@ -76,12 +75,22 @@ interface IField {
7675
width?: string;
7776
displayAsList?: boolean;
7877
isOverview?: boolean;
78+
isJurorBalance?: boolean;
7979
}
8080

81-
const Field: React.FC<IField> = ({ icon: Icon, name, value, link, width, displayAsList, isOverview }) => {
81+
const Field: React.FC<IField> = ({
82+
icon: Icon,
83+
name,
84+
value,
85+
link,
86+
width,
87+
displayAsList,
88+
isOverview,
89+
isJurorBalance,
90+
}) => {
8291
return (
83-
<FieldContainer isList={displayAsList} isOverview={isOverview} width={width}>
84-
{(!displayAsList || isOverview) && (
92+
<FieldContainer isList={displayAsList} isOverview={isOverview} isJurorBalance={isJurorBalance} width={width}>
93+
{(!displayAsList || isOverview || isJurorBalance) && (
8594
<>
8695
<Icon />
8796
<label>{name}:</label>
@@ -97,5 +106,4 @@ const Field: React.FC<IField> = ({ icon: Icon, name, value, link, width, display
97106
</FieldContainer>
98107
);
99108
};
100-
101109
export default Field;

web/src/components/NumberInputField.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ const Container = styled.div`
1010
const StyledField = styled(Field)`
1111
width: 100%;
1212
height: fit-content;
13+
14+
input[type="number"]::-webkit-inner-spin-button,
15+
input[type="number"]::-webkit-outer-spin-button {
16+
-webkit-appearance: none;
17+
appearance: none;
18+
}
19+
input[type="number"] {
20+
-moz-appearance: textfield;
21+
}
22+
input {
23+
border: 1px solid ${({ theme }) => theme.stroke};
24+
border-right: none;
25+
height: 45px;
26+
font-size: 16px;
27+
}
1328
`;
1429

1530
interface INumberInputField {

web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { commify, uncommify } from "utils/commify";
1414
import { EnsureChain } from "components/EnsureChain";
1515

1616
const StyledField = styled(NumberInputField)`
17-
width: 100%;
1817
height: fit-content;
1918
`;
2019

@@ -33,6 +32,13 @@ const InputArea = styled.div`
3332
flex-direction: column;
3433
align-items: center;
3534
gap: 12px;
35+
width: 100%;
36+
`;
37+
38+
const InputFieldAndButton = styled.div`
39+
display: flex;
40+
flex-direction: row;
41+
width: 100%;
3642
`;
3743

3844
interface IInputDisplay {
@@ -87,35 +93,37 @@ const InputDisplay: React.FC<IInputDisplay> = ({
8793
</StyledLabel>
8894
</LabelArea>
8995
<InputArea>
90-
<StyledField
91-
value={uncommify(amount)}
92-
onChange={(e) => {
93-
setAmount(e);
94-
}}
95-
placeholder={isStaking ? "Amount to stake" : "Amount to withdraw"}
96-
message={
97-
isStaking
98-
? `You need to stake at least ${formatPNK(courtDetails?.court.minStake ?? 0n, 3)} PNK. ` +
99-
"You may need two transactions, one to increase allowance, the other to stake."
100-
: `You need to either withdraw all or keep at least ${formatPNK(
101-
courtDetails?.court.minStake ?? 0n,
102-
3
103-
)} PNK.`
104-
}
105-
formatter={(number: string) => commify(roundNumberDown(Number(number)))}
106-
/>
107-
<EnsureChain>
108-
<StakeWithdrawButton
109-
{...{
110-
parsedAmount,
111-
action,
112-
setAmount,
113-
isSending,
114-
setIsSending,
115-
setIsPopupOpen,
96+
<InputFieldAndButton>
97+
<StyledField
98+
value={uncommify(amount)}
99+
onChange={(e) => {
100+
setAmount(e);
116101
}}
102+
placeholder={isStaking ? "Amount to stake" : "Amount to withdraw"}
103+
// message={
104+
// isStaking
105+
// ? `You need to stake at least ${formatPNK(courtDetails?.court.minStake ?? 0n, 3)} PNK. ` +
106+
// "You may need two transactions, one to increase allowance, the other to stake."
107+
// : `You need to either withdraw all or keep at least ${formatPNK(
108+
// courtDetails?.court.minStake ?? 0n,
109+
// 3
110+
// )} PNK.`
111+
// }
112+
formatter={(number: string) => commify(roundNumberDown(Number(number)))}
117113
/>
118-
</EnsureChain>
114+
<EnsureChain>
115+
<StakeWithdrawButton
116+
{...{
117+
parsedAmount,
118+
action,
119+
setAmount,
120+
isSending,
121+
setIsSending,
122+
setIsPopupOpen,
123+
}}
124+
/>
125+
</EnsureChain>
126+
</InputFieldAndButton>
119127
</InputArea>
120128
</>
121129
);

web/src/pages/Courts/CourtDetails/StakePanel/JurorStakeDisplay.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useEffect, useMemo } from "react";
2-
import styled from "styled-components";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
34
import { useParams } from "react-router-dom";
45
import { formatEther } from "viem";
56
import { useAccount } from "wagmi";
@@ -13,10 +14,21 @@ import { useKlerosCoreGetJurorBalance } from "hooks/contracts/generated";
1314

1415
const Container = styled.div`
1516
display: flex;
17+
width: 100%;
1618
flex-direction: column;
1719
justify-content: space-between;
1820
gap: 8px;
1921
margin-top: 12px;
22+
23+
${landscapeStyle(
24+
() => css`
25+
margin-top: 32px;
26+
gap: 32px;
27+
flex-direction: row;
28+
flex-wrap: wrap;
29+
justify-content: flex-start;
30+
`
31+
)}
2032
`;
2133

2234
const format = (value: bigint | undefined): string => (value !== undefined ? formatEther(value) : "0");
@@ -104,7 +116,7 @@ const JurorBalanceDisplay = () => {
104116
return (
105117
<Container>
106118
{data.map(({ icon, name, value }) => (
107-
<Field key={name} {...{ icon, name, value }} />
119+
<Field isJurorBalance={true} key={name} {...{ icon, name, value }} />
108120
))}
109121
</Container>
110122
);

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useMemo } from "react";
2+
import styled from "styled-components";
23
import { useParams } from "react-router-dom";
34
import { useAccount, usePublicClient } from "wagmi";
45
import { Button } from "@kleros/ui-components-library";
@@ -17,6 +18,11 @@ import { wrapWithToast } from "utils/wrapWithToast";
1718
import { isUndefined } from "utils/index";
1819
import { EnsureChain } from "components/EnsureChain";
1920

21+
const StyledStakeWithdrawButton = styled(Button)`
22+
border: 1px solid ${({ theme }) => theme.stroke};
23+
height: 45px;
24+
`;
25+
2026
export enum ActionType {
2127
allowance = "allowance",
2228
stake = "stake",
@@ -129,7 +135,7 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
129135
const { text, checkDisabled, onClick } = buttonProps[isAllowance ? ActionType.allowance : action];
130136
return (
131137
<EnsureChain>
132-
<Button
138+
<StyledStakeWithdrawButton
133139
text={text}
134140
isLoading={isSending}
135141
disabled={

web/src/pages/Courts/CourtDetails/StakePanel/index.tsx

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import React, { useState } from "react";
2-
import styled from "styled-components";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
34
import { useLockOverlayScroll } from "hooks/useLockOverlayScroll";
45
import Tag from "components/Tag";
56
import JurorBalanceDisplay from "./JurorStakeDisplay";
67
import InputDisplay from "./InputDisplay";
78
import { ActionType } from "./StakeWithdrawButton";
89
import Popup, { PopupType } from "components/Popup/index";
910
import BalanceIcon from "assets/svgs/icons/balance.svg";
11+
import ThreePnksIcon from "tsx:assets/svgs/styled/three-pnks.svg";
1012

1113
const Container = styled.div`
1214
position: relative;
@@ -15,6 +17,23 @@ const Container = styled.div`
1517
display: flex;
1618
flex-direction: column;
1719
gap: 28px;
20+
21+
${landscapeStyle(
22+
() => css`
23+
flex-direction: row;
24+
`
25+
)};
26+
`;
27+
28+
const LeftArea = styled.div`
29+
display: flex;
30+
flex-direction: column;
31+
32+
${landscapeStyle(
33+
() => css`
34+
width: 50%;
35+
`
36+
)};
1837
`;
1938

2039
const TagArea = styled.div`
@@ -23,13 +42,32 @@ const TagArea = styled.div`
2342
`;
2443

2544
const StakeArea = styled(TagArea)`
45+
margin-top: 28px;
2646
flex-direction: column;
2747
`;
2848

2949
const TextArea = styled.div`
50+
margin-top: 32px;
3051
color: ${({ theme }) => theme.primaryText};
3152
`;
3253

54+
const ThreePnksIconContainer = styled.div`
55+
display: flex;
56+
width: 100%;
57+
justify-content: flex-start;
58+
align-items: center;
59+
60+
${landscapeStyle(
61+
() => css`
62+
width: 50%;
63+
justify-content: flex-end;
64+
align-items: flex-end;
65+
margin-bottom: 42px;
66+
margin-right: 52px;
67+
`
68+
)};
69+
`;
70+
3371
const StakePanel: React.FC<{ courtName: string; id: string }> = ({ courtName = "General Court", id }) => {
3472
const [amount, setAmount] = useState("");
3573
const [isSending, setIsSending] = useState<boolean>(false);
@@ -47,31 +85,36 @@ const StakePanel: React.FC<{ courtName: string; id: string }> = ({ courtName = "
4785
const isStaking = action === ActionType.stake;
4886
return (
4987
<Container>
50-
<TagArea>
51-
<Tag text="Stake" active={isActive} onClick={() => handleClick(ActionType.stake)} />
52-
<Tag text="Withdraw" active={!isActive} onClick={() => handleClick(ActionType.withdraw)} />
53-
</TagArea>
54-
<TextArea>
55-
<strong>{`${isStaking ? "Stake" : "Withdraw"} PNK`}</strong> {`${isStaking ? "to join the" : "from"}`}{" "}
56-
{courtName} court. Depending on the staking phase, your stake might take some time to be live.
57-
</TextArea>
58-
<StakeArea>
59-
<InputDisplay {...{ action, isSending, setIsSending, setIsPopupOpen, amount, setAmount }} />
60-
<JurorBalanceDisplay />
61-
</StakeArea>
62-
{isPopupOpen && (
63-
<Popup
64-
title={isStaking ? "Stake Confirmed" : "Withdraw Confirmed"}
65-
icon={BalanceIcon}
66-
popupType={PopupType.STAKE_WITHDRAW}
67-
isStake={isStaking}
68-
pnkStaked={amount}
69-
courtName={courtName}
70-
courtId={id}
71-
setIsOpen={setIsPopupOpen}
72-
setAmount={setAmount}
73-
/>
74-
)}
88+
<LeftArea>
89+
<TagArea>
90+
<Tag text="Stake" active={isActive} onClick={() => handleClick(ActionType.stake)} />
91+
<Tag text="Withdraw" active={!isActive} onClick={() => handleClick(ActionType.withdraw)} />
92+
</TagArea>
93+
<TextArea>
94+
<strong>{`${isStaking ? "Stake" : "Withdraw"} PNK`}</strong> {`${isStaking ? "to join the" : "from"}`}{" "}
95+
{courtName} court
96+
</TextArea>
97+
<StakeArea>
98+
<InputDisplay {...{ action, isSending, setIsSending, setIsPopupOpen, amount, setAmount }} />
99+
<JurorBalanceDisplay />
100+
</StakeArea>
101+
{isPopupOpen && (
102+
<Popup
103+
title={isStaking ? "Stake Confirmed" : "Withdraw Confirmed"}
104+
icon={BalanceIcon}
105+
popupType={PopupType.STAKE_WITHDRAW}
106+
isStake={isStaking}
107+
pnkStaked={amount}
108+
courtName={courtName}
109+
courtId={id}
110+
setIsOpen={setIsPopupOpen}
111+
setAmount={setAmount}
112+
/>
113+
)}
114+
</LeftArea>
115+
<ThreePnksIconContainer>
116+
<ThreePnksIcon />
117+
</ThreePnksIconContainer>
75118
</Container>
76119
);
77120
};

0 commit comments

Comments
 (0)