Motiva
Мои коллекции
← каталог

Split Reveal

Заголовок, где каждое слово выезжает из-под маски со стаггером — классический вход текста.

gsaploadrevealstaggerintermediate~23 КБreduced-motion ✓

Пропсы

Разобрано из кода записи: обязательные — без «?», у остальных показано значение по умолчанию.

ПропТипПо умолчаниюЧто это
text?string"Премиум-анимации, готовые к копированию…

Установка

npx shadcn@latest add https://motiva.pages.dev/r/split-reveal-text.json

зависимости: gsap@^3.15.0 · @gsap/react@^2.1.2

Что нужно в проекте до установки
  1. components.json в корне — с алиасами в форме"components": "@/components". Нет файла — CLI не поймёт, куда класть.
  2. Алиас @ объявлен дважды: "paths": {"@/*": ["./src/*"]} в корневом tsconfig.json (в Vite он часто содержит только references — тогда CLI создаёт папку@) и resolve.alias в конфиге сборщика.
  3. Токены подключены один раз на приложение:import "@/styles/motiva-tokens.css" — они приезжают вместе с записью. Без них секция потеряет цвета, ритм и тему.
  4. Своя типографика не должна спорить: если у вас на обёрткеtext-align: center, он протечёт внутрь блоков.
  5. Проект без TypeScript? Всё равно нужен минимальныйtsconfig.json с pathsи "tsx": true в components.json: CLI грузит tsconfig безусловно, а с "tsx": false идёт за jsconfig.json и падает так же. Приехавший рядом.tsx можно не трогать — вам нужен.vanilla.js.

Экспорт

↓ Скачать .zip

Код

"use client";

import { useRef } from "react";
import { useGSAP } from "@gsap/react";
import gsap from "gsap";

/** Текст, где каждое слово выезжает из-под маски со стаггером (GSAP). data-shot/reduced → финальное состояние. */
export function SplitReveal({ text = "Премиум-анимации, готовые к копированию" }: { text?: string }) {
  const ref = useRef<HTMLDivElement>(null);

  useGSAP(
    () => {
      const el = ref.current;
      if (!el) return;
      const words = el.querySelectorAll(".sr-word");
      if (
        document.documentElement.hasAttribute("data-shot") ||
        window.matchMedia("(prefers-reduced-motion: reduce)").matches
      ) {
        gsap.set(words, { yPercent: 0, opacity: 1 });
        return;
      }
      gsap.from(words, { yPercent: 115, opacity: 0, duration: 0.8, ease: "power3.out", stagger: 0.08 });
    },
    { scope: ref },
  );

  return (
    <div
      ref={ref}
      style={{ fontSize: "2rem", fontWeight: 700, lineHeight: 1.15, textAlign: "center", maxWidth: 460, color: "oklch(0.94 0.01 265)" }}
    >
      {text.split(" ").map((w, i) => (
        <span key={i} style={{ display: "inline-block", overflow: "hidden", verticalAlign: "bottom" }}>
          <span className="sr-word" style={{ display: "inline-block" }}>
            {w}&nbsp;
          </span>
        </span>
      ))}
    </div>
  );
}
лицензия: MITавтор: Motivaисточник: оригинал (Motiva)v1.0.0