Gradient Text
Анимированный градиентный текст: background-clip:text, широкий градиент бесконечно течёт по буквам.
Пропсы
Разобрано из кода записи: обязательные — без «?», у остальных показано значение по умолчанию.
| Проп | Тип | По умолчанию | Что это |
|---|---|---|---|
| children? | ReactNode | "Градиент течёт по тексту" | |
| duration? | number | 6 | Длительность цикла, сек. |
| colors? | string[] | ["oklch(0.75 0.16 300)", "oklch(0.78 0.1… | |
| style? | CSSProperties | — |
Установка
npx shadcn@latest add https://motiva.pages.dev/r/gradient-text.jsonЧто нужно в проекте до установки
Файл
components.jsonв корнеИз него CLI узнаёт, куда класть файлы. Алиасы — в такой форме:
"aliases": { "components": "@/components", "lib": "@/lib" }Нет файла — установка не начнётся вовсе.
Алиас
@объявлен дваждыВ корневом
tsconfig.jsonи в конфиге сборщика. В Vite корневой tsconfig часто содержит толькоreferences— этого мало."paths": { "@/*": ["./src/*"] } // tsconfig.json resolve.alias = { "@": "/src" } // vite.config.tsБез
pathsCLI молча создаёт папку с именем@.Токены подключены один раз на приложение
Они приезжают вместе с записью — достаточно импортировать их в точке входа:
import "@/styles/motiva-tokens.css";Без них блок потеряет цвета, ритм и тему.
Своя типографика не спорит с блоком
Наследуемые свойства протекают внутрь:
text-align: centerна обёртке отцентрует содержимое секции. То же касаетсяfont-familyиline-height.Проект без TypeScript? всё равно нужен tsconfig
CLI грузит
tsconfig.jsonбезусловно, а при"tsx": falseидёт заjsconfig.jsonи падает так же. Минимум — файл сpathsи"tsx": trueвcomponents.json.Приехавший рядом
.tsxможно не трогать — вам нужен.vanilla.js.
Экспорт
Код
.gt-text {
display: inline-block;
font-size: clamp(1.8rem, 1rem + 3.6vw, 3.2rem);
font-weight: 800;
letter-spacing: -0.02em;
background-size: 300% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: gt-flow var(--gt-dur) linear infinite;
}
@keyframes gt-flow { to { background-position: 300% 0; } }
@media (prefers-reduced-motion: reduce) { .gt-text { animation: none; } }
const css = `.gt-text {
display: inline-block;
font-size: clamp(1.8rem, 1rem + 3.6vw, 3.2rem);
font-weight: 800;
letter-spacing: -0.02em;
background-size: 300% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: gt-flow var(--gt-dur) linear infinite;
}
@keyframes gt-flow { to { background-position: 300% 0; } }
@media (prefers-reduced-motion: reduce) { .gt-text { animation: none; } }
`;
import type { CSSProperties, ReactNode } from "react";
export interface GradientTextProps {
children?: ReactNode;
/** Длительность цикла, сек. */
duration?: number;
colors?: string[];
style?: CSSProperties;
}
/**
* Анимированный градиентный текст: background-clip:text + широкий градиент едет по
* background-position. Чистый CSS. Reduced-motion/data-shot — градиент статичен.
*/
export function GradientText({
children = "Градиент течёт по тексту",
duration = 6,
colors = ["oklch(0.75 0.16 300)", "oklch(0.78 0.14 210)", "oklch(0.8 0.15 150)", "oklch(0.75 0.16 300)"],
style,
}: GradientTextProps) {
return (
<span
className="gt-text"
style={
{
"--gt-dur": `${duration}s`,
backgroundImage: `linear-gradient(90deg, ${colors.join(", ")})`,
...style,
} as CSSProperties
}
>
<style href="motiva-gradient-text" precedence="medium">{css}</style>
{children}
</span>
);
}