Skip to content

Commit

Permalink
add trail animation component
Browse files Browse the repository at this point in the history
  • Loading branch information
jonesmac committed Oct 11, 2024
1 parent 5b68245 commit 51817f5
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
45 changes: 45 additions & 0 deletions packages/animation/src/Trail.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BoxProps, Card } from '@mui/material'

Check warning on line 1 in packages/animation/src/Trail.stories.tsx

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22.3.0)

'BoxProps' is defined but never used
import type { Meta, StoryFn } from '@storybook/react'
import React from 'react'

import type { TrailProps } from './Trail.tsx'
import { Trail } from './Trail.tsx'

const TestCard = () => (
<Card sx={{
width: '300px', height: '300px', display: 'flex', bgcolor: 'green',
}}
/>
)

const testCards = Array.from({ length: 5 }, (_, index) => <TestCard key={index} />)

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

const DefaultProps: TrailProps = {
open: true,
gap: 2,
fullWidth: true,
display: 'flex',
flexDirection: 'row',
}

const Template: StoryFn<typeof Trail> = args => <Trail {...args} />

const Default = Template.bind({})
Default.args = { children: [], ...DefaultProps }

const WithChildren = Template.bind({})
WithChildren.args = { children: testCards, ...DefaultProps }

const WithChildrenProps = Template.bind({})
WithChildrenProps.args = {
children: testCards, ...DefaultProps, flexDirection: 'column', fullWidth: false,
}

export {
Default, WithChildren, WithChildrenProps,
}
38 changes: 38 additions & 0 deletions packages/animation/src/Trail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { BoxProps } from '@mui/material'
import { Box } from '@mui/material'
import { a, useTrail } from '@react-spring/web'
import React, { isValidElement } from 'react'

export interface TrailProps extends BoxProps {
fullWidth?: boolean
open: boolean
}

export const Trail: React.FC<TrailProps> = ({
fullWidth, open, children, ...props
}) => {
// Ensure children is an array for iteration
const childArray = isValidElement(children) ? [children] : (children as React.ReactNode[])
const childArrayWithKey = childArray.map((child, index) => ({ child, key: index }))
const resolvedWidth = fullWidth ? '100%' : 'auto'

const trail = useTrail(childArrayWithKey.length, {
config: {
friction: 200, mass: 5, tension: 2000,
},
from: { opacity: 0, y: 20 },
display: 'flex',
opacity: open ? 1 : 0,
y: open ? 0 : 20,
})

return (
<Box width={resolvedWidth} {...props}>
{trail.map(({ ...style }, index) => (
<a.div key={childArrayWithKey[index].key} style={{ ...style, width: resolvedWidth }}>
<a.div className={`trail-${index}`}>{childArrayWithKey[index].child}</a.div>
</a.div>
))}
</Box>
)
}
1 change: 1 addition & 0 deletions packages/animation/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './RotationAnimation.tsx'
export * from './Trail.tsx'

0 comments on commit 51817f5

Please sign in to comment.