diff --git a/dapp/.eslintrc b/dapp/.eslintrc
index 441891d36..c6a162b85 100644
--- a/dapp/.eslintrc
+++ b/dapp/.eslintrc
@@ -3,6 +3,15 @@
"extends": ["@thesis-co"],
"rules": {
"import/no-extraneous-dependencies": "off",
- "import/prefer-default-export": "off"
+ "import/prefer-default-export": "off",
+ // TypeScript allows us to declare props that are non-optional internally
+ // but are interpreted as optional externally if they have defaultProps
+ // defined; the following two adjustments disable eslint-plugin-react
+ // checks that predate this ability for TS and that no longer apply.
+ "react/default-props-match-prop-types": [
+ 2,
+ { "allowRequiredDefaults": true }
+ ],
+ "react/require-default-props": [0]
}
}
diff --git a/dapp/src/DApp.tsx b/dapp/src/DApp.tsx
index 085b6fbe8..d87e33642 100644
--- a/dapp/src/DApp.tsx
+++ b/dapp/src/DApp.tsx
@@ -2,7 +2,12 @@ import React from "react"
import { ChakraProvider } from "@chakra-ui/react"
import { useDetectThemeMode } from "./hooks"
import theme from "./theme"
-import { LedgerWalletAPIProvider, WalletContextProvider } from "./contexts"
+import {
+ LedgerWalletAPIProvider,
+ StakingFlowProvider,
+ WalletContextProvider,
+ DocsDrawerContextProvider,
+} from "./contexts"
import Header from "./components/Header"
import Overview from "./components/Overview"
@@ -23,9 +28,13 @@ function DAppProviders() {
return (
-
-
-
+
+
+
+
+
+
+
)
diff --git a/dapp/src/components/DocsDrawer/index.tsx b/dapp/src/components/DocsDrawer/index.tsx
new file mode 100644
index 000000000..2aeb2a0b2
--- /dev/null
+++ b/dapp/src/components/DocsDrawer/index.tsx
@@ -0,0 +1,27 @@
+import React from "react"
+import {
+ Drawer,
+ DrawerBody,
+ DrawerContent,
+ Text,
+ DrawerOverlay,
+ useColorModeValue,
+} from "@chakra-ui/react"
+import { useDocsDrawerContext } from "../../hooks"
+
+export default function DocsDrawer() {
+ const { isOpen, onClose } = useDocsDrawerContext()
+
+ return (
+
+
+ {/* TODO: Set the correct background color */}
+
+
+ {/* TODO: Add a documentation */}
+ Documentation
+
+
+
+ )
+}
diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx
index 8b35a010b..cea1d2589 100644
--- a/dapp/src/components/Header/ConnectWallet.tsx
+++ b/dapp/src/components/Header/ConnectWallet.tsx
@@ -3,7 +3,6 @@ import {
Button,
HStack,
Icon,
- Text,
Tooltip,
useColorModeValue,
} from "@chakra-ui/react"
@@ -15,12 +14,14 @@ import {
useRequestEthereumAccount,
useWalletContext,
} from "../../hooks"
-import { formatSatoshiAmount, truncateAddress } from "../../utils"
+import { truncateAddress } from "../../utils"
+import { TokenBalance } from "../TokenBalance"
+import { TextMd } from "../Typography"
export type ConnectButtonsProps = {
leftIcon: typeof Icon
rightIcon: typeof Icon
- account: Account | undefined
+ account?: Account
requestAccount: () => Promise
}
@@ -61,13 +62,11 @@ export default function ConnectWallet() {
return (
- Balance
-
- {!btcAccount || btcAccount?.balance.isZero()
- ? "0.00"
- : formatSatoshiAmount(btcAccount.balance.toString())}
-
- {BITCOIN.symbol}
+ Balance
+
+
)
diff --git a/dapp/src/components/ModalOverlay/index.tsx b/dapp/src/components/ModalOverlay/index.tsx
new file mode 100644
index 000000000..b4f18e542
--- /dev/null
+++ b/dapp/src/components/ModalOverlay/index.tsx
@@ -0,0 +1,40 @@
+import React, { useEffect, useState } from "react"
+import { Box, useColorModeValue } from "@chakra-ui/react"
+import { useStakingFlowContext } from "../../hooks"
+
+const DELAY = 300
+
+export default function ModalOverlay({ marginTop }: { marginTop?: number }) {
+ const { modalType } = useStakingFlowContext()
+ const [showOverlay, setShowOverlay] = useState(!modalType)
+
+ useEffect(() => {
+ const timeout = setTimeout(
+ () => {
+ setShowOverlay(!!modalType)
+ },
+ // When the modal opens, we should show the sidebar without delay.
+ // However, when the modal disappears, the overlay should disappear with some delay.
+ modalType ? 0 : DELAY,
+ )
+ return () => clearTimeout(timeout)
+ }, [modalType])
+
+ return (
+
+ )
+}
diff --git a/dapp/src/components/Modals/BaseModal.tsx b/dapp/src/components/Modals/BaseModal.tsx
new file mode 100644
index 000000000..1f98f4345
--- /dev/null
+++ b/dapp/src/components/Modals/BaseModal.tsx
@@ -0,0 +1,23 @@
+import React from "react"
+import { Modal, ModalCloseButton, ModalContent } from "@chakra-ui/react"
+import { useStakingFlowContext } from "../../hooks"
+import { HEADER_HEIGHT } from "../Header"
+
+export default function BaseModal({ children }: { children: React.ReactNode }) {
+ const { closeModal } = useStakingFlowContext()
+
+ return (
+
+
+
+ {children}
+
+
+ )
+}
diff --git a/dapp/src/components/Modals/ConnectWalletModal.tsx b/dapp/src/components/Modals/ConnectWalletModal.tsx
new file mode 100644
index 000000000..b36faf402
--- /dev/null
+++ b/dapp/src/components/Modals/ConnectWalletModal.tsx
@@ -0,0 +1,52 @@
+import React from "react"
+import {
+ Button,
+ Image,
+ ModalBody,
+ ModalFooter,
+ ModalHeader,
+ VStack,
+ Text,
+} from "@chakra-ui/react"
+import BaseModal from "./BaseModal"
+import { Currency, RequestAccountParams } from "../../types"
+import { TextMd } from "../Typography"
+
+type ConnectWalletModalProps = {
+ currency: Currency
+ image: string
+ requestAccount: (...params: RequestAccountParams) => Promise
+}
+
+export default function ConnectWalletModal({
+ currency,
+ image,
+ requestAccount,
+}: ConnectWalletModalProps) {
+ return (
+
+
+ {currency.name} account not installed
+
+
+
+
+
+ {currency.name} account is required to make transactions for
+ depositing and staking your {currency.symbol}.
+
+
+
+
+
+
+
+ )
+}
diff --git a/dapp/src/components/Modals/StakeModal.tsx b/dapp/src/components/Modals/StakeModal.tsx
new file mode 100644
index 000000000..581431e08
--- /dev/null
+++ b/dapp/src/components/Modals/StakeModal.tsx
@@ -0,0 +1,93 @@
+import React from "react"
+import {
+ Button,
+ ModalBody,
+ ModalFooter,
+ Flex,
+ Tabs,
+ TabList,
+ Tab,
+ TabPanels,
+ TabPanel,
+ NumberInput,
+ NumberInputField,
+ NumberInputStepper,
+} from "@chakra-ui/react"
+import { useStakingFlowContext } from "../../hooks"
+import BaseModal from "./BaseModal"
+import { TokenBalance } from "../TokenBalance"
+import { BITCOIN } from "../../constants"
+import { TextMd } from "../Typography"
+
+function StakeDetails({
+ text,
+ tokenBalance,
+ usdBalance,
+}: {
+ text: string
+ tokenBalance: string
+ usdBalance: string
+}) {
+ return (
+
+ {text}
+
+
+ )
+}
+
+export default function StakeModal() {
+ const { closeModal } = useStakingFlowContext()
+
+ return (
+
+
+
+
+ Stake
+ {/* TODO: Add a content for unstake tab */}
+ Unstake
+
+
+
+
+ {/* TODO: Create a custom number input component */}
+
+
+
+
+
+ {/* TODO: Use the real data */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/dapp/src/components/Modals/StakingOverviewModal.tsx b/dapp/src/components/Modals/StakingOverviewModal.tsx
new file mode 100644
index 000000000..d54999747
--- /dev/null
+++ b/dapp/src/components/Modals/StakingOverviewModal.tsx
@@ -0,0 +1,67 @@
+import React from "react"
+import {
+ Button,
+ Flex,
+ ModalBody,
+ ModalFooter,
+ ModalHeader,
+ Step,
+ StepDescription,
+ StepIndicator,
+ StepNumber,
+ StepSeparator,
+ StepTitle,
+ Stepper,
+} from "@chakra-ui/react"
+import { useStakingFlowContext } from "../../hooks"
+import BaseModal from "./BaseModal"
+
+const STEPS = [
+ {
+ title: "Sign message",
+ description:
+ "You will sign a gas-free Ethereum message to indicate the address where you'd like to get your stBTC liquid staking token.",
+ },
+ {
+ title: "Deposit BTC",
+ description:
+ "You will make a Bitcoin transaction to deposit and stake your BTC.",
+ },
+]
+
+export default function StakingOverviewModal() {
+ const { setModalType } = useStakingFlowContext()
+
+ return (
+
+ Staking overview
+
+
+ {STEPS.map((step) => (
+
+
+
+
+
+ {step.title}
+ {step.description}
+
+
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/dapp/src/components/Overview/PositionDetails.tsx b/dapp/src/components/Overview/PositionDetails.tsx
index 972db661f..4606692dd 100644
--- a/dapp/src/components/Overview/PositionDetails.tsx
+++ b/dapp/src/components/Overview/PositionDetails.tsx
@@ -1,43 +1,34 @@
import React from "react"
-import {
- Text,
- Button,
- HStack,
- Tooltip,
- Icon,
- useColorModeValue,
- Flex,
-} from "@chakra-ui/react"
-import { BITCOIN, USD } from "../../constants"
-import { Info } from "../../static/icons"
+import { Button, Flex } from "@chakra-ui/react"
+import { BITCOIN } from "../../constants"
+import Staking from "../Staking"
+import { useStakingFlowContext } from "../../hooks"
+import { TokenBalance } from "../TokenBalance"
+import { TextMd } from "../Typography"
export default function PositionDetails() {
+ const { setModalType } = useStakingFlowContext()
+
return (
-
-
- Your positions
-
-
- 34.75
- {BITCOIN.symbol}
-
-
-
- 1.245.148,1
- {USD.symbol}
-
- {/* TODO: Add correct text for tooltip */}
-
-
-
-
+ <>
+
+
+ Your positions
+ {/* TODO: Use the real data */}
+
+
+
+ {/* TODO: Handle click actions */}
+
+
-
- {/* TODO: Handle click actions */}
-
-
-
-
+
+ >
)
}
diff --git a/dapp/src/components/Sidebar/index.tsx b/dapp/src/components/Sidebar/index.tsx
new file mode 100644
index 000000000..b07c592c1
--- /dev/null
+++ b/dapp/src/components/Sidebar/index.tsx
@@ -0,0 +1,31 @@
+import React from "react"
+import { Box, Button, useColorModeValue } from "@chakra-ui/react"
+import { useDocsDrawerContext, useStakingFlowContext } from "../../hooks"
+import DocsDrawer from "../DocsDrawer"
+
+export default function Sidebar({ marginTop }: { marginTop?: number }) {
+ const { modalType } = useStakingFlowContext()
+ const { onOpen } = useDocsDrawerContext()
+
+ return (
+ <>
+
+ {/* TODO: Add a correct content for the sidebar */}
+
+
+
+ >
+ )
+}
diff --git a/dapp/src/components/Staking/index.tsx b/dapp/src/components/Staking/index.tsx
new file mode 100644
index 000000000..b3e42621b
--- /dev/null
+++ b/dapp/src/components/Staking/index.tsx
@@ -0,0 +1,54 @@
+import React from "react"
+import ConnectWalletModal from "../Modals/ConnectWalletModal"
+import StakingOverviewModal from "../Modals/StakingOverviewModal"
+import { useRequestBitcoinAccount, useRequestEthereumAccount, useStakingFlowContext, useWalletContext } from "../../hooks"
+import ModalOverlay from "../ModalOverlay"
+import { HEADER_HEIGHT } from "../Header"
+import Sidebar from "../Sidebar"
+import StakeModal from "../Modals/StakeModal"
+import { BITCOIN, ETHEREUM } from "../../constants"
+import ConnectBTCAccount from "../../static/images/ConnectBTCAccount.png"
+import ConnectETHAccount from "../../static/images/ConnectETHAccount.png"
+
+function Modal() {
+ const { modalType } = useStakingFlowContext()
+ const { btcAccount, ethAccount } = useWalletContext()
+ const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount()
+ const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount()
+
+ if (!modalType) return null
+
+ if (!btcAccount)
+ return (
+
+ )
+
+ if (!ethAccount)
+ return (
+
+ )
+
+ if (modalType === "overview") return
+
+ if (modalType === "stake") return
+}
+
+export default function Staking() {
+ return (
+ <>
+
+ {/* The user has several modals in a flow.
+ Let's use our own modal overlay to prevent the background flickering effect. */}
+
+
+ >
+ )
+}
diff --git a/dapp/src/components/TokenBalance/index.tsx b/dapp/src/components/TokenBalance/index.tsx
new file mode 100644
index 000000000..7d8fcc13e
--- /dev/null
+++ b/dapp/src/components/TokenBalance/index.tsx
@@ -0,0 +1,40 @@
+import React from "react"
+import { HStack, Flex } from "@chakra-ui/react"
+import { Currency } from "../../types"
+import { formatTokenAmount } from "../../utils"
+import { USD } from "../../constants"
+import { TextMd, TextSm } from "../Typography"
+
+type TokenBalanceProps = {
+ currency: Currency
+ tokenBalance: string | number
+ usdBalance?: string
+ desiredDecimals?: number
+ alignItems?: "end" | "start"
+}
+
+export function TokenBalance({
+ currency,
+ tokenBalance,
+ usdBalance,
+ desiredDecimals = 2,
+ alignItems = "end",
+}: TokenBalanceProps) {
+ return (
+
+
+
+ {formatTokenAmount(tokenBalance, currency.decimals, desiredDecimals)}
+
+ {currency.symbol}
+
+ {usdBalance && (
+ // TODO: Set the correct color
+
+ {usdBalance}
+ {USD.symbol}
+
+ )}
+
+ )
+}
diff --git a/dapp/src/contexts/DocsDrawerContext.tsx b/dapp/src/contexts/DocsDrawerContext.tsx
new file mode 100644
index 000000000..f5097fc96
--- /dev/null
+++ b/dapp/src/contexts/DocsDrawerContext.tsx
@@ -0,0 +1,44 @@
+import React, { createContext, useCallback, useMemo, useState } from "react"
+
+type DocsDrawerContextValue = {
+ isOpen: boolean
+ onOpen: () => void
+ onClose: () => void
+}
+
+export const DocsDrawerContext = createContext({
+ isOpen: false,
+ onOpen: () => {},
+ onClose: () => {},
+})
+
+export function DocsDrawerContextProvider({
+ children,
+}: {
+ children: React.ReactNode
+}): React.ReactElement {
+ const [isOpen, setIsOpen] = useState(false)
+
+ const onOpen = useCallback(() => {
+ setIsOpen(true)
+ }, [])
+
+ const onClose = useCallback(() => {
+ setIsOpen(false)
+ }, [])
+
+ const contextValue: DocsDrawerContextValue = useMemo(
+ () => ({
+ isOpen,
+ onOpen,
+ onClose,
+ }),
+ [isOpen, onClose, onOpen],
+ )
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/dapp/src/contexts/StakingFlowContext.tsx b/dapp/src/contexts/StakingFlowContext.tsx
new file mode 100644
index 000000000..a58446787
--- /dev/null
+++ b/dapp/src/contexts/StakingFlowContext.tsx
@@ -0,0 +1,42 @@
+import React, { createContext, useCallback, useMemo, useState } from "react"
+import { ModalType } from "../types"
+
+type StakingFlowContextValue = {
+ modalType: ModalType | undefined
+ closeModal: () => void
+ setModalType: React.Dispatch>
+}
+
+export const StakingFlowContext = createContext({
+ modalType: undefined,
+ setModalType: () => {},
+ closeModal: () => {},
+})
+
+export function StakingFlowProvider({
+ children,
+}: {
+ children: React.ReactNode
+}): React.ReactElement {
+ const [modalType, setModalType] = useState(undefined)
+
+ const closeModal = useCallback(() => {
+ setModalType(undefined)
+ }, [])
+
+ const contextValue: StakingFlowContextValue =
+ useMemo(
+ () => ({
+ modalType,
+ closeModal,
+ setModalType,
+ }),
+ [modalType, closeModal],
+ )
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/dapp/src/contexts/WalletContext.tsx b/dapp/src/contexts/WalletContext.tsx
index f327ce0bd..63fb3faba 100644
--- a/dapp/src/contexts/WalletContext.tsx
+++ b/dapp/src/contexts/WalletContext.tsx
@@ -8,9 +8,12 @@ type WalletContextValue = {
setEthAccount: React.Dispatch>
}
-export const WalletContext = createContext(
- undefined,
-)
+export const WalletContext = createContext({
+ ethAccount: undefined,
+ btcAccount: undefined,
+ setEthAccount: () => {},
+ setBtcAccount: () => {},
+})
export function WalletContextProvider({
children,
@@ -27,7 +30,7 @@ export function WalletContextProvider({
ethAccount,
setEthAccount,
}),
- [btcAccount, setBtcAccount, ethAccount, setEthAccount],
+ [btcAccount, ethAccount],
)
return (
diff --git a/dapp/src/contexts/index.tsx b/dapp/src/contexts/index.tsx
index 3ea3058ed..d05560c99 100644
--- a/dapp/src/contexts/index.tsx
+++ b/dapp/src/contexts/index.tsx
@@ -1,2 +1,4 @@
export * from "./WalletContext"
export * from "./LedgerWalletAPIProvider"
+export * from "./StakingFlowContext"
+export * from "./DocsDrawerContext"
diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts
index 038388476..c6fd499d8 100644
--- a/dapp/src/hooks/index.ts
+++ b/dapp/src/hooks/index.ts
@@ -2,3 +2,5 @@ export * from "./useDetectThemeMode"
export * from "./useRequestBitcoinAccount"
export * from "./useRequestEthereumAccount"
export * from "./useWalletContext"
+export * from "./useStakingFlowContext"
+export * from "./useDocsDrawerContext"
diff --git a/dapp/src/hooks/useDocsDrawerContext.ts b/dapp/src/hooks/useDocsDrawerContext.ts
new file mode 100644
index 000000000..92b03f2d3
--- /dev/null
+++ b/dapp/src/hooks/useDocsDrawerContext.ts
@@ -0,0 +1,14 @@
+import { useContext } from "react"
+import { DocsDrawerContext } from "../contexts"
+
+export function useDocsDrawerContext() {
+ const context = useContext(DocsDrawerContext)
+
+ if (!context) {
+ throw new Error(
+ "DocsDrawerContext used outside of DocsDrawerContext component",
+ )
+ }
+
+ return context
+}
diff --git a/dapp/src/hooks/useRequestBitcoinAccount.ts b/dapp/src/hooks/useRequestBitcoinAccount.ts
index 971a3f9ef..b9cce07c2 100644
--- a/dapp/src/hooks/useRequestBitcoinAccount.ts
+++ b/dapp/src/hooks/useRequestBitcoinAccount.ts
@@ -5,12 +5,12 @@ import { UseRequestAccountReturn } from "../types"
import { WalletContext } from "../contexts"
export function useRequestBitcoinAccount(): UseRequestAccountReturn {
- const walletContext = useContext(WalletContext)
+ const { setBtcAccount } = useContext(WalletContext)
const { account, requestAccount } = useRequestAccount()
useEffect(() => {
- walletContext?.setBtcAccount(account || undefined)
- }, [account, walletContext])
+ setBtcAccount(account || undefined)
+ }, [account, setBtcAccount])
const requestBitcoinAccount = useCallback(async () => {
await requestAccount({ currencyIds: [CURRENCY_ID_BITCOIN] })
diff --git a/dapp/src/hooks/useRequestEthereumAccount.ts b/dapp/src/hooks/useRequestEthereumAccount.ts
index ebeb1f268..c780aea20 100644
--- a/dapp/src/hooks/useRequestEthereumAccount.ts
+++ b/dapp/src/hooks/useRequestEthereumAccount.ts
@@ -5,12 +5,12 @@ import { UseRequestAccountReturn } from "../types"
import { WalletContext } from "../contexts"
export function useRequestEthereumAccount(): UseRequestAccountReturn {
- const walletContext = useContext(WalletContext)
+ const { setEthAccount } = useContext(WalletContext)
const { account, requestAccount } = useRequestAccount()
useEffect(() => {
- walletContext?.setEthAccount(account || undefined)
- }, [account, walletContext])
+ setEthAccount(account || undefined)
+ }, [account, setEthAccount])
const requestEthereumAccount = useCallback(async () => {
await requestAccount({ currencyIds: [CURRENCY_ID_ETHEREUM] })
diff --git a/dapp/src/hooks/useStakingFlowContext.ts b/dapp/src/hooks/useStakingFlowContext.ts
new file mode 100644
index 000000000..870e15f71
--- /dev/null
+++ b/dapp/src/hooks/useStakingFlowContext.ts
@@ -0,0 +1,14 @@
+import { useContext } from "react"
+import { StakingFlowContext } from "../contexts"
+
+export function useStakingFlowContext() {
+ const context = useContext(StakingFlowContext)
+
+ if (!context) {
+ throw new Error(
+ "StakingFlowContext used outside of StakingFlowContext component",
+ )
+ }
+
+ return context
+}
diff --git a/dapp/src/static/images/ConnectBTCAccount.png b/dapp/src/static/images/ConnectBTCAccount.png
new file mode 100644
index 000000000..deff3c0cc
Binary files /dev/null and b/dapp/src/static/images/ConnectBTCAccount.png differ
diff --git a/dapp/src/static/images/ConnectETHAccount.png b/dapp/src/static/images/ConnectETHAccount.png
new file mode 100644
index 000000000..e1ad2974d
Binary files /dev/null and b/dapp/src/static/images/ConnectETHAccount.png differ
diff --git a/dapp/src/theme/Drawer.ts b/dapp/src/theme/Drawer.ts
new file mode 100644
index 000000000..bdb9956e9
--- /dev/null
+++ b/dapp/src/theme/Drawer.ts
@@ -0,0 +1,11 @@
+import { ComponentSingleStyleConfig } from "@chakra-ui/react"
+
+const Drawer: ComponentSingleStyleConfig = {
+ baseStyle: {
+ dialogContainer: {
+ zIndex: "drawer",
+ },
+ },
+}
+
+export default Drawer
diff --git a/dapp/src/theme/Stepper.ts b/dapp/src/theme/Stepper.ts
new file mode 100644
index 000000000..79f438195
--- /dev/null
+++ b/dapp/src/theme/Stepper.ts
@@ -0,0 +1,33 @@
+import { mode } from "@chakra-ui/theme-tools"
+import type { StyleFunctionProps } from "@chakra-ui/styled-system"
+import { ComponentSingleStyleConfig } from "@chakra-ui/react"
+
+const Stepper: ComponentSingleStyleConfig = {
+ baseStyle: {
+ indicator: {
+ borderRadius: 4,
+ fontWeight: "500",
+ },
+ step: {
+ gap: 6,
+ },
+ },
+ variants: {
+ basic: (props: StyleFunctionProps) => ({
+ indicator: {
+ "&[data-status=complete]": {
+ // TODO: Set the correct color
+ background: mode("black", "purple")(props),
+ },
+ },
+ separator: {
+ "&[data-status=complete]": {
+ // TODO: Set the correct color
+ background: mode("black", "purple")(props),
+ },
+ },
+ }),
+ },
+}
+
+export default Stepper
diff --git a/dapp/src/theme/Tabs.ts b/dapp/src/theme/Tabs.ts
new file mode 100644
index 000000000..f864f610b
--- /dev/null
+++ b/dapp/src/theme/Tabs.ts
@@ -0,0 +1,30 @@
+import { mode } from "@chakra-ui/theme-tools"
+import type { StyleFunctionProps } from "@chakra-ui/styled-system"
+import { ComponentSingleStyleConfig } from "@chakra-ui/react"
+
+const Tabs: ComponentSingleStyleConfig = {
+ variants: {
+ underline: (props: StyleFunctionProps) => ({
+ tab: {
+ padding: 0,
+ fontWeight: 700,
+ borderBottom: "4px solid",
+ borderColor: "transparent",
+ background: "transparent",
+ _selected: {
+ // TODO: Set the correct color
+ color: mode("black", "black")(props),
+ borderColor: mode("#F34900", "#F34900")(props),
+ },
+ // TODO: Set the correct color
+ color: mode("#675E60", "#675E60")(props),
+ },
+ tablist: {
+ borderBottom: "none",
+ gap: 8,
+ },
+ }),
+ },
+}
+
+export default Tabs
diff --git a/dapp/src/theme/index.ts b/dapp/src/theme/index.ts
index de73c60c8..41f5418b0 100644
--- a/dapp/src/theme/index.ts
+++ b/dapp/src/theme/index.ts
@@ -2,7 +2,10 @@ import { StyleFunctionProps, Tooltip, extendTheme } from "@chakra-ui/react"
import { mode } from "@chakra-ui/theme-tools"
import Button from "./Button"
import Switch from "./Switch"
-import { colors, fontSizes, fontWeights, lineHeights } from "./utils"
+import Drawer from "./Drawer"
+import Stepper from "./Stepper"
+import Tabs from "./Tabs"
+import { colors, fontSizes, fontWeights, lineHeights, zIndices } from "./utils"
// Currently, there is no possibility to set all tooltips with hasArrow by defaultProps.
// Let's override the defaultProps as follows.
@@ -13,6 +16,7 @@ const defaultTheme = {
fontSizes,
fontWeights,
lineHeights,
+ zIndices,
styles: {
global: (props: StyleFunctionProps) => ({
body: {
@@ -24,6 +28,9 @@ const defaultTheme = {
components: {
Button,
Switch,
+ Drawer,
+ Stepper,
+ Tabs,
},
}
diff --git a/dapp/src/theme/utils/index.ts b/dapp/src/theme/utils/index.ts
index 9f377b3e3..a125c015d 100644
--- a/dapp/src/theme/utils/index.ts
+++ b/dapp/src/theme/utils/index.ts
@@ -1,2 +1,3 @@
export * from "./colors"
+export * from "./zIndices"
export * from "./fonts"
diff --git a/dapp/src/theme/utils/zIndices.ts b/dapp/src/theme/utils/zIndices.ts
new file mode 100644
index 000000000..b141510db
--- /dev/null
+++ b/dapp/src/theme/utils/zIndices.ts
@@ -0,0 +1,17 @@
+export const zIndices = {
+ hide: -1,
+ auto: "auto",
+ base: 0,
+ docked: 10,
+ dropdown: 1000,
+ sticky: 1100,
+ banner: 1200,
+ overlay: 1300,
+ modal: 1400,
+ sidebar: 1450,
+ drawer: 1470,
+ popover: 1500,
+ skipLink: 1600,
+ toast: 1700,
+ tooltip: 1800,
+}
diff --git a/dapp/src/types/index.ts b/dapp/src/types/index.ts
index 1e77e81e7..32b259c7f 100644
--- a/dapp/src/types/index.ts
+++ b/dapp/src/types/index.ts
@@ -1,2 +1,3 @@
export * from "./ledger-live-app"
export * from "./currency"
+export * from "./staking"
diff --git a/dapp/src/types/ledger-live-app.ts b/dapp/src/types/ledger-live-app.ts
index c63368d3e..1fa680d07 100644
--- a/dapp/src/types/ledger-live-app.ts
+++ b/dapp/src/types/ledger-live-app.ts
@@ -1,6 +1,6 @@
import { WalletAPIClient } from "@ledgerhq/wallet-api-client"
-type RequestAccountParams = Parameters
+export type RequestAccountParams = Parameters
export type UseRequestAccountReturn = {
requestAccount: (...params: RequestAccountParams) => Promise
diff --git a/dapp/src/types/staking.ts b/dapp/src/types/staking.ts
new file mode 100644
index 000000000..38c5d8098
--- /dev/null
+++ b/dapp/src/types/staking.ts
@@ -0,0 +1 @@
+export type ModalType = "overview" | "stake"
diff --git a/dapp/src/utils/numbers.ts b/dapp/src/utils/numbers.ts
index dcd077dfd..5e44e49db 100644
--- a/dapp/src/utils/numbers.ts
+++ b/dapp/src/utils/numbers.ts
@@ -15,6 +15,10 @@ export function bigIntToUserAmount(
fixedPointDecimals: number,
desiredDecimals = 2,
): string {
+ if (fixedPoint === BigInt(0)) {
+ return `0.${"0".repeat(desiredDecimals)}`
+ }
+
const fixedPointDesiredDecimalsAmount =
fixedPoint /
10n ** BigInt(Math.max(1, fixedPointDecimals - desiredDecimals))