← каталог
Spotlight Hero
Прожектор на hero: широкий луч из угла одним радиальным градиентом — мягкость без blur. Появление one-shot, дальше только медленное дыхание трансформом.
cssautobasic0reduced-motion ✓
🎛 Настройки — крути и копируй
Пропсы
Разобрано из кода записи: обязательные — без «?», у остальных показано значение по умолчанию.
| Проп | Тип | По умолчанию | Что это |
|---|---|---|---|
| backdrop? | string | false | BACKDROP | Подложка под светом: CSS-значение `background` или `false`. `false` нужен, когда запись стоит фоном СЕКЦИИ и подложку задаёт она. |
| hue? | number | 290 | Тон света, градусы oklch. |
| angle? | number | -26 | Наклон луча, градусы. |
| strength? | number | 0.55 | Яркость луча (0.2–1). |
| children? | ReactNode | — | Содержимое поверх (в витрине — заголовок, в секции обычно пусто). |
Установка
npx shadcn@latest add https://motiva.pages.dev/r/spotlight-hero.jsonЧто нужно в проекте до установки
components.jsonв корне — с алиасами в форме"components": "@/components". Нет файла — CLI не поймёт, куда класть.- Алиас
@объявлен дважды:"paths": {"@/*": ["./src/*"]}в корневомtsconfig.json(в Vite он часто содержит толькоreferences— тогда CLI создаёт папку@) иresolve.aliasв конфиге сборщика. - Токены подключены один раз на приложение:
import "@/styles/motiva-tokens.css"— они приезжают вместе с записью. Без них секция потеряет цвета, ритм и тему. - Своя типографика не должна спорить: если у вас на обёртке
text-align: center, он протечёт внутрь блоков. - Проект без TypeScript? Всё равно нужен минимальный
tsconfig.jsonсpathsи"tsx": trueвcomponents.json: CLI грузит tsconfig безусловно, а с"tsx": falseидёт заjsconfig.jsonи падает так же. Приехавший рядом.tsxможно не трогать — вам нужен.vanilla.js.
Экспорт
Код
import type { CSSProperties, ReactNode } from "react";
/** Подложка по умолчанию — как в витрине. */
const BACKDROP = "oklch(0.13 0.015 275)";
export interface SpotlightHeroProps {
/**
* Подложка под светом: CSS-значение `background` или `false`.
* `false` нужен, когда запись стоит фоном СЕКЦИИ и подложку задаёт она.
*/
backdrop?: string | false;
/** Тон света, градусы oklch. */
hue?: number;
/** Наклон луча, градусы. */
angle?: number;
/** Яркость луча (0.2–1). */
strength?: number;
/** Содержимое поверх (в витрине — заголовок, в секции обычно пусто). */
children?: ReactNode;
}
/**
* Прожектор на hero: широкий луч бьёт из верхнего левого угла. Мягкость даёт сам
* радиальный градиент — ни одного filter: blur (полноэкранный blur — перерисовка,
* AGENTS). Появление — одна анимация opacity+transform, дальше только медленное
* «дыхание» трансформом: растр градиента закеширован композитором.
* Reduced-motion / data-shot — свет стоит включённым (база = финал).
*/
export function SpotlightHero({
backdrop = BACKDROP,
hue = 290,
angle = -26,
strength = 0.55,
children,
}: SpotlightHeroProps = {}) {
return (
<div
className="sh"
style={{
position: "absolute",
inset: 0,
overflow: "hidden",
...(backdrop === false ? null : { background: backdrop }),
}}
>
<style>{`
.sh { container-type: size; }
.sh-beam {
position: absolute;
width: 120cqw; height: 220cqh;
border-radius: 999px;
transform-origin: 50% 0;
/* база = финальное состояние: при animation: none свет просто включён */
opacity: 1;
animation: sh-in 1.6s cubic-bezier(0.22, 1, 0.36, 1) both, sh-breathe 12s ease-in-out 1.6s infinite;
}
.sh-main {
left: -34cqw; top: -120cqh;
background: radial-gradient(50% 50% at 50% 50%, var(--sh-c1), transparent 68%);
transform: rotate(var(--sh-angle));
}
.sh-side {
right: -50cqw; top: -140cqh;
background: radial-gradient(50% 50% at 50% 50%, var(--sh-c2), transparent 66%);
transform: rotate(calc(var(--sh-angle) * -0.6));
animation-delay: 0.25s, 1.85s;
}
@keyframes sh-in {
from { opacity: 0; translate: 0 -12cqh; }
to { opacity: 1; translate: 0 0; }
}
@keyframes sh-breathe {
0%, 100% { scale: 1; }
50% { scale: 1.045; }
}
@media (prefers-reduced-motion: reduce) { .sh-beam { animation: none; } }
`}</style>
<div
style={
{
position: "absolute",
inset: 0,
"--sh-angle": `${angle}deg`,
"--sh-c1": `oklch(0.92 0.03 ${hue} / ${strength})`,
"--sh-c2": `oklch(0.85 0.05 ${hue + 40} / ${strength * 0.4})`,
} as CSSProperties
}
>
<div className="sh-beam sh-main" />
<div className="sh-beam sh-side" />
</div>
{children && (
<div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>{children}</div>
)}
</div>
);
}
Похожие эффекты
лицензия: MITавтор: Motivaисточник: оригинал (Motiva); идея-референс — Aceternity Spotlight (только идея: terms запрещают заимствование кода)v1.0.0