diff --git a/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx b/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx index be4c887a..e455e9b8 100644 --- a/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx +++ b/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx @@ -11,6 +11,8 @@ import { InterestRateField } from "@/src/comps/InterestRateField/InterestRateFie import { LinkTextButton } from "@/src/comps/LinkTextButton/LinkTextButton"; import { RedemptionInfo } from "@/src/comps/RedemptionInfo/RedemptionInfo"; import { Screen } from "@/src/comps/Screen/Screen"; +import { useStoredState } from "@/src/services/StoredState"; +import { FirstTimeOnboardingModal } from "./FirstTimeOnboardingModal"; import { WarningBox } from "@/src/comps/WarningBox/WarningBox"; import { DEBT_SUGGESTIONS, ETH_MAX_RESERVE, MAX_COLLATERAL_DEPOSITS, MIN_DEBT } from "@/src/constants"; import content from "@/src/content"; @@ -91,6 +93,16 @@ export function BorrowScreen() { const [interestRateDelegate, setInterestRateDelegate] = useState
(null); const [agreeToLiquidationRisk, setAgreeToLiquidationRisk] = useState(false); + // First-time user onboarding modal + const { onboardingDismissed, setState: setStoredState } = useStoredState(); + const [onboardingClosed, setOnboardingClosed] = useState(false); + const showOnboarding = !onboardingDismissed && !onboardingClosed; + + const handleOnboardingClose = () => { + setOnboardingClosed(true); + setStoredState({ onboardingDismissed: true }); + }; + const agreeCheckboxId = useId(); const setInterestRateRounded = useCallback((averageInterestRate: Dnum, setValue: (value: string) => void) => { @@ -224,19 +236,24 @@ export function BorrowScreen() { && !insufficientColl; return ( - - {content.borrowScreen.headline( + <> + + + {content.borrowScreen.headline(
+ ); } diff --git a/frontend/app/src/screens/BorrowScreen/FirstTimeOnboardingModal.tsx b/frontend/app/src/screens/BorrowScreen/FirstTimeOnboardingModal.tsx new file mode 100644 index 00000000..084f86c8 --- /dev/null +++ b/frontend/app/src/screens/BorrowScreen/FirstTimeOnboardingModal.tsx @@ -0,0 +1,141 @@ +import { WHITE_LABEL_CONFIG } from "@/src/white-label.config"; +import { css } from "@/styled-system/css"; +import { Button, Modal } from "@liquity2/uikit"; + +export function FirstTimeOnboardingModal({ + onClose, + visible, +}: { + onClose: () => void; + visible: boolean; +}) { + const { mainToken } = WHITE_LABEL_CONFIG.tokens; + const { brandName, links } = WHITE_LABEL_CONFIG.branding; + + return ( + +
+

+ Before opening your first position, here are some important things to know: +

+ +
+ + + + + + + +
+ + +
+
+ ); +} + +function FaqItem({ + title, + description, +}: { + title: string; + description: string; +}) { + return ( +
+

+ {title} +

+

+ {description} +

+
+ ); +} diff --git a/frontend/app/src/services/StoredState.tsx b/frontend/app/src/services/StoredState.tsx index a3477f3d..e5f7496f 100644 --- a/frontend/app/src/services/StoredState.tsx +++ b/frontend/app/src/services/StoredState.tsx @@ -22,6 +22,7 @@ export const StoredStateSchema = v.object({ v.literal("approve-amount"), v.literal("approve-infinite"), ]), + onboardingDismissed: v.optional(v.boolean()), }); type StoredStateType = v.InferOutput; @@ -29,6 +30,7 @@ type StoredStateType = v.InferOutput; const defaultState: StoredStateType = { loanModes: {}, preferredApproveMethod: "permit", + onboardingDismissed: false, }; type StoredStateContext = StoredStateType & {