Создание простого компонента уведомления в React без внешних зависимостей

Почему собственный компонент иногда лучше готового пакета
Готовые библиотеки (toasts/notification libraries) дают функционал «из коробки» — очередь уведомлений, позиционирование, контейнер, очередность. Но они добавляют зависимость и вес. Если вам нужен простой одноуровневый компонент с несколькими типами и базовой анимацией, собственная реализация:
- легче и прозрачнее для поддержки,
- проще интегрируется с вашим CSS и дизайном,
- не перегружает сборку.
Важно: выбирайте готовые решения, если вам нужны очереди, расширенные политики показа, персистентность, уровень приоритетов или интеграция с сервером событий.
Настройка проекта (Vite + React)
- Установите Node.js и yarn (или используйте npm, заменив команды).
- Создайте проект Vite (React + JavaScript):
yarn create viteКоманда спросит имя проекта, фреймворк — выберите react, затем вариант — JavaScript.
После создания перейдите в папку проекта и откройте её в редакторе. Запустите dev-сервер:
yarn devПо умолчанию приложение будет доступно в браузере по адресу http://localhost:5173/.
Дизайн компонента уведомления — что нужно учитывать
Компонент должен быть гибким: поддерживать разные типы (success, warning, error), заголовок и описание, иконки и действие закрытия. Он должен:
- принимать props: type, title, description;
- рендерить разные цвета и иконки по типу;
- корректно выглядеть при разных длинах текста;
- быть доступным (screen reader friendly) — минимум: aria-атрибуты для статуса.
Примеры вариаций:
Структура файлов
Рекомендуемая минимальная структура:
- src/Notification.jsx — компонент уведомления
- src/notification.css — стили
- src/App.jsx — демонстрация использования
Реализация: Notification.jsx
Ниже — минимальный и чистый пример компонента с иконками из react-icons и классами для каждого типа.
// src/Notification.jsx
import React from 'react'
import { RxCross2, RxInfoCircled } from 'react-icons/rx'
import './notification.css'
export default function Notification({ type = 'success', title, description, onClose }) {
return (
{title}
{description}
)
}Примечания:
- Добавлен атрибут role=”status” и aria-live=”polite” для улучшенной доступности.
- onClose — callback для закрытия уведомления (контейнер или родительская логика отвечает за удаление).
Стили: notification.css
Базовые и типовые классы можно организовать так:
/* src/notification.css */
.notification {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: 8px 12px;
gap: 12px;
max-width: 560px;
box-sizing: border-box;
transition: transform 200ms ease, opacity 200ms ease;
}
.notification__left {
display: flex;
gap: 8px;
align-items: flex-start;
}
.notification__content {
display: flex;
flex-direction: column;
}
.notification__title {
font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto;
font-weight: 600;
font-size: 14px;
line-height: 1.2;
}
.notification__description {
font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto;
font-weight: 400;
font-size: 13px;
margin-top: 2px;
}
.notification__close {
background: transparent;
border: none;
padding: 4px;
display: flex;
align-items: center;
cursor: pointer;
}
/* Цвета для состояний */
.notification__success { background: #f6fef9; border: 1px solid #2f9461; border-radius: 8px; }
.notification__error { background: #fffbfa; border: 1px solid #cd3636; border-radius: 8px; }
.notification__warning { background: #fffcf5; border: 1px solid #c8811a; border-radius: 8px; }
.notification__title__success { color: #2f9461; }
.notification__title__warning { color: #c8811a; }
.notification__title__error { color: #cd3636; }
.notification__description__success { color: #53b483; }
.notification__description__warning { color: #e9a23b; }
.notification__description__error { color: #f34141; }
.notification__icon__success { color: #2f9461; }
.notification__icon__warning { color: #c8811a; }
.notification__icon__error { color: #cd3636; }
/* Простая анимация появления */
.notification-enter { transform: translateY(-8px); opacity: 0; }
.notification-enter-active { transform: translateY(0); opacity: 1; transition: transform 180ms ease, opacity 180ms ease; }
.notification-exit { transform: translateY(0); opacity: 1; }
.notification-exit-active { transform: translateY(-8px); opacity: 0; transition: transform 180ms ease, opacity 180ms ease; }Важно: цвета и шрифты адаптируйте под ваш дизайн. Здесь использованы нейтральные системные шрифты и простые оттенки.
Пример использования в App.jsx
// src/App.jsx
import React, { useState } from 'react'
import Notification from './Notification'
function App() {
const [visible, setVisible] = useState(true)
return (
{visible && (
setVisible(false)}
/>
)}
)
}
export default AppДобавление автоматического скрытия и анимации
Чтобы уведомление автоматически исчезало через N секунд, используйте эффект useEffect в родителе или внутри компонента:
// внутри Notification или в контейнере уведомлений
useEffect(() => {
if (!duration) return;
const id = setTimeout(() => onClose && onClose(), duration);
return () => clearTimeout(id);
}, [duration, onClose]);Для плавной анимации входа/выхода можно использовать CSS-классы и небольшой контейнер, либо библиотеку react-transition-group для более управляемых переходов.
Контейнер уведомлений для нескольких сообщений
Если у вас будет несколько уведомлений, создайте NotificationContainer, который хранит массив уведомлений и рендерит их стеком. Контейнер отвечает за:
- добавление/удаление уведомлений,
- позиционирование (top-right, bottom-left и т. д.),
- предотвращение перекрытия и очередь.
Простая архитектура: держать массив объектов { id, type, title, description, duration } в state контейнера.
Альтернативные подходы и когда их использовать
- Готовые библиотеки (react-toastify, notistack, radix-ui, headlessui): когда нужна очередь, блокировка повторов, позиции, богатая API.
- CSS-only уведомления: когда не нужна логика — просто статические сообщения в DOM.
- Система событий (EventEmitter/Redux/Context): если уведомления могут генерироваться в разных местах приложения.
Когда не стоит делать свой компонент: если вы ожидаете сложных сценариев показа (приоритеты, повторяющиеся события, синхронизация с сервером), используйте проверенные библиотеки.
Правила доступности и локализации
- Используйте aria-live=”polite” или “assertive” в зависимости от важности сообщения.
- Кнопка закрытия должна иметь aria-label с понятным переводом.
- Тексты и даты локализуйте через i18n-библиотеки (react-intl, i18next).
Важно: цвета не должны быть единственным каналом передачи информации — используйте иконки и текст.
Мини-методология внедрения (шаги)
- Создать компонент Notification.jsx и notification.css.
- Добавить простую демонстрацию в App.jsx.
- Протестировать на разных длинах текста и в мобильном размере.
- Добавить accessibility (aria).
- Опционально: реализовать контейнер для очереди уведомлений.
- Покрыть тестами ключевые сценарии (см. ниже).
Критерии приёмки
- Компонент рендерится с title и description.
- Для типов success/warning/error применяются разные цвета и иконки.
- Нажатие на кнопку закрытия вызывает onClose и удаляет уведомление.
- aria-live установлен и кнопка закрытия имеет aria-label.
- Анимация входа/выхода не «дергает» остальной контент.
Тест-кейсы и приемочные критерии
- Показ уведомления типа success с коротким текстом — визуальная проверка цвета и иконки.
- Показ уведомления с длинным description — проверка переноса и доступного размера контейнера.
- Нажатие на крестик — уведомление удаляется.
- Проверка aria-live: screen reader должен читать сообщение при появлении.
- Автоматическое скрытие через duration — уведомление исчезает по таймеру.
Чек-лист для ролей
Разработчик:
- реализовать компонент и стили,
- покрыть unit-тестами (рендер, props),
- добавить базовую документацию.
Тестировщик:
- проверить визуально все типы,
- проверить доступность,
- провести тесты на разных устройствах.
Дизайнер:
- утвердить палитру цветов и размеры иконок,
- проверить визуальную иерархию текста.
Когда подход не сработает (контрпримеры)
- Если нужны глобальные правила очереди с приоритетами, самостоятельный компонент слишком прост.
- Если приложение требует персистентности уведомлений между сессиями — нужен бэкенд/локальное хранилище.
- Для массовых нотификаций в реальном времени лучше применять систему очередей и специализированные библиотеки.
Безопасность и приватность
Уведомления не должны отображать чувствительные данные (пароли, PII) в явном виде. Для приватной информации используйте защищённые каналы и минимизируйте время отображения.
Краткое резюме
Создание простого компонента уведомления в React — быстрый способ получить контролируемое поведение без лишних зависимостей. Начните с минимальной реализации (Notification.jsx + notification.css), затем при необходимости расширяйте до контейнера и интегрируйте автоматическое скрытие, анимации и accessibility. Если требования усложняются, рассмотрите проверенные библиотеки уведомлений.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента