Skip to content

Commit

Permalink
feat: sparkles text
Browse files Browse the repository at this point in the history
  • Loading branch information
wkylin committed Jan 17, 2025
1 parent 7ce5815 commit a36e6ad
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
1 change: 0 additions & 1 deletion src/components/stateless/SlideText/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useEffect, useMemo, useState } from 'react'

Check failure on line 1 in src/components/stateless/SlideText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

ESLint

ESLint: Install the 'eslint' package
import { motion } from 'motion/react'
import { MoveRight, PhoneCall } from 'lucide-react'

const SlideText = ({ text = [] }) => {
const [titleNumber, setTitleNumber] = useState(0)
Expand Down
92 changes: 92 additions & 0 deletions src/components/stateless/SparklesText/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { CSSProperties, ReactElement, useEffect, useState } from 'react'

Check warning on line 1 in src/components/stateless/SparklesText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

Unused import

Unused import specifier ReactElement

Check warning on line 1 in src/components/stateless/SparklesText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

Unused import

Unused import specifier CSSProperties

Check failure on line 1 in src/components/stateless/SparklesText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

ESLint

ESLint: Install the 'eslint' package
import { motion } from 'motion/react'
import clsx from 'clsx'

const SparklesText = ({
text,
colors = { first: '#9E7AFF', second: '#FE8BBB' },
className,
sparklesCount = 10,
...props
}) => {
const [sparkles, setSparkles] = useState([])

useEffect(() => {
const generateStar = () => {
const starX = `${Math.random() * 100}%`
const starY = `${Math.random() * 100}%`
const color = Math.random() > 0.5 ? colors.first : colors.second
const delay = Math.random() * 2
const scale = Math.random() * 1 + 0.3

Check warning on line 20 in src/components/stateless/SparklesText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

Pointless arithmetic expression

Math.random() \* 1 can be replaced with Math.random()
const lifespan = Math.random() * 10 + 5
const id = `${starX}-${starY}-${Date.now()}`
return { id, x: starX, y: starY, color, delay, scale, lifespan }
}

const initializeStars = () => {
const newSparkles = Array.from({ length: sparklesCount }, generateStar)
setSparkles(newSparkles)
}

const updateStars = () => {
setSparkles((currentSparkles) =>
currentSparkles.map((star) => {
if (star.lifespan <= 0) {
return generateStar()
} else {
return { ...star, lifespan: star.lifespan - 0.1 }
}
})
)
}

initializeStars()
const interval = setInterval(updateStars, 100)

return () => clearInterval(interval)
}, [colors.first, colors.second])

return (
<div
className={clsx('text', className)}
{...props}
style={{
'--sparkles-first-color': `${colors.first}`,
'--sparkles-second-color': `${colors.second}`,
}}
>
<span className="relative inline-block">
{sparkles.map((sparkle) => (
<Sparkle key={sparkle.id} {...sparkle} />
))}
<i>{text}</i>
</span>
</div>
)
}

const Sparkle = ({ id, x, y, color, delay, scale }) => {
return (
<motion.svg

Check notice on line 70 in src/components/stateless/SparklesText/index.jsx

View workflow job for this annotation

GitHub Actions / Qodana for JS

Unresolved JSX component

Unresolved component motion.svg
key={id}
className="absolute z-20 pointer-events-none"
initial={{ opacity: 0, left: x, top: y }}
animate={{
opacity: [0, 1, 0],
scale: [0, scale, 0],
rotate: [75, 120, 150],
}}
transition={{ duration: 0.8, repeat: Infinity, delay }}
width="21"
height="21"
viewBox="0 0 21 21"
>
<path
d="M9.82531 0.843845C10.0553 0.215178 10.9446 0.215178 11.1746 0.843845L11.8618 2.72026C12.4006 4.19229 12.3916 6.39157 13.5 7.5C14.6084 8.60843 16.8077 8.59935 18.2797 9.13822L20.1561 9.82534C20.7858 10.0553 20.7858 10.9447 20.1561 11.1747L18.2797 11.8618C16.8077 12.4007 14.6084 12.3916 13.5 13.5C12.3916 14.6084 12.4006 16.8077 11.8618 18.2798L11.1746 20.1562C10.9446 20.7858 10.0553 20.7858 9.82531 20.1562L9.13819 18.2798C8.59932 16.8077 8.60843 14.6084 7.5 13.5C6.39157 12.3916 4.19225 12.4007 2.72023 11.8618L0.843814 11.1747C0.215148 10.9447 0.215148 10.0553 0.843814 9.82534L2.72023 9.13822C4.19225 8.59935 6.39157 8.60843 7.5 7.5C8.60843 6.39157 8.59932 4.19229 9.13819 2.72026L9.82531 0.843845Z"
fill={color}
/>
</motion.svg>
)
}

export default SparklesText
5 changes: 5 additions & 0 deletions src/pages/home/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import BackgroundBoxes from '@stateless/BackgroundBoxes'
import TypeWriter from '@stateless/TypeWriter'
import SlideText from '@stateless/SlideText'
import SparklesCore from '@stateless/Sparkles'
import SparklesText from '@stateless/SparklesText'

import firstImage from '@assets/images/88-300x160.jpg'
import secondImage from '@assets/images/2-300x160.jpg'
Expand Down Expand Up @@ -289,6 +290,10 @@ const Home = () => {
This is something
<SlideText text={['amazing', 'new', 'wonderful', 'beautiful', 'smart']} />
</section>
<section style={{ marginBottom: 15, fontSize: 20 }}>
<SparklesText text="Magic UI" sparklesCount={5} />
</section>

<section style={{ marginBottom: 15, fontSize: 20 }}>
<AutoLink text="foo bar baz http://example.org bar https://github.com/wkylin/pro-react-admin" />
</section>
Expand Down

0 comments on commit a36e6ad

Please sign in to comment.