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;