Skip to content

Commit

Permalink
Activities bar - added carousel (#287)
Browse files Browse the repository at this point in the history
> Closes: #225 

---

### Implement a carousel component

---

### _What was done:_

- Creating a responsive carousel component for the activities card
- Added packages: `react-slick, ver. ^0.30.2` | `@types/react-slick:
"^0.23.13"`
React-slick is a carousel component built with React. It is a react port
of a slick carousel: https://kenwheeler.github.io/slick/.
  The first release was in 2015, the last release - 2 weeks ago. 
  Based on MIT license. 
  Weekly downloads: 1,071,550
  Unpacked Size only: 815 kB
  Stars on GitHub: 11.5k 
  Docs: https://react-slick.neostack.com/
  More details: https://www.npmjs.com/package/react-slick
  Repository: https://github.com/akiran/react-slick
- Changed file structure of ActivityBar
- Added SimpleGrid area to OverviewPage
- Separating DocsButton in OverviewPage.


---

### _Preview:_
<img width="1569" alt="activities-carousel"
src="https://github.com/thesis/acre/assets/28560653/90ddde69-7f11-4c97-901f-16b2c024e23e">

---

### _Additional info:_
 - If there are fewer cards, the carousel arrows are hidden.
- If the user removes a card, the carousel component is refreshed in the
background for correct width conversion.
- If the last element is removed, the carousel is moved to the previous
element to improve user experience.
- The activity details page will be changed in another story, according
to the design we are waiting for.
  • Loading branch information
ioay authored Apr 9, 2024
2 parents 014c33e + a6ba5d6 commit bd4f25f
Show file tree
Hide file tree
Showing 27 changed files with 607 additions and 123 deletions.
2 changes: 2 additions & 0 deletions dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@sentry/react": "^7.98.0",
"@sentry/types": "^7.102.0",
"@tanstack/react-table": "^8.11.3",
"@types/react-slick": "^0.23.13",
"axios": "^1.6.7",
"ethers": "^6.10.0",
"formik": "^2.4.5",
Expand All @@ -34,6 +35,7 @@
"react-number-format": "^5.3.1",
"react-redux": "^9.1.0",
"react-router-dom": "^6.22.0",
"react-slick": "^0.30.2",
"recharts": "^2.12.0"
},
"devDependencies": {
Expand Down
66 changes: 66 additions & 0 deletions dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from "react"
import { ArrowUpRight } from "#/assets/icons"
import { Box, Icon } from "@chakra-ui/react"
import { Variants, motion } from "framer-motion"
import { chakraUnitToPx } from "#/theme/utils"

const arrowUpVariants: Variants = {
initial: {
x: 0,
y: -5,
},
animate: (boxSizePx: number) => ({
x: [0, boxSizePx],
y: [-5, -boxSizePx],
transition: {
duration: 0.4,
ease: "easeInOut",
},
}),
}

const arrowBottomVariants: Variants = {
initial: (boxSizePx: number) => ({
x: -boxSizePx,
y: boxSizePx,
}),
animate: (boxSizePx: number) => ({
x: [-boxSizePx, 0],
y: [boxSizePx, -5],
transition: {
duration: 0.4,
ease: "easeInOut",
},
}),
}

type ArrowUpRightAnimatedIconProps = {
boxSize?: number
color?: string
}

export function ArrowUpRightAnimatedIcon({
boxSize = 4,
color = "brand.400",
}: ArrowUpRightAnimatedIconProps) {
const boxSizePx = chakraUnitToPx(boxSize)
return (
<Box pos="relative" boxSize={boxSize} overflow="hidden">
{[
{ id: "arrow-up", variants: arrowUpVariants },
{ id: "arrow-bottom", variants: arrowBottomVariants },
].map(({ id, variants }) => (
<Box
key={id}
pos="absolute"
as={motion.div}
boxSize={boxSize}
custom={boxSizePx}
variants={variants}
>
<Icon as={ArrowUpRight} boxSize={boxSize} color={color} />
</Box>
))}
</Box>
)
}
1 change: 1 addition & 0 deletions dapp/src/assets/icons/animated/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ArrowUpRightAnimatedIcon"
13 changes: 13 additions & 0 deletions dapp/src/components/GlobalStyles/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ export default function GlobalStyles() {
font-weight: 900;
font-style: normal;
}
// React-slick package: Chakra-ui with react-slick package doesn't
// generate flex style for auto-generated slick-track wrapper.
// Instead of importing default styles for react-slick carousel
// we only add what we need - flex for the .slick-track.
.slick-track {
display: flex;
}
// React-slick package: Hiding arrows instead of disabling them in case
// when carousel is not fully completed by slides.
[data-id="slick-arrow-prev"]:disabled:has(~ [data-id="slick-arrow-next"]:disabled),
[data-id="slick-arrow-prev"]:disabled ~ [data-id="slick-arrow-next"]:disabled{
display: none;
}
`}
/>
)
Expand Down
35 changes: 0 additions & 35 deletions dapp/src/components/shared/ActivityBar/index.tsx

This file was deleted.

25 changes: 0 additions & 25 deletions dapp/src/components/shared/ActivityBar/mock-activities.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,48 @@ import {
Tooltip,
CloseButton,
} from "@chakra-ui/react"
import { useLocation } from "react-router-dom"
import { ActivityInfo, LocationState } from "#/types"
import { capitalize } from "#/utils"
import { useNavigate } from "react-router-dom"
import { ActivityInfo } from "#/types"
import { ChevronRightIcon } from "#/assets/icons"
import { CurrencyBalance } from "#/components/shared/CurrencyBalance"
import StatusInfo from "#/components/shared/StatusInfo"
import { TextSm } from "#/components/shared/Typography"
import ActivityCardContainer from "./ActivityCardContainer"
import { routerPath } from "#/router/path"
import { useActivities } from "#/hooks"
import { ActivityCardWrapper } from "./ActivityCardWrapper"

type ActivityCardType = CardProps & {
activity: ActivityInfo
onRemove: (txHash: string) => void
onRemove: (activity: ActivityInfo) => void
}

function ActivityCard({ activity, onRemove }: ActivityCardType) {
const state = useLocation().state as LocationState | null
const isActive = state ? activity.txHash === state.activity.txHash : false
const isCompleted = activity.status === "completed"
export function ActivityCard({ activity, onRemove }: ActivityCardType) {
const navigate = useNavigate()
const { isCompleted, isSelected } = useActivities()

const isActivitySelected = isSelected(activity)
const isActivityCompleted = isCompleted(activity)

const onClick = useCallback(() => {
navigate(`${routerPath.activity}/${activity.txHash}`)
}, [activity.txHash, navigate])

const onClose = useCallback(
(event: React.MouseEvent) => {
event.preventDefault()
if (activity.txHash) {
onRemove(activity.txHash)
event.stopPropagation()
if (activity) {
onRemove(activity)
}
},
[onRemove, activity.txHash],
[activity, onRemove],
)

return (
<ActivityCardContainer isCompleted={isCompleted} isActive={isActive}>
<ActivityCardWrapper
isCompleted={isActivityCompleted}
isActive={isActivitySelected}
onClick={onClick}
>
<CardHeader p={0} w="100%">
<HStack justifyContent="space-between">
<CurrencyBalance
Expand All @@ -49,23 +60,23 @@ function ActivityCard({ activity, onRemove }: ActivityCardType) {
balanceFontWeight="black"
symbolFontWeight="medium"
/>
{isCompleted ? (
{isActivityCompleted ? (
<Tooltip label="Remove" placement="top">
<CloseButton size="sm" onClick={onClose} />
</Tooltip>
) : (
<Icon
as={ChevronRightIcon}
boxSize={5}
color={isActive ? "gold.700" : "grey.400"}
_hover={isActive ? { color: "gold.700" } : undefined}
color={isActivityCompleted ? "gold.700" : "grey.400"}
_hover={isActivityCompleted ? { color: "gold.700" } : undefined}
/>
)}
</HStack>
</CardHeader>
<CardBody p={0}>
<TextSm fontWeight="semibold" marginBottom={4}>
{capitalize(activity.action)}
<CardBody p={0} pb={4}>
<TextSm fontWeight="semibold" textTransform="capitalize">
{activity.action}
</TextSm>
</CardBody>
<CardFooter p={0}>
Expand All @@ -76,8 +87,6 @@ function ActivityCard({ activity, onRemove }: ActivityCardType) {
fontWeight="medium"
/>
</CardFooter>
</ActivityCardContainer>
</ActivityCardWrapper>
)
}

export default ActivityCard
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react"
import { CardProps, Card } from "@chakra-ui/react"

type ActivityCardContainerProps = CardProps & {
isCompleted: boolean
isActive: boolean
type ActivityCardWrapperProps = CardProps & {
children: React.ReactNode
isCompleted: boolean
isActive?: boolean
}

const completedStyles = {
Expand Down Expand Up @@ -34,18 +34,19 @@ const activeStyles = {
},
}

function ActivityCardContainer({
export function ActivityCardWrapper({
isActive,
isCompleted,
children,
...props
}: ActivityCardContainerProps) {
}: ActivityCardWrapperProps) {
return (
<Card
{...props}
width={64}
paddingX={5}
padding={3}
w={64}
mr={3}
px={5}
p={3}
cursor="pointer"
borderWidth={1}
borderColor="gold.100"
_hover={{
Expand All @@ -55,10 +56,9 @@ function ActivityCardContainer({
}}
{...(isActive && activeStyles)}
{...(isCompleted && completedStyles)}
{...props}
>
{children}
</Card>
)
}

export default ActivityCardContainer
1 change: 1 addition & 0 deletions dapp/src/components/shared/ActivityCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ActivityCard"
33 changes: 33 additions & 0 deletions dapp/src/components/shared/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { forwardRef } from "react"
import { FlexProps, Flex } from "@chakra-ui/react"
import Slider, { Settings as SliderProps } from "react-slick"

const carouselSettings: SliderProps = {
dots: false,
infinite: false,
draggable: false,
variableWidth: true,
speed: 500,
slidesToShow: 12,
slidesToScroll: 1,
}

type CarouselProps = FlexProps &
SliderProps & {
children: React.ReactNode
}

export const Carousel = forwardRef<HTMLInputElement, CarouselProps>(
(props, ref) => (
<Flex
as={Slider}
ref={ref}
// overflow="hidden" is required to hide the items outside the viewport.
overflow="hidden"
{...carouselSettings}
{...props}
>
{props.children}
</Flex>
),
)
1 change: 1 addition & 0 deletions dapp/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export * from "./useInitApp"
export * from "./useCurrencyConversion"
export * from "./useDepositTelemetry"
export * from "./useFetchBTCPriceUSD"
export * from "./useActivities"
export * from "./useFetchBTCBalance"
export * from "./useSize"
Loading

0 comments on commit bd4f25f

Please sign in to comment.