Skip to content

Commit

Permalink
animated list component
Browse files Browse the repository at this point in the history
  • Loading branch information
jonesmac committed Jan 24, 2025
1 parent f8247cd commit 06b197f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
61 changes: 61 additions & 0 deletions packages/animation/src/AnimatedList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { CardProps } from '@mui/material'
import { Button, Card } from '@mui/material'
import type { Meta, StoryFn } from '@storybook/react'
import { FlexCol } from '@xylabs/react-flexbox'
import React, { useMemo, useState } from 'react'

import type { AnimatedListProps } from './AnimatedList.tsx'
import { AnimatedList } from './AnimatedList.tsx'

const colors = ['red', 'green', 'blue', 'yellow', 'purple']

const TestCard = (props: CardProps) => {
const bgcolor = useMemo(() => colors[Math.floor(Math.random() * colors.length)], [])
return (
<Card
sx={{
width: '300px', height: '50px', display: 'flex', bgcolor,
}}
{...props}
/>
)
}

export default {
title: 'animations/AnimatedList',
component: AnimatedList,
} as Meta

const Template: StoryFn<typeof AnimatedList> = (args) => {
const [index, setIndex] = useState(0)
const [items, setItems] = useState<AnimatedListProps['items']>([])

// Function to add a new item
const addChild = () => {
const newIndex = index + 1
setIndex(newIndex)
setItems([{ child: <TestCard title="key" key={newIndex}>{newIndex}</TestCard>, key: newIndex }, ...items ?? []])
}

// Function to remove the last item
const removeChild = () => {
setItems(items?.slice(0, -1))
}
return (
<FlexCol alignItems="stretch" gap={2}>
<Button onClick={addChild}>Add Item</Button>
<Button onClick={removeChild}>Remove Item</Button>
<FlexCol gap={2}>
<AnimatedList items={items} {...args} />
</FlexCol>
</FlexCol>
)
}

const Default = Template.bind({})
Default.args = {}

const WithChildren = Template.bind({})
WithChildren.args = {}

export { Default, WithChildren }
35 changes: 35 additions & 0 deletions packages/animation/src/AnimatedList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { animated, useTransition } from '@react-spring/web'
import type { ReactNode } from 'react'
import React, { useRef } from 'react'

export interface AnimatedListProps {
items?: { child: ReactNode; key: number }[]
}

export const AnimatedList: React.FC<AnimatedListProps> = ({ items }) => {
const ref = useRef<HTMLDivElement>(null)

const transitions = useTransition(items, {
from: {
opacity: 0, height: 0, transform: 'translateY(-20px)',
},
enter: {
opacity: 1, height: ref.current?.scrollHeight, transform: 'translateY(0px)',

},
leave: {
opacity: 0, height: 0, transform: 'translateY(20px)',
},
keys: items?.map(item => item.key),
})

return (
<>
{transitions((styles, item) => (
<animated.div style={styles} key={item?.key} ref={ref}>
{item?.child}
</animated.div>
))}
</>
)
}
1 change: 1 addition & 0 deletions packages/animation/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './AnimatedList.tsx'
export * from './RotationAnimation.tsx'
export * from './Trail.tsx'

0 comments on commit 06b197f

Please sign in to comment.