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. Installation
Navigate to the Code tab of the selected component to view installation instructions.
There are two ways to install the component in your React project: CLI or Manual. Click on one of the options below and follow the instructions.
3. Install via CLI
Run the provided command from your project root directory (the folder containing package.json). This will automatically add the component code to your specified components directory.
Terminal / Console
# npx mosaicui-cli@latest <component-type>/<component-name>
npx mosaicui-cli@latest backgrounds/classic-dots-pattern-background 4. Use the Component in Your Project
Import the installed 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.
classic-dots-pattern-background-preview.jsx
import ClassicDotsPatternBackground from "@/components/backgrounds/classic-dots-pattern-background/classic-dots-pattern-background";
const ClassicDotsPatternBackgroundPreview = () => {
return (
<ClassicDotsPatternBackground
variant="random"
dotColor="#7a80dd"
style={{
width: "100%",
height: "100%",
}}
wrapperProps = {{
style: {
display: "grid",
placeItems: "center",
height: "100%"
}
}}
>
<h2>
Dot Pattern Background
</h2>
</ClassicDotsPatternBackground>
);
};
export default ClassicDotsPatternBackgroundPreview; 3. Install Dependencies (If Required)
Some components rely on additional packages like react-three-fiber or framer-motion. Only install these when needed.
Terminal / Console
npm install react-thee-fiber 4. Copy the Code
Each component provides a code tab containing the component file and a corresponding CSS module.
4.1. Copy the Component File
Copy the component code into your reusable components folder in your project (For example: /src/components/)
classic-dots-pattern-background.jsx
import { memo, useState, useRef, useMemo, useCallback, useEffect, useLayoutEffect } from "react";
import styles from "./classic-dots-pattern-background.module.css";
const ClassicDotsPatternBackground = (props) => {
const {
children,
variant = "standard",
dotColor = "rgb(255, 255, 255)",
dotScale = 1,
gap = 4,
// radial variant configuration props
radialDirection = "in",
radialScale = 0.25,
// random variant configuration prop
density = 0.5,
// generic props
className = "",
wrapperTagName = "div",
wrapperProps = {},
...restProps
} = props;
const {
className: wrapperClassName = "",
...restWrapperProps
} = wrapperProps;
const Wrapper = wrapperTagName || "div";
const containerRef = useRef(null);
const canvasRef = useRef(null);
const [mounted, setMounted] = useState(false);
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const { devicePixelRatio, canvasWidth, canvasHeight } = useMemo(() => {
const devicePixelRatio = Math.max(1, globalThis.devicePixelRatio || 1);
return {
devicePixelRatio,
canvasWidth: width * devicePixelRatio,
canvasHeight: height * devicePixelRatio,
};
}, [width, height]);
const _dotColor = useMemo(() => {
const canvas = document.createElement("canvas");
canvas.width = canvas.height = 1;
const ctx = canvas.getContext("2d");
ctx.fillStyle = dotColor;
ctx.fillRect(0, 0, 1, 1);
const [r, g, b] = Array.from(ctx.getImageData(0, 0, 1, 1).data);
canvas.remove();
return (alpha) => {
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
}, [dotColor]);
const _dotScale = useMemo(() => (
Math.min(5, Math.max(0.1, dotScale))
), [dotScale]);
const _gap = useMemo(() => (
Math.max(1, gap)
), [gap]);
const _radialScale = useMemo(() => (
Math.min(1, Math.max(0.1, radialScale))
), [radialScale]);
const _density = useMemo(() => (
Math.min(1, Math.max(0.1, density))
), [density]);
const ctx = useMemo(() => {
return canvasRef.current?.getContext("2d");
}, [canvasRef.current]);
const dist = useCallback((x1, y1, x2, y2) => {
return Math.hypot(x2 - x1, y2 - y1);
}, []);
const map = useCallback((value, start1, stop1, start2, stop2) => {
const min = Math.min(start2, stop2);
const max = Math.max(start2, stop2);
const newValue = start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
return Math.min(Math.max(newValue, min), max);
}, []);
const render = useCallback(() => {
ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
const dotContainerSize = (_gap * 2) + (_dotScale * 2);
const diagonalDistance = Math.sqrt(width ** 2, height ** 2);
for (let y = 0; y <= height; y += dotContainerSize) {
for (let x = 0; x <= width; x += dotContainerSize) {
if (variant === "random") {
if (Math.random() > _density) {
continue;
}
}
ctx.beginPath();
const posX = x + (dotContainerSize / 2);
const posY = y + (dotContainerSize / 2);
ctx.ellipse(posX, posY, _dotScale, _dotScale, 0, 0, 360, false);
if (variant === "radial") {
const distance = dist(posX, posY, (width / 2), (height / 2));
let alpha = 1;
if (radialDirection === "in") {
alpha = map(distance, 0, (diagonalDistance / (10 * _radialScale)), 1, 0);
} else {
alpha = map(distance, diagonalDistance, (diagonalDistance / (2 / _radialScale)), 1, 0);
}
ctx.fillStyle = _dotColor(alpha);
} else {
ctx.fillStyle = dotColor;
}
ctx.fill();
ctx.closePath();
}
}
}, [
ctx,
map,
dist,
devicePixelRatio,
width,
height,
canvasWidth,
canvasHeight,
variant,
dotColor,
radialDirection,
_dotScale,
_dotColor,
_gap,
_radialScale,
_density,
]);
useEffect(() => {
const updateContainerDimensions = () => {
const {
width,
height,
} = containerRef.current.getBoundingClientRect();
setWidth(width);
setHeight(height);
};
const resizeObserver = new ResizeObserver(updateContainerDimensions);
resizeObserver.observe(containerRef.current);
updateContainerDimensions();
setMounted(true);
return () => {
resizeObserver.disconnect();
};
}, []);
useLayoutEffect(() => {
if (!mounted) return;
render();
}, [mounted, render]);
return (
<div
{...restProps}
ref={containerRef}
className={[
className,
styles["classic-dots-pattern-background"],
].join(" ")}
>
<canvas
aria-hidden={true}
width={canvasWidth}
height={canvasHeight}
ref={canvasRef}
/>
<Wrapper
{...restWrapperProps}
className={[
wrapperClassName,
styles["wrapper"],
].join(" ")}
>
{children}
</Wrapper>
</div>
);
};
export default memo(ClassicDotsPatternBackground); 4.2. Copy the CSS Module File
Copy the associated CSS module file into the same folder:
classic-dots-pattern-background.module.css
.classic-dots-pattern-background {
position: relative;
>canvas {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 1;
}
>.wrapper {
position: relative;
z-index: 2;
}
} Using CSS Modules ensures:
- Scoped styles, preventing class name collisions
- Seamless integration with React components
5. 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.
classic-dots-pattern-background-preview.jsx
import ClassicDotsPatternBackground from "@/components/backgrounds/classic-dots-pattern-background/classic-dots-pattern-background";
const ClassicDotsPatternBackgroundPreview = () => {
return (
<ClassicDotsPatternBackground
variant="random"
dotColor="#7a80dd"
style={{
width: "100%",
height: "100%",
}}
wrapperProps = {{
style: {
display: "grid",
placeItems: "center",
height: "100%"
}
}}
>
<h2>
Dot Pattern Background
</h2>
</ClassicDotsPatternBackground>
);
};
export default ClassicDotsPatternBackgroundPreview;