Skip to content

Commit

Permalink
Tong/395 phase 2 modal (#410)
Browse files Browse the repository at this point in the history
* transition modal UI refinement

* Update src/app/components/Modals/TransitionModal/StageStepping.tsx

Co-authored-by: David Totrashvili <[email protected]>

* Update src/app/components/Modals/TransitionModal/TransitionModal.tsx

Co-authored-by: David Totrashvili <[email protected]>

* Update src/app/components/Modals/TransitionModal/TransitionModal.tsx

Co-authored-by: David Totrashvili <[email protected]>

* Apply suggestions from code review

Co-authored-by: David Totrashvili <[email protected]>

* fix syntax error

---------

Co-authored-by: David Totrashvili <[email protected]>
  • Loading branch information
supertong and totraev authored Nov 30, 2024
1 parent 68817aa commit 299a1c4
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 14 deletions.
41 changes: 27 additions & 14 deletions src/app/components/Modals/CongratModal.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import { Button, Heading } from "@babylonlabs-io/bbn-core-ui";
import {
Button,
Dialog,
DialogBody,
DialogFooter,
Heading,
MobileDialog,
} from "@babylonlabs-io/bbn-core-ui";
import { LuPartyPopper } from "react-icons/lu";

import { GeneralModal } from "./GeneralModal";
import { useIsMobileView } from "@/app/hooks/useBreakpoint";

interface CongratModalProps {
open: boolean;
onClose: () => void;
}

export function CongratModal({ open, onClose }: CongratModalProps) {
const isMobileView = useIsMobileView();
const DialogComponent = isMobileView ? MobileDialog : Dialog;

return (
<GeneralModal
open={open}
onClose={onClose}
closeOnOverlayClick={false}
closeOnEsc={false}
>
<div className="flex flex-col gap-8 md:max-w-[34rem] text-primary-dark">
<DialogComponent open={open} onClose={onClose}>
<DialogBody className="flex flex-col pb-8 pt-4 text-primary-dark gap-4">
<div className="py-4 flex flex-col items-center gap-4">
<LuPartyPopper className="text-5xl" />
<div className="bg-primary-contrast h-20 w-20 flex items-center justify-center">
<LuPartyPopper className="text-5xl" />
</div>
<Heading variant="h4">Conratulations</Heading>
<p className="text-base text-center">
Share feedback or report issues on our{" "}
Expand All @@ -43,10 +50,16 @@ export function CongratModal({ open, onClose }: CongratModalProps) {
community!
</p>
</div>
<Button onClick={onClose}>
<span>Done</span>
</DialogBody>
<DialogFooter className="flex gap-4">
<Button
variant="contained"
className="flex-1 text-xs sm:text-base"
onClick={onClose}
>
Done
</Button>
</div>
</GeneralModal>
</DialogFooter>
</DialogComponent>
);
}
41 changes: 41 additions & 0 deletions src/app/components/Modals/TransitionModal/StageEnd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
Button,
DialogBody,
DialogFooter,
Heading,
} from "@babylonlabs-io/bbn-core-ui";
import { IoMdCheckmark } from "react-icons/io";

interface StageEndProps {
onClose: () => void;
}

export function StageEnd({ onClose }: StageEndProps) {
return (
<>
<DialogBody className="flex flex-col pb-8 pt-4 text-primary-dark gap-4">
<div className="py-4 flex flex-col items-center gap-4">
<div className="bg-primary-contrast h-20 w-20 flex items-center justify-center">
<IoMdCheckmark className="text-5xl" />
</div>
<Heading variant="h4">Transition Submitted</Heading>
<p className="text-base text-center">
Your phase-1 staking transaction has been successfully submitted to
the Babylon blockchain and should be activated and receive voting
power in a few blocks. Please monitor the Activity tab for the
activation status.
</p>
</div>
</DialogBody>
<DialogFooter className="flex gap-4">
<Button
variant="contained"
className="flex-1 text-xs sm:text-base"
onClick={onClose}
>
Confirm
</Button>
</DialogFooter>
</>
);
}
45 changes: 45 additions & 0 deletions src/app/components/Modals/TransitionModal/StageStart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
Button,
DialogBody,
DialogFooter,
Heading,
} from "@babylonlabs-io/bbn-core-ui";
import { MdLooksTwo } from "react-icons/md";

interface StageStartProps {
onClose: () => void;
}

export function StageStart({ onClose }: StageStartProps) {
return (
<>
<DialogBody className="flex flex-col pb-8 pt-4 text-primary-dark gap-4">
<div className="py-4 flex flex-col items-center gap-4">
<div className="bg-primary-contrast h-20 w-20 flex items-center justify-center">
<MdLooksTwo className="text-5xl" />
</div>
<Heading variant="h4">Transition to Phase 2</Heading>
<p className="text-base text-center">
You are about to transition your phase-1 stake delegation to secure
the phase-2 Babylon PoS blockchain. The transition requires the
association of your Babylon testnet rewards account with your BTC
key as well as your consent to slashing in the case of equivocation.
</p>
</div>
</DialogBody>
<DialogFooter className="flex gap-4">
<Button
variant="outlined"
color="primary"
onClick={onClose}
className="flex-1 text-xs sm:text-base"
>
Cancel
</Button>
<Button variant="contained" className="flex-1 text-xs sm:text-base">
Proceed
</Button>
</DialogFooter>
</>
);
}
109 changes: 109 additions & 0 deletions src/app/components/Modals/TransitionModal/StageStepping.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
Button,
DialogBody,
DialogFooter,
DialogHeader,
Loader,
Text,
} from "@babylonlabs-io/bbn-core-ui";
import { twMerge } from "tailwind-merge";

