Skip to content

Instantly share code, notes, and snippets.

@rynbyjn
Created December 1, 2023 23:50
Show Gist options
  • Save rynbyjn/96e4c48640d6cf6d11324b3ef995f3cc to your computer and use it in GitHub Desktop.
Save rynbyjn/96e4c48640d6cf6d11324b3ef995f3cc to your computer and use it in GitHub Desktop.
Atom CSS animation React component
import { keyframes } from '@emotion/react'
import styled from '../../constants/theme'
interface AtomProps {
size: number
}
const Atom: React.FC<Partial<AtomProps>> = ({ size = 50 }) => {
return (
<AtomContainer size={size}>
<Electron size={size} />
<Electron size={size} />
<Electron size={size} />
<CenterDot size={size} />
</AtomContainer>
)
}
const AtomContainer = styled.div<AtomProps>(({ size }) => ({
alignItems: 'center',
display: 'flex',
height: size,
justifyContent: 'center',
position: 'relative',
width: size,
}))
const electron1Animation = keyframes({
'0%': { transform: 'rotateY(60deg) rotateX(-60deg) rotate(0)' },
'100%': { transform: 'rotateY(60deg) rotateX(-60deg) rotate(360deg)' },
})
const electron2Animation = keyframes({
'0%': { transform: 'rotateY(-60deg) rotateX(-60deg) rotate(0)' },
'100%': { transform: 'rotateY(-60deg) rotateX(-60deg) rotate(360deg)' },
})
const electron3Animation = keyframes({
'0%': { transform: 'rotateY(75deg) rotateX(0) rotate(180deg)' },
'100%': { transform: 'rotateY(75deg) rotateX(0) rotate(540deg)' },
})
const Electron = styled.div<AtomProps>(({ size, theme }) => ({
'&::before': {
boxShadow: `0 1px ${theme.background} inset, 0 1px ${theme.background}`,
content: '""',
display: 'block',
position: 'absolute',
width: size * 0.4,
height: size / 8,
borderRadius: '50%',
background: theme.background,
top: 0,
left: 0,
},
'&:nth-of-type(2)': {
animation: `${electron2Animation} 1s linear infinite`,
transform: 'rotateY(-60deg) rotateX(-60deg) rotate(0)',
},
'&:nth-of-type(3)': {
animation: `${electron3Animation} 1s linear infinite`,
transform: 'rotateY(75deg) rotateX(0) rotate(180deg)',
},
animation: `${electron1Animation} 1s linear infinite`,
border: `2px solid ${theme.primary}`,
borderRadius: size * 0.75,
height: size,
position: 'absolute',
transform: 'rotateY(60deg) rotateX(-60deg) rotate(0)',
width: size,
}))
const CenterDot = styled.div<AtomProps>(({ size, theme }) => ({
backgroundColor: theme.primary,
borderRadius: '50%',
height: size / 10,
position: 'absolute',
width: size / 10,
}))
export default Atom
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment