8. Анимации и Движение
Motion в Rocketmind — функциональный, не декоративный. Каждая анимация решает задачу: подтверждает действие, указывает направление, сообщает о смене состояния.
8.2 Timing-шкала
Полоска показывает относительную длину каждого токена.
--duration-instant50msНемедленная реакция (cursor, checkmark мгновенный)--duration-fast100msHover-эффекты кнопок, смена цвета--duration-base200msСтандарт: переходы состояний (active/disabled/focus)--duration-smooth300msПоявление/скрытие элементов (dropdown, tooltip)--duration-enter400msВходящие элементы (модал, панель)--duration-grid1600msAnimated Grid Lines hero reveal — единственная длинная анимация8.3 Easing-кривые
Нажми «Play», чтобы увидеть как шарик движется с данной кривой.
--ease-standardHover, focus, active — большинство переходов
cubic-bezier(0.4, 0, 0.2, 1)
--ease-enterПоявление элементов (модал, дропдаун, toast)
cubic-bezier(0, 0, 0.2, 1)
--ease-exitИсчезновение элементов (закрытие, скрытие)
cubic-bezier(0.4, 0, 1, 1)
--ease-springHover scale на карточках — небольшой перелёт
cubic-bezier(0.34, 1.56, 0.64, 1)
8.4 Микроинтерактивы
Наведи курсор на каждый элемент.
Button hover
Primary button: hover меняет цвет. 100ms ease-standard.
Ghost button hover
Ghost button использует прежний Secondary-style и на hover меняет серый фон. 100ms ease-standard.
Input focus
Input: при фокусе border жёлтый. 200ms ease-standard.
Agent card hover
Карточка агента: hover меняет border на фиолетовый. 200ms ease-spring.
AI-агент
Hover this card
Link CTA → arrow
Текстовая ссылка: hover сдвигает стрелку на 4px вправо. 100ms ease-standard.
Nav icon hover
Иконка в сайдбаре: hover меняет цвет с muted-foreground на foreground. 100ms ease-standard.
8.5 Переходы между состояниями экрана
Нажми кнопку, чтобы воспроизвести анимацию появления элемента.
Dropdown / Tooltip
Fade + slide 8px вниз. 300ms ease-enter.
Опции
Редактировать
Удалить
Модальное окно
Slide + scale от 0.98. 400ms ease-enter.
Диалог
Вы уверены в этом действии?
Toast / Notification
Slide справа-налево. 300ms ease-enter.
Сообщение в чате
Fade + slide 8px снизу. 300ms ease-enter.
AI-агент
Привет! Чем могу помочь?
8.6 Loading / Skeleton
Skeleton занимает место сразу — нет «прыжков» при загрузке. Shimmer движется бесконечно.
Skeleton shimmer
Блоки-заглушки с движущимся блеском. Показываются пока грузятся данные.
Typing indicator
Три точки с stagger 0.2s. Показывает, что агент печатает ответ.
8.7 Page-level правила
8.8 Доступность (Reduced Motion)
prefers-reduced-motion: reduce
Все анимации обязаны уважать системные настройки. Исключение — typing-indicator: заменяется на статичный •••.
8.9 Animated Grid Lines
Тонкие линии hero-секции материализуют каркас дизайна. Только одноразовая анимация при загрузке — после появления статичны. Используется с токеном --duration-grid (1600ms).
scaleX/scaleY 0→1 · 1600ms ease-out · stagger 0.1s между линиями
8.10 Dot Grid Lens
Фоновый эффект «линзы» на сетке точек: при движении курсора точки вблизи него увеличиваются по квадратичному закону. Используется в hero-секции и CTA лендинга. Реализован через Canvas.
Токены, алгоритм и применение
--dot-size3pxБазовый диаметр точки--dot-size-max10pxМаксимальный диаметр в центре линзы--dot-gap20pxШаг сетки (расстояние между центрами)--lens-radius120pxРадиус влияния курсора--dot-color#CBCBCB / #404040Цвет точек (= --border токен)--dot-color-accent#FFCC00Акцентный цвет точек в центре линзыdistance = sqrt((x − mx)² + (y − my)²)
t = clamp(1 − distance / LENS_RADIUS, 0, 1)
scale = 1 + (MAX_SCALE − 1) × t² // квадратичный easing
dotRadius = BASE_RADIUS × scale
| Экран | Секция | Вариант |
|---|---|---|
| Лендинг — Hero | Полный фон hero | Акцентный (#FFCC00 в линзе) |
| Лендинг — CTA | Фон CTA-блока | Монохромный |
| Auth | Фоновый декор | Монохромный, opacity: 0.5 |
| Main App | — | Не используется |
8.11 Hero Background Noise & Bottom Fade
Для тёмного hero допустим отдельный декоративный слой: мягкая подложка на токенах, статичный шум и нижний fade в --background. Эффект применяется только к фону, а не к контенту.
Токены и правила
Base backdrop--background + --rm-yellow-100 + --rm-gray-alpha-1002 radial-gradient и 1 vertical linear-gradient без новых цветовNoise overlaysoft-light · opacity 0.04-0.06Только статичный SVG noise, без анимацииBottom fadetransparent 74% -> var(--background) 100%Fade затрагивает только декоративный слойИспользуем только в full-bleed hero на тёмном фоне. Шум всегда неинтерактивный и статичный, fade уходит в токен страницы, а логотип, copy и CTA остаются поверх слоя с полным контрастом.
8.12 Hero Round Glass Lens
Круглая hero-линза искажает уже собранную сцену внутри круга через WebGL, без blur и без отдельной DOM-копии контента внутри линзы. Центр остаётся почти стабильным, а fisheye/barrel-искажение усиливается к краю.
Примеры использования
Пример 1 — anchorRef + motion
<RoundGlassLens
sceneRef={sceneRef}
anchorRef={anchorRef}
size={280}
xOffset={60}
yOffset={18}
motionParallax
/>Пример 2 — Custom optical settings
AI AGENTS
Powered by Rocketmind
<RoundGlassLens
sceneRef={sceneRef}
size={220}
xOffset={-40}
refraction={0.04}
depth={0.22}
dispersion={0.55}
distortionRadius={1.1}
blur={0.22}
gradientAngle={135}
motionParallax
/>Пример 3 — Subtle / no shadow
Strategic growth platform
<RoundGlassLens
sceneRef={sceneRef}
size={180}
refraction={0.025}
depth={0.14}
dispersion={0.28}
blur={0.12}
shadowEnabled={false}
motionParallax
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| sceneRef | RefObject<HTMLElement> | — | Элемент для захвата (обязательно) |
| size | number | 320 | Диаметр линзы в px |
| x / y | number | center | Центр в координатах sceneRef |
| anchorRef | RefObject<HTMLElement> | — | Привязка к элементу (приоритет над x/y) |
| xOffset / yOffset | number | 0 | Смещение от центра анкора или сцены |
| refraction | number | 0.03 | Сила преломления (0–0.12) |
| depth | number | 0.18 | Глубина кривизны (0–0.5) |
| dispersion | number | 0.36 | Хроматическая дисперсия (0–5) |
| distortionRadius | number | 1.08 | Радиус зоны искажения (0.2–1.5) |
| shadowRadius | number | 0.98 | Радиус краевой тени (0.2–1.5) |
| blur | number | 0.18 | Радиальный блур (0–2) |
| gradientAngle | number | 205 | Угол градиента ободка (0–360°) |
| shadowEnabled | boolean | true | Краевое затемнение |
| motionParallax | boolean | auto | Параллакс по курсору |
| motionStrength | number | 0.032 | Сила параллакса |
| showControls | boolean | false | Показать панель настройки (dev) |
| storageKey | string | — | Ключ localStorage для сохранения настроек |
Dev-воркфлоу
- 1Добавьте
showControls storageKey="my-page:lens"в компонент. - 2Настраивайте параметры в плавающей панели. Нажмите COPY — в буфере обмена JSX-пропсы.
- 3Вставьте пропсы в код, уберите
showControls storageKey.
Токены, алгоритм и правила
Diameterclamp(280px, 30vw, 360px)Размер линзы в heroOuter stroke1px linear-gradient(62deg, #FFE900 1%, #A6A6A6 40%, rgba(64,64,64,0) 100%)Тонкая градиентная обводка по кругуSide flaresblue-white chromatic accentsКороткие световые вспышки слева и справаInner strokenoneВнутренняя 1px-линия не используетсяPointer offset limit64pxМаксимальное смещение от базовой точкиRendererWebGL + scene capture textureНе дублировать контент внутри линзыrim = smoothstep(0.34, 0.98, normalized)
rimBand = rim × (1 − smoothstep(0.82, 1.0, normalized))
sampleOffset = localOffset × (1 − 0.22 × rimBand)
sampleOffset −= direction × radius × 0.085 × normalized³
Не вставляем внутрь линзы копию wordmark, меню, логотипов или background-слоёв. На pointer: coarse линза фиксируется на базовой позиции, а при prefers-reduced-motion: reduce отключается следование за курсором и дополнительные обновления сцены.
Secondary Lens
Допустима вторая большая линза справа без искажения сцены. Она использует тот же градиентный бордер и двигается за курсором в 3 раза медленнее и с амплитудой в 3 раза меньше, чем основная.
Доступность & Touch
На touch-устройствах (pointer: coarse) интерактивные hero-линзы фиксируются или отключаются, а декоративные фоны остаются статичными. При prefers-reduced-motion: reduce следование за курсором и дополнительные анимации останавливаются.
8.13 Wave Animation
Фоновый шейдер из бегущей сетки точек. Применяется в футере лендинга и на экране 404 как декоративный слой. Точки плавно затухают по мере удаления от камеры (глубина u_fade_near → u_fade_far), поэтому нижние точки остаются яркими, а верх плавно растворяется в фоне.
Параметры
pointSize3Размер точки в пикселяхwaveSpeed2Скорость бегущей волныwaveIntensity10Частота синусоиды по сеткеparticleColor#ffffffЦвет точек (применяем с альфой через fade)gridDistance4Шаг сетки в мировых единицахfadeNear20Глубина, с которой начинается затуханиеfadeFar200Глубина, на которой точка полностью прозрачна<WaveAnimation
pointSize={3}
waveSpeed={2}
waveIntensity={10}
particleColor="#ffffff"
gridDistance={4}
/>8.14 New-notification state («не просмотрено»)
Состояние для свежесозданной карточки/строки, которую пользователь ещё не открыл. Мягкая бледно-жёлтая подложка и плавно-пульсирующая жёлтая обводка — привлекают внимание без агрессии. Снимается после первого клика.
Новый проект
Подложка `--rm-yellow-10`, пульс 1.8s
Обычная карточка
Для сравнения — без пульса
Токены и параметры
bgvar(--rm-yellow-10)Подложка — самый бледный жёлтый из §1.1shadow (peak)0 0 0 3px rgba(255, 204, 0, 0.55)Яркий пик пульсаshadow (idle)0 0 0 0 rgba(255, 204, 0, 0)Исходная прозрачностьduration1.8sПолный цикл пульса — idle → peak → idleeasingease-in-outПлавное нарастание и затуханиеreduced-motionstatic 2px @ 0.4αСтатичная обводка при prefers-reduced-motion<Link
data-new={isNew || undefined}
className="rounded-sm border border-border transition-colors
data-[new=true]:bg-[var(--rm-yellow-10)]
data-[new=true]:rm-new-pulse"
>
…
</Link>Правила использования: только на одном иерархическом уровне; не более 3 непросмотренных в списке; не сочетать с акцентной hover-обводкой. См. §8.14 DS MD.
8.15 Message rise (real-time-only)
Анимация «подлёта» новых сообщений в чате при отправке в real-time. Не применяется к исторически загруженным сообщениям. Визуально — bubble подлетает снизу (14px) через прозрачность за 0.28s.
Параметры
fromopacity: 0; translateY(14px)Старт — лёгкое смещение снизуtoopacity: 1; translateY(0)Конечное положение bubble'аduration0.28sБыстро, но заметноeasingcubic-bezier(0.2, 0.8, 0.2, 1)Ease-out — мягкое приземлениеreduced-motionanimation: noneБез анимации для prefers-reduced-motion// Set<string> id-шников real-time сообщений
const [freshIds, setFreshIds] = useState(new Set());
// При добавлении нового сообщения:
setMessages(p => [...p, msg]);
setFreshIds(p => new Set(p).add(msg.id));
// В bubble:
<div className={freshIds.has(msg.id) ? "rm-message-rise" : ""}>
…
</div>Правила: не применять при загрузке истории; один раз при mount (не повторяется); не комбинировать с `rm-new-pulse`. См. §8.15 DS MD.
8.16 Pipeline step dimmed state
Визуальное приглушение не-пройденных шагов последовательного процесса — в списках вроде sidebar R-экспертов. Пользователь мгновенно видит, что за спиной, что сейчас, что впереди.
Матрица состояний
completedopacity: 100%Нормальная яркость, CheckCircle2 в жёлтом акцентеin_progress / awaiting_validationopacity: 100%Нормальная яркость, CircleDashed в foregroundcurrent (у проекта) + not_startedopacity: 100%Текущий следующий шаг — не затемнять никогдаnot_started (не current)opacity: 50%Приглушён, сигнал «впереди»hoveropacity: 100%Восстанавливается на hoverconst isDimmed =
status === "not_started" &&
currentExpertCodename !== codename;
<div className={`… ${isDimmed ? "opacity-50 hover:opacity-100" : ""}`}>
…
</div>Правила: current-шаг никогда не приглушается; hover восстанавливает; не использовать в dashboard-сценариях (там прогресс-бар). См. §8.16 DS MD.
8.17 Content load — fade-in-up
Появление контента при загрузке экрана в SaaS-обучении: тело урока, дашборд программы («разводная»), вопрос блиц-теста, экран AI-эксперта, профиль. opacity 0→1 + подъём 8px, 400ms, ease-enter — одним блоком.
Контент появляется через прозрачность и лёгкий подъём 8px. Один раз при загрузке экрана — урок, дашборд программы, вопрос блиц-теста, чат агента, профиль.
Параметры
fromopacity: 0; translateY(8px)Старт — лёгкое смещение снизуtoopacity: 1; translateY(0)Конечное положение контентаdurationvar(--duration-enter) = 400msПоявление экранаeasingvar(--ease-enter)Decelerate — мягкое торможениеreduced-motionanimation: noneБез анимации для prefers-reduced-motion// Класс .rm-content-enter в @rocketmind/ui globals.css.
// Перезапуск анимации на смене контента — через React key:
<article key={lesson.id} className="rm-content-enter …">…</article>Правила: один раз на маунт контейнера; перезапуск через key (id урока/программы/индекс вопроса/id агента); НЕ scroll-triggered; НЕ на каждый элемент списка. См. §8.17 DS MD.