import { Tick } from "./Tick";

const stepContent = [
"Step 1: Consent to slashing",
"Step 2: Consent to slashing during unbonding ",
"Step 3: BTC-BBN address binding for receiving staking rewards",
"Step 4: Staking transaction registration",
];

interface StageSteppingProps {
onClose: () => void;
onSign: () => void;
step: number;
awaitingResponse?: boolean;
}
const Step = ({
active,
completed,
current,
content,
}: {
active: boolean;
completed: boolean;
current: number;
content: string;
}) => (
<div
className={twMerge(
"p-4 flex flex-row items-center justify-start gap-3 rounded border border-primary-dark/20 bg-secondary-contrast self-stretch",
!active && "opacity-25",
)}
>
{completed ? (
<Tick />
) : (
<div className="rounded-full bg-secondary-main flex h-10 w-10 items-center justify-center">
<Text variant="body1" className="text-secondary-contrast">
{current}
</Text>
</div>
)}
<Text variant="body1" className="text-primary-dark">
{content}
</Text>
</div>
);
export function StageStepping({
onClose,
onSign,
step,
awaitingResponse = false,
}: StageSteppingProps) {
return (
<>
<DialogHeader
title="Transition to Phase 2"
onClose={onClose}
className="text-primary-dark"
/>
<DialogBody className="flex flex-col pb-8 pt-4 text-primary-dark gap-4">
<Text variant="body1" className="text-primary-main">
Please sign the following messages
</Text>
<div className="py-4 flex flex-col items-start gap-6">
{stepContent.map((content, index) => (
<Step
key={content}
completed={step > index + 1}
active={step === index + 1}
current={index + 1}
content={content}
/>
))}
</div>
</DialogBody>
<DialogFooter className="flex gap-4">
<Button
variant="outlined"
color="primary"
onClick={onClose}
className="flex-1 text-xs sm:text-base"
>
Cancel
</Button>
<Button
variant="contained"
className="flex-1 text-xs sm:text-base"
onClick={onSign}
>
{awaitingResponse ? (
<Loader size={16} className="text-white" />
) : (
"Sign"
)}
</Button>
</DialogFooter>
</>
);
}
9 changes: 9 additions & 0 deletions src/app/components/Modals/TransitionModal/Tick.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IoCheckmarkSharp } from "react-icons/io5";

export function Tick() {
return (
<div className="rounded-full bg-primary-light flex h-10 w-10 items-center justify-center">
<IoCheckmarkSharp size={24} className="text-secondary-contrast" />
</div>
);
}
75 changes: 75 additions & 0 deletions src/app/components/Modals/TransitionModal/TransitionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Dialog, MobileDialog } from "@babylonlabs-io/bbn-core-ui";

import { useIsMobileView } from "@/app/hooks/useBreakpoint";

import { StageEnd } from "./StageEnd";
import { StageStart } from "./StageStart";
import { StageStepping } from "./StageStepping";

interface TransitionModalProps {
open: boolean;
onClose: () => void;
onSign: () => void;
stage:
| "start"
| "step-1"
| "step-2"
| "step-3"
| "step-4"
| "pre-end"
| "end";
}
const stageUIMapping = {
start: ({ onClose }: TransitionModalProps) => (
<StageStart onClose={onClose} />
),
"step-1": ({ onClose, onSign }: TransitionModalProps) => (
<StageStepping step={1} onClose={onClose} onSign={onSign} />
),
"step-2": ({ onClose, onSign }: TransitionModalProps) => (
<StageStepping
step={2}
onClose={onClose}
onSign={onSign}
awaitingResponse={true}
/>
),
"step-3": ({ onClose, onSign }: TransitionModalProps) => (
<StageStepping
step={3}
onClose={onClose}
onSign={onSign}
awaitingResponse={true}
/>
),
"step-4": ({ onClose, onSign }: TransitionModalProps) => (
<StageStepping
step={4}
onClose={onClose}
onSign={onSign}
awaitingResponse={true}
/>
),
"pre-end": ({ onClose, onSign }: TransitionModalProps) => (
<StageStepping
step={5}
onClose={onClose}
onSign={onSign}
awaitingResponse={true}
/>
),
end: ({ onClose }: TransitionModalProps) => <StageEnd onClose={onClose} />,
} as const;
export function TransitionModal(props: TransitionModalProps) {
const { open, onClose, stage } = props;
const isMobileView = useIsMobileView();
const DialogComponent = isMobileView ? MobileDialog : Dialog;

const Content = stageUIMapping[stage];

return (
<DialogComponent open={open} onClose={onClose}>
<Content {...props} />
</DialogComponent>
);
}

0 comments on commit 299a1c4

Please sign in to comment.