Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Header component adjustements #357

Merged
merged 24 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5d8343a
Implement `Navigation` component
kpyszkowski Apr 15, 2024
06596ba
Define `Layout` as wrapper route
kpyszkowski Apr 15, 2024
c0b0df3
Implement conditional `ConnectWallet` rendering
kpyszkowski Apr 15, 2024
0c707f7
Remove Ethereum wallet connection button
kpyszkowski Apr 15, 2024
a06c1de
Implement `ConnectWallet`'s presence animation
kpyszkowski Apr 15, 2024
e54282f
Adjust `Header`'s padding
kpyszkowski Apr 16, 2024
5cedbf2
Refactor `Navigation` component
kpyszkowski Apr 17, 2024
dec2bcc
Replace color values with semantic tokens
kpyszkowski Apr 17, 2024
bc41b76
Wrap `Navigation` component with `nav` element
kpyszkowski Apr 17, 2024
5d25c89
Move `Header` outside `main` element
kpyszkowski Apr 17, 2024
b02de09
Update comment to be more descriptive
kpyszkowski Apr 17, 2024
7ce1664
Remove explicit null value in `ConnectWallet`
kpyszkowski Apr 17, 2024
78b0814
Rename hook
kpyszkowski Apr 18, 2024
5ff78eb
Merge branch 'landing-page' into header-navigation
kpyszkowski Apr 18, 2024
66fc680
Adjust navigation items
kpyszkowski Apr 18, 2024
0548299
Merge branch 'landing-page' into header-navigation
kpyszkowski Apr 18, 2024
cc68712
Encaplsulate `NavigationItem` component
kpyszkowski Apr 22, 2024
bea88fc
Define 'navigation' Link theme variant
kpyszkowski Apr 22, 2024
4ffdb22
Encapsulate `NavLink` component into separate file
kpyszkowski Apr 22, 2024
2a9b31a
Move navigation item type definition to types dir
kpyszkowski Apr 22, 2024
856e70a
Merge branch 'landing-page' into header-navigation
kpyszkowski Apr 22, 2024
5393743
Merge branch 'landing-page' into header-navigation
kpyszkowski Apr 23, 2024
d286b0f
Resolve merge errors
kpyszkowski Apr 23, 2024
689154b
Remove `NavigationItem` export
kpyszkowski Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 47 additions & 40 deletions dapp/src/components/Header/ConnectWallet.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import React from "react"
import { Button, HStack, Icon, Tooltip } from "@chakra-ui/react"
import { useWallet } from "#/hooks"
import { useIsHomeRouteActive, useWallet, useWalletContext } from "#/hooks"
import { CurrencyBalance } from "#/components/shared/CurrencyBalance"
import { TextMd } from "#/components/shared/Typography"
import { BitcoinIcon, EthereumIcon } from "#/assets/icons"
import { BitcoinIcon } from "#/assets/icons"
import { Account } from "@ledgerhq/wallet-api-client"
import { CURRENCY_ID_BITCOIN } from "#/constants"
import {
isSupportedBTCAddressType,
logPromiseFailure,
truncateAddress,
} from "#/utils"
import { AnimatePresence, motion, Variants } from "framer-motion"

const containerVariants: Variants = {
hidden: { opacity: 0, y: -48 },
visible: { opacity: 1, y: 0 },
}
Comment on lines +16 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can move containerVariants to theme dir.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep animation related variables coupled together. Will not make it.


const getCustomDataByAccount = (
account?: Account,
Expand All @@ -28,53 +34,54 @@ const getCustomDataByAccount = (
export default function ConnectWallet() {
const {
bitcoin: { account: btcAccount, requestAccount: requestBitcoinAccount },
ethereum: { account: ethAccount, requestAccount: requestEthereumAccount },
} = useWallet()
// TODO: Move `isConnected` to useWallet hook
const { isConnected } = useWalletContext()

const customDataBtcAccount = getCustomDataByAccount(btcAccount)
const customDataEthAccount = getCustomDataByAccount(ethAccount)

const isHomeRoute = useIsHomeRouteActive()

const handleConnectBitcoinAccount = () => {
logPromiseFailure(requestBitcoinAccount())
}

const handleConnectEthereumAccount = () => {
logPromiseFailure(requestEthereumAccount())
}

return (
<HStack spacing={4}>
<HStack display={{ base: "none", md: "flex" }}>
<TextMd color="grey.500">Balance</TextMd>
<CurrencyBalance
currency="bitcoin"
amount={btcAccount?.balance.toString()}
/>
</HStack>
<Tooltip
label="Currently, we support only Legacy or Native SegWit addresses. Please try connecting another address."
placement="top"
isDisabled={
!(btcAccount && !isSupportedBTCAddressType(btcAccount.address))
}
>
<Button
variant="card"
colorScheme={customDataBtcAccount.colorScheme}
leftIcon={<Icon as={BitcoinIcon} boxSize={6} />}
onClick={handleConnectBitcoinAccount}
<AnimatePresence initial={false}>
{(isConnected || !isHomeRoute) && (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, in such cases, we set the condition higher and return null if it does not meet the condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not true with <AnimatePresence /> component. It requires the render condition to be explicitly defined inside it to capture the rerender.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so let's create AnimatePresence as a standalone wrapper with children prop and move there this condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why, it's pointless. It will cause the code to shadow. AnimatePresence as a part of Framer Motion has enough semantic meaning. No need to make it a wrapper.

<HStack
as={motion.div}
variants={containerVariants}
initial="hidden"
animate="visible"
exit="hidden"
spacing={4}
>
{customDataBtcAccount.text}
</Button>
</Tooltip>
<Button
variant="card"
colorScheme={customDataEthAccount.colorScheme}
leftIcon={<Icon as={EthereumIcon} boxSize={6} />}
onClick={handleConnectEthereumAccount}
>
{customDataEthAccount.text}
</Button>
</HStack>
<HStack display={{ base: "none", md: "flex" }}>
<TextMd color="grey.500">Balance</TextMd>
<CurrencyBalance
currency="bitcoin"
amount={btcAccount?.balance.toString()}
/>
</HStack>
<Tooltip
label="Currently, we support only Legacy or Native SegWit addresses. Please try connecting another address."
placement="top"
isDisabled={
!(btcAccount && !isSupportedBTCAddressType(btcAccount.address))
}
>
<Button
variant="card"
colorScheme={customDataBtcAccount.colorScheme}
leftIcon={<Icon as={BitcoinIcon} boxSize={6} />}
onClick={handleConnectBitcoinAccount}
>
{customDataBtcAccount.text}
</Button>
</Tooltip>
</HStack>
)}
</AnimatePresence>
)
}
24 changes: 24 additions & 0 deletions dapp/src/components/Header/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react"
import { Box, BoxProps, HStack, List } from "@chakra-ui/react"
import { NavigationItemType } from "#/types/navigation"
import NavigationItem from "./NavigationItem"

type NavigationProps = BoxProps & {
items: NavigationItemType[]
}

function Navigation(props: NavigationProps) {
const { items, ...restProps } = props

return (
<Box as="nav" {...restProps}>
<HStack as={List} spacing={5} ml={12}>
{items.map((item) => (
<NavigationItem key={item.href} {...item} />
))}
</HStack>
</Box>
)
}

export default Navigation
38 changes: 38 additions & 0 deletions dapp/src/components/Header/Navigation/NavigationItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react"
import {
Box,
ListItem,
ListItemProps,
useMultiStyleConfig,
} from "@chakra-ui/react"
import { motion } from "framer-motion"
import { NavigationItemType } from "#/types/navigation"
import { NavLink } from "../../shared/NavLink"

type NavigationItemProps = ListItemProps & NavigationItemType

function NavigationItem(props: NavigationItemProps) {
const { label, href, ...restProps } = props
const styles = useMultiStyleConfig("Link", { variant: "navigation" })

return (
<ListItem pos="relative" {...restProps}>
<NavLink to={href} sx={styles.container}>
{({ isActive }) => (
<>
{label}
{isActive && (
<Box
as={motion.span}
layoutId="active-route-indicator"
sx={styles.indicator}
/>
)}
</>
)}
</NavLink>
</ListItem>
)
}

export default NavigationItem
1 change: 1 addition & 0 deletions dapp/src/components/Header/Navigation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Navigation } from "./Navigation"
14 changes: 12 additions & 2 deletions dapp/src/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import React from "react"
import { Flex, HStack, Icon } from "@chakra-ui/react"
import { AcreLogo } from "#/assets/icons"
import { routerPath } from "#/router/path"
import { Flex, HStack, Icon } from "@chakra-ui/react"
import { NavigationItemType } from "#/types/navigation"
import ConnectWallet from "./ConnectWallet"
import { Navigation } from "./Navigation"

// TODO: To be adjusted after project pivot/cleanup
const NAVIGATION_ITEMS: NavigationItemType[] = [
{ label: "Season 1", href: routerPath.home },
{ label: "Dashboard", href: routerPath.dashboard },
]

export default function Header() {
return (
<HStack as="header" p={6}>
<HStack as="header" px={10} py={7}>
<Icon as={AcreLogo} w={20} h={12} />
<Navigation items={NAVIGATION_ITEMS} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to pass items props instead of importing navigation items directly in the Navigation component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not. It makes Navigation reusable.
It might not be needed in our particular case but who knows.

<Flex ml="auto">
<ConnectWallet />
</Flex>
Expand Down
16 changes: 16 additions & 0 deletions dapp/src/components/shared/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react"
import {
Link as ChakraLink,
LinkProps as ChakraLinkProps,
} from "@chakra-ui/react"
import {
Link as RouterLink,
LinkProps as RouterLinkProps,
} from "react-router-dom"

type LinkProps = Omit<ChakraLinkProps, "as" | "href"> &
Pick<RouterLinkProps, "to">

export function Link(props: LinkProps) {
return <ChakraLink as={RouterLink} {...props} />
}
Comment on lines +14 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's separate these two components into two files Link for the Link component and NavLink for NavLink

Copy link
Contributor Author

@kpyszkowski kpyszkowski Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref commit: 4ffdb22

21 changes: 21 additions & 0 deletions dapp/src/components/shared/NavLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react"
import {
Link as ChakraLink,
LinkProps as ChakraLinkProps,
} from "@chakra-ui/react"
import {
NavLink as RouterNavLink,
NavLinkProps as RouterNavLinkProps,
} from "react-router-dom"

type NavLinkProps = Omit<ChakraLinkProps, "as" | "href" | "children"> &
Pick<RouterNavLinkProps, "to" | "children">

export function NavLink(props: NavLinkProps) {
const { children, ...restProps } = props
return (
<ChakraLink as={RouterNavLink} {...restProps}>
{children as React.ReactNode}
</ChakraLink>
)
}
1 change: 1 addition & 0 deletions dapp/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export * from "./useTimeout"
export * from "./useCountdown"
export * from "./useActivities"
export * from "./useSize"
export * from "./router"
1 change: 1 addition & 0 deletions dapp/src/hooks/router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useIsActiveRoute"
10 changes: 10 additions & 0 deletions dapp/src/hooks/router/useIsActiveRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { routerPath } from "#/router/path"
import { useLocation } from "react-router-dom"

export const useIsActiveRoute = (route: string) => {
const location = useLocation()

return location.pathname === route
}

export const useIsHomeRouteActive = () => useIsActiveRoute(routerPath.home)
2 changes: 1 addition & 1 deletion dapp/src/router/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react"
import { BrowserRouter, Route, Routes } from "react-router-dom"
import LandingPage from "#/pages/LandingPage"
import Layout from "#/components/shared/Layout"
import ActivityPage from "#/pages/ActivityPage"
import DashboardPage from "#/pages/DashboardPage"
import Layout from "#/components/shared/Layout"
import { routerPath } from "./path"

export function Router() {
Expand Down
38 changes: 34 additions & 4 deletions dapp/src/theme/Link.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { defineStyle, defineStyleConfig } from "@chakra-ui/react"
import { createMultiStyleConfigHelpers, defineStyle } from "@chakra-ui/react"

const baseStyle = defineStyle({
const PARTS = ["container", "indicator"]
const multiStyleConfig = createMultiStyleConfigHelpers(PARTS)

const containerBaseStyle = defineStyle({
fontWeight: "semibold",
fontSize: "sm",
lineHeight: "sm",
Expand All @@ -10,6 +13,33 @@ const baseStyle = defineStyle({
},
})

export const linkTheme = defineStyleConfig({
baseStyle,
const navigationContainerStyles = defineStyle({
display: "block",
fontSize: "md",
lineHeight: "md",
fontWeight: "bold",
marginBottom: 2,
color: "grey.500",
_activeLink: { color: "grey.700" },
})

const navigationIndicatorStyles = defineStyle({
pos: "absolute",
bottom: 0.5,
left: 0,
w: "full",
h: 0.5,
bg: "brand.400",
})

export const linkTheme = multiStyleConfig.defineMultiStyleConfig({
baseStyle: {
container: containerBaseStyle,
},
variants: {
navigation: {
container: navigationContainerStyles,
indicator: navigationIndicatorStyles,
},
},
})
4 changes: 4 additions & 0 deletions dapp/src/types/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type NavigationItemType = {
label: string
href: string
}
Loading