Installation
Follow these simple steps to add MosaicUI components to your React project:
Steps
1. Choose a Component
Browse the components library and select the component you want to use.
2. Install Dependencies (If Required)
Navigate to the code tab of the component to see the installation instructions for any required dependencies.
Some components rely on additional packages like react-three-fiber, or framer-motion. Only install these when needed.
Terminal / Command Propmpt
npm install react-thee-fiber 3. Copy the Code
Each component provides a code tab containing the component file and a corresponding CSS module.
3.1. Copy the Component File
Copy the component code into your reusable components folder in your project (For example: /src/components/)
decrypting-text-animation.jsx
import { memo, useEffect, useMemo, useState } from "react";
import styles from "./decrypting-text-animation.module.css";
const random = (n = 1) => {
return Math.floor(Math.random() * n);
};
const DecryptingTextAnimation = (props) => {
const {
text,
speed = 50,
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%&*-+?",
} = props;
const letterVariants = ["outlined", "filled"];
const getRandomLetterVariant = () => {
return letterVariants[random(letterVariants.length)];
};
const getTextMappings = () => {
return (
text
?.split(" ")
.filter(Boolean)
.map(word => (
word
.split("")
.map((letter) => ({
letter,
variant: getRandomLetterVariant(),
index: random(charset.length),
}))
))
);
};
const [currentText, setCurrentText] = useState(text);
const [textMapping, setTextMapping] = useState(getTextMappings);
const shuffledCharset = useMemo(() => {
return charset.split("").sort(() => (
random(5) - random(5)
)).join("");
}, [charset, text]);
useEffect(() => {
const intervalId = setInterval(() => {
setTextMapping((prev) => {
return prev.map(word => (
word.map(entry => {
const isDone = entry.letter === shuffledCharset[entry.index];
return {
...entry,
variant: isDone ? "" : getRandomLetterVariant(),
index: isDone ? (
entry.index
) : (
(entry.index + 1) % shuffledCharset.length
)
};
})
))
});
const isDone = textMapping.flat().every(entry => {
return entry.letter === shuffledCharset[entry.index];
});
if (isDone) {
clearInterval(intervalId);
return;
}
}, speed);
return () => {
clearInterval(intervalId);
};
}, [shuffledCharset, textMapping, speed]);
if (currentText !== text) {
setCurrentText(text);
setTextMapping(getTextMappings());
}
return (
<span
aria-label={currentText}
className={styles["decrypting-text"]}
>
{
textMapping.map((word, wordIndex, arr) => (
<>
<span
aria-hidden={true}
className={styles["word"]}
>
{word.map((letter) => {
return (
<span
aria-hidden={true}
className={[
styles["letter"],
styles[`letter-${letter.variant}`]
].join(" ")}
>
{shuffledCharset[letter.index]}
</span>
);
})}
</span>
{wordIndex !== (arr.length - 1) && (
<span aria-hidden={true}>
</span>
)}
</>
))
}
</span>
)
};
export default memo(DecryptingTextAnimation); 3.2. Copy the CSS Module File
Copy the associated CSS module file into the same folder:
decrypting-text-animation.module.css
.decrypting-text {
.word {
white-space: nowrap;
word-break: keep-all;
.letter {
display: inline-block;
font: inherit;
transition: all 100ms ease-in-out;
&.letter-filled {
background: currentColor;
}
&.letter-outlined {
box-shadow: inset 0 0 1px 1px currentColor;
}
}
}
} Using CSS Modules ensures:
- Scoped styles, preventing class name collisions
- Seamless integration with React components
4. Use the Component in Your Project
Import the component into your React app and render it. Follow the example code provided with the component, and check the Props section to see which props are supported for customization.
decrypting-text-animation-preview.jsx
import DecryptingTextAnimation from "@/components/text-effects/decrypting-text-animation/decrypting-text-animation";
/* keep text on center */
const wrapperStyles = {
textAlign: "center",
padding: "24px",
textWrap: "balance",
};
const DecryptingTextAnimationPreview = () => {
return (
<div style={wrapperStyles}>
<p style={{
fontFamily: "monospace",
fontSize: "1.5rem",
}}>
Beyond the encrypted noise lives {" "}
<strong>
<DecryptingTextAnimation
text="Pure Awareness"
speed={50}
/>
</strong>
</p>
</div>
);
};
export default DecryptingTextAnimationPreview;