Анимированные иконки Lucide Animated: примеры и настройка
Анимированные иконки Lucide Animated на практике: бесплатная мастерская с 48 иконками, поиском и категориями. Сначала видны 12 карточек, остальные раскрываются по кнопке. Примеры в кнопках, меню, карточке и уведомлениях, настройка цвета, размера и фона, статический SVG, код и исходный проект. Доступность и спокойный режим.
Колокольчик слегка качнулся, когда появились уведомления; стрелка ожила при переходе к следующему шагу; галочка подтвердила сохранение настроек. Такие небольшие движения помогают заметить действие и его результат. Lucide Animated — открытая коллекция анимированных иконок на основе Lucide. Её компоненты можно добавить в React-приложение и управлять анимацией из собственного интерфейса.
Ниже — бесплатная мастерская без регистрации: 48 иконок, поиск, категории, разные варианты использования и настройка внешнего вида. Сначала видны 12 карточек, остальные открываются кнопкой «Показать ещё». Попробуйте кнопку, меню, уведомление, карточку и кнопку только с иконкой. Здесь можно скопировать пример, скачать статический SVG или учебный проект. Настройки примеров обрабатываются в браузере.
Примерьте иконки к интерфейсу
Выберите иконку, настройте её вид и попробуйте анимацию в кнопке, меню или уведомлении. Заберите код и исходники своего примера.
Без регистрации
Иконки — Lucide Animated, pqoqubbw. Площадка и примеры использования — ae-nekrasov.ru. Настройки обрабатываются в браузере.
Для мастерской взяты настоящие компоненты из pqoqubbw/icons. Каталог, элементы управления и учебные сценарии написаны для этой статьи. В проекте зафиксированы React 19.3.0 и Motion 14.0.0; это версии нашей сборки. Статья и примеры не воспроизводят официальные демонстрационные страницы проекта.
Что входит в Lucide Animated
Основной проект предоставляет React-компоненты с анимацией Motion. У иконки есть обычная форма SVG и сценарий движения: например, поворот колокольчика или прорисовка галочки. Компонент можно настроить, скопировать в своё приложение и менять дальше. Официальная справка проекта показывает установку отдельных иконок через реестр shadcn.
Для Svelte, Vue, Angular и Flutter в README приведены отдельные работы сообщества: Svelte от jis3r, Vue от imfenghuang, Angular от ajitzero и Flutter от ravikovind. У них свои пакеты, API и сопровождение. Перед выбором проверяйте нужные иконки и инструкции конкретного порта.
Оригинальные TSX-файлы нельзя просто подключить к PHP-шаблону тегом script: им нужна сборка React. Готовый виджет можно затем встроить в HTML5-страницу или WordPress. Если требуется только неподвижный рисунок, достаточно SVG; устанавливать React для одного статического значка необязательно.
Как пользоваться мастерской
Начните с поиска по русскому назначению или английскому имени. Он проверяет все 48 иконок, включая ещё не раскрытые карточки. Например, найдите bell, file-text, shield-check или calendar-days. Для просмотра по назначению выберите категорию: «Навигация», «Действия», «Файлы и закладки», «Состояния и защита», «Общение» или «Вид и время». Поиск работает вместе с категорией; счётчики показывают число совпадений.
В категории «Все» сначала показаны прежние 12 иконок. Кнопка «Показать ещё» добавляет карточки порциями по 12; подборку можно снова свернуть. Смена поиска или категории возвращает компактный вид, но сохраняет выбранную иконку и настройки предпросмотра. Если совпадений нет, очистите запрос или воспользуйтесь кнопкой сброса. Это наша практическая подборка; полный каталог находится на сайте автора.
Выберите контекст, затем размер, цвет и фон. Проверяйте рисунок там, где он будет работать: значок в компактной кнопке и крупная иконка карточки решают разные задачи. Режимы наведения/фокуса и нажатия позволяют сравнить запуск мышью, клавиатурой и касанием. Кнопка повтора пригодится для просмотра одного движения.
Спокойный режим отключает движение. Мастерская также учитывает системную настройку уменьшения анимации. Скачиваемый SVG содержит статическую форму; поведение Motion находится в React-коде и в исходном проекте. Учебные уведомления и действия помогают проверить интерфейс; они не означают подключение почты, сервера или личного кабинета.
Установка: добавляем исходник нужной иконки
Для нового приложения сначала создайте React-проект и настройте shadcn по официальной инструкции для Vite. В готовом проекте должны работать TypeScript, псевдоним @/ и помощник cn из @/lib/utils. Затем добавьте колокольчик:
npx shadcn@latest add "https://lucide-animated.com/r/bell.json"
Команда получает описание компонента из официального реестра bell, добавляет его исходник и указанную зависимость motion. Место файла определяется настройками shadcn. Ниже предполагается путь @/components/ui/bell; если ваш файл установлен в другую папку, измените импорт.
Обратите внимание на имя экспорта: в проверенном исходнике это BellIcon и тип BellIconHandle. В кратких примерах документации встречаются другие имена, поэтому сверяйте импорт с фактически добавленным файлом. Сам репозиторий отмечен как private: true; здесь используется установка исходников из реестра, а не предположение о едином npm-пакете для всех фреймворков.
Размер, цвет и первое отображение
Параметр size задаёт размер SVG. Линии используют currentColor, поэтому цвет удобно передать через родительский элемент. В первом примере иконка служит неподвижным украшением рядом с текстом:
import { useRef } from "react";
import { BellIcon, type BellIconHandle } from "@/components/ui/bell";
export function NotificationsLabel() {
const bell = useRef<BellIconHandle>(null);
return (
<div style={{ display: "flex", alignItems: "center", gap: 8, color: "#175cd3" }}>
<div aria-hidden="true">
<BellIcon ref={bell} size={24} />
</div>
<span>Уведомления</span>
</div>
);
}
Переданный ref переводит эту иконку под наше управление: встроенное наведение больше не запускает движение самостоятельно. Мы не вызываем запуск, поэтому пример остаётся спокойным. В BellIcon внешний элемент — div, а обычные HTML-атрибуты относятся к нему. Это важно при выборе разметки: не считайте компонент непосредственным SVG и не вкладывайте его внешний div внутрь нативной кнопки.
Управление анимацией при наведении и фокусе
Следующий компонент совмещает настоящую кнопку и декоративную иконку, расположенную рядом в разметке. Кнопка принимает действия пользователя; иконка только отображает состояние. Методы startAnimation() и stopAnimation() получаем через ref. Назначение ссылки на компонент объясняет документация React.
import { useEffect, useRef, useState } from "react";
import { useReducedMotion } from "motion/react";
import { BellIcon, type BellIconHandle } from "@/components/ui/bell";
type BellButtonProps = {
label: string;
iconOnly?: boolean;
expanded?: boolean;
controls?: string;
onClick: () => void;
};
export function BellButton({
label, iconOnly = false, expanded, controls, onClick
}: BellButtonProps) {
const bell = useRef<BellIconHandle>(null);
const [hovered, setHovered] = useState(false);
const [focused, setFocused] = useState(false);
const reduce = useReducedMotion();
useEffect(() => {
if (reduce === false && (hovered || focused)) {
bell.current?.startAnimation();
} else {
bell.current?.stopAnimation();
}
}, [hovered, focused, reduce]);
return (
<div className={`icon-action ${iconOnly ? "icon-action--compact" : ""}`}>
<button
type="button"
aria-label={iconOnly ? label : undefined}
aria-expanded={expanded}
aria-controls={controls}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
onClick={onClick}
>
{!iconOnly && label}
</button>
<div className="icon-action__picture" aria-hidden="true">
<BellIcon ref={bell} size={24} />
</div>
</div>
);
}
Фокус и наведение учитываются отдельно: уход мыши не отменяет движение, пока кнопка удерживает клавиатурный фокус. Размер области нажатия задаёт кнопка, а не маленький SVG. Добавьте в CSS проекта:
.icon-action { position: relative; display: inline-block; color: #175cd3; }
.icon-action button {
min-height: 44px; min-width: 44px; padding: 10px 14px 10px 44px;
color: inherit; background: #fff; border: 1px solid currentColor;
border-radius: 10px; font: inherit; cursor: pointer;
}
.icon-action__picture {
position: absolute; left: 12px; top: 50%;
transform: translateY(-50%); pointer-events: none;
}
.icon-action--compact button { width: 48px; padding: 0; }
.icon-action button:focus-visible { outline: 3px solid #111; outline-offset: 3px; }
Кнопка только с иконкой и понятное назначение
Посетитель может не догадаться, что означает колокольчик без подписи. Где позволяет место, оставляйте видимый текст. Для компактной кнопки задайте доступное имя, описывающее действие: «Открыть уведомления». Требование к имени и роли элемента раскрывается в пояснении W3C. Сам декоративный рисунок скрываем от чтения через aria-hidden.
import { useState } from "react";
import { BellButton } from "./BellButton";
export function NotificationPanel() {
const [open, setOpen] = useState(false);
return (
<section aria-label="Учебные уведомления">
<BellButton
iconOnly
label={open ? "Закрыть уведомления" : "Открыть уведомления"}
expanded={open}
controls="notification-list"
onClick={() => setOpen(value => !value)}
/>
<div id="notification-list" hidden={!open}>
<p>Учебное уведомление: материал готов к просмотру.</p>
</div>
</section>
);
}
Это раскрываемый блок, поэтому передаём aria-expanded и связь с его содержимым. Анимация не изменяет число уведомлений и не сообщает об их прочтении. Такие состояния должны приходить из данных приложения. Если компонентов несколько, назначьте каждому блоку уникальный id, например через React useId().
Галочка после реального сохранения, ожидание и ошибка
Вращение загрузчика показывает ожидание, а галочка — успешный результат. Не подменяйте выполнение действия красивым движением по нажатию. В примере ниже обработчик ждёт ответ сервера. Адрес /api/settings необходимо заменить вашим обработчиком, который возвращает успешный HTTP-статус только после сохранения. Добавьте компонент галочки той же командой, используя circle-check.json.
import { useEffect, useRef, useState } from "react";
import { useReducedMotion } from "motion/react";
import {
CircleCheckIcon, type CircleCheckIconHandle
} from "@/components/ui/circle-check";
export function SaveSettings({ values }: { values: Record<string, string> }) {
const [state, setState] = useState<"idle" | "saving" | "saved" | "error">("idle");
const check = useRef<CircleCheckIconHandle>(null);
const reduce = useReducedMotion();
useEffect(() => {
if (state === "saved" && reduce === false) check.current?.startAnimation();
else check.current?.stopAnimation();
}, [state, reduce]);
async function save() {
if (state === "saving") return;
setState("saving");
try {
const response = await fetch("/api/settings", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(values)
});
if (!response.ok) throw new Error("Save failed");
setState("saved");
} catch {
setState("error");
}
}
const message = {
idle: "Настройки ещё не сохранены.", saving: "Сохраняем…",
saved: "Настройки сохранены.", error: "Не удалось сохранить. Повторите попытку."
}[state];
return (
<section aria-label="Сохранение настроек" aria-busy={state === "saving"}>
<button type="button" disabled={state === "saving"} onClick={save}>
{state === "saving" ? "Сохраняем…" : "Сохранить настройки"}
</button>
<div aria-hidden="true" style={{ visibility: state === "saved" ? "visible" : "hidden" }}>
<CircleCheckIcon ref={check} size={24} />
</div>
<p role="status">{message}</p>
</section>
);
}
Текст сохраняет смысл при отключённом движении. Ошибка позволяет повторить действие; кнопка временно недоступна во время запроса. Если форма продолжает редактироваться после сохранения, отдельно отслеживайте изменения и возвращайте сообщение в состояние «Есть несохранённые изменения». Для загрузки файла подтверждайте его подготовку или запуск скачивания в соответствии с вашим обработчиком; браузер не всегда позволяет узнать, куда пользователь сохранил файл.
Уменьшение движения и собственный спокойный режим
Настройка уменьшения движения нужна людям, которым анимация мешает воспринимать страницу. Хук useReducedMotion() учитывает системное предпочтение и реагирует на его изменение. В наших фрагментах запуск разрешён только при значении false. Это также оставляет иконку неподвижной, пока предпочтение ещё не определено.
Если добавляете переключатель «Спокойный режим», объедините его с системной настройкой: запрет на движение действует при любом из двух условий. Передавайте ref во все используемые иконки и проверяйте разрешение в каждом пути запуска — при наведении, фокусе, нажатии и смене данных. Не ограничивайтесь CSS: Motion может менять SVG-пути средствами JavaScript. Отключение только поворота не обязательно остановит прорисовку линии.
При выключении движения можно сразу вернуть иконку к обычному виду. В исходных компонентах stopAnimation() означает переход к варианту normal; это не обещание мгновенно отменить каждый переход. Для строгого отсутствия движения измените длительность возвращения в локальном исходнике или показывайте статическую SVG-форму. Смысл действий, фокус и текстовые сообщения должны сохраняться.
Что проверить перед добавлением на сайт
Начните с одного сценария, например открытия уведомлений, и проверьте его на узком экране: подпись читается, кнопка достаточно удобна для касания, фокус виден, панель не выходит за границы. Пройдите ту же последовательность клавишей Tab и клавишами Enter или Space. Затем включите уменьшение движения в системе и убедитесь, что действие остаётся понятным без анимации.
Добавляйте только необходимые компоненты и измеряйте итоговую сборку своего приложения. SVG не даёт автоматической гарантии лёгкости всей страницы: размер зависит от зависимостей, числа компонентов и способа сборки. Постоянно вращающиеся значки оправданы во время ожидания; после завершения операции остановите их. Для каталога с большим числом иконок имеет смысл не запускать движение за пределами видимой области.
Компоненты распространяются под MIT; сохраняйте текст лицензии и уведомление об авторских правах при передаче исходников. В README автор отдельно описывает ограничения на распространение его обучающих материалов и демонстраций. Наш проект содержит собственную мастерскую и объяснения. Скачайте исходники, найдите выбранную иконку и перенесите нужный сценарий в своё приложение, сохранив условия используемых компонентов.

