Files
router-lists-ui/UX_UI_IMPROVEMENTS.md
T

16 KiB
Raw Blame History

🎨 UX/UI Улучшения Router Lists UI - 2025

📋 Обзор

Данный документ описывает комплексные UX/UI улучшения, внесенные в проект Router Lists UI. Все компоненты разработаны исключительно на стилях Tabler UI без использования сторонних UI библиотек.


РЕАЛИЗОВАННЫЕ УЛУЧШЕНИЯ

🎯 ВЫСОКИЙ ПРИОРИТЕТ

1. Оптимизация навигации и информационной архитектуры

📍 Улучшенный компонент Breadcrumbs

Файл: frontend/src/components/Breadcrumbs.jsx

Новые возможности:

  • Кнопка "Назад" с сохранением состояния навигации
  • Динамические счетчики результатов в breadcrumbs
  • Отображение информации об активных фильтрах
  • Автоматический подсчет записей с правильными склонениями

Использование:

<Breadcrumbs 
  items={[
    { label: 'Главная', to: '/dashboard' },
    { label: 'Домены', count: 1250 }
  ]}
  showBack={true}
  filterInfo="Community: Cloudflare"
  count={1250}
/>

2. Улучшения таблиц и списков данных

🔖 SavedFilters - Сохраненные фильтры

Файл: frontend/src/components/SavedFilters.jsx

Возможности:

  • Сохранение комбинаций фильтров в localStorage
  • Быстрое применение сохраненных фильтров
  • Удаление неактуальных фильтров
  • Отображение даты создания фильтра

Использование:

<SavedFilters
  pageKey="domains" // уникальный ключ страницы
  currentFilters={{ searchTerm, filterCommunity, sortField }}
  onApplyFilter={(filters) => {
    setSearchTerm(filters.searchTerm)
    setFilterCommunity(filters.filterCommunity)
  }}
/>
☑️ BulkActionsBar - Массовые операции

Файл: frontend/src/components/BulkActionsBar.jsx

Возможности:

  • Выбор множества элементов через чекбоксы
  • Кнопка "Выбрать все" / "Снять выбор"
  • Массовое удаление, редактирование, экспорт
  • Sticky позиционирование при скролле
  • Кастомные действия через props

Использование:

<BulkActionsBar
  selectedCount={selectedItems.size}
  totalCount={totalItems}
  onSelectAll={() => selectAll()}
  onDeselectAll={() => clearSelection()}
  onDelete={() => handleBulkDelete()}
  onExport={() => handleBulkExport()}
  customActions={[
    { 
      icon: IconEdit, 
      label: 'Изменить community', 
      onClick: handleBulkEditCommunity 
    }
  ]}
/>

3. Формы и валидация

✓ ValidatedInput - Input с inline валидацией

Файл: frontend/src/components/ValidatedInput.jsx

Возможности:

  • Real-time валидация с debounce
  • Визуальные индикаторы (галочка/крестик)
  • Подсказки при ошибках
  • Поддержка required полей
  • Автофокус

Использование:

<ValidatedInput
  label="IP адрес"
  value={ip}
  onChange={setIp}
  onValidate={(value) => {
    const valid = /^(\d{1,3}\.){3}\d{1,3}$/.test(value)
    return {
      valid,
      message: valid 
        ? 'IP адрес корректен' 
        : 'Введите IPv4 (например: 1.1.1.1)'
    }
  }}
  helpText="Введите IPv4 адрес"
  required
/>

4. Feedback и уведомления

🔔 ToastContainer - Система toast уведомлений

Файлы:

  • frontend/src/components/ToastContainer.jsx
  • Интеграция в frontend/src/App.jsx

Возможности:

  • 4 типа уведомлений: success, error, warning, info
  • Автозакрытие с настраиваемой длительностью
  • Действия в уведомлениях (кнопки "Отменить", "Повторить")
  • Анимированное появление/исчезновение
  • Глобальный доступ через window.toast

Использование:

// Через hook
const toast = useToast()
toast.success('Данные сохранены')
toast.error('Ошибка соединения', { duration: 0 }) // не закроется автоматически
toast.warning('Проверьте данные', { duration: 5000 })
toast.info('Обновление доступно', {
  actions: [
    { label: 'Обновить', onClick: () => window.location.reload() }
  ]
})

// Через window (обратная совместимость)
window.toast.success('Успех!')
ProgressIndicator - Индикаторы прогресса

Файл: frontend/src/components/ProgressIndicator.jsx

Компоненты:

  1. ProgressIndicator - полный индикатор с кнопкой отмены
  2. LinearProgress - компактный линейный
  3. CircularProgress - кольцевой индикатор

Использование:

// Полный индикатор
<ProgressIndicator
  current={45}
  total={100}
  message="Обработка доменов..."
  variant="blue"
  onCancel={() => cancelOperation()}
/>

// Линейный
<LinearProgress 
  progress={75} 
  message="Загрузка..." 
  variant="green" 
/>

// Кольцевой
<CircularProgress 
  progress={60} 
  size={64} 
  variant="purple" 
/>
💀 Skeleton Loaders - Улучшенные загрузчики

Файл: frontend/src/components/TableSkeleton.jsx

Компоненты:

  1. TableSkeleton - для таблиц (с поддержкой чекбоксов)
  2. CardSkeleton - для карточек статистики
  3. ListSkeleton - для списков
  4. FormSkeleton - для форм

Использование:

import TableSkeleton, { CardSkeleton, ListSkeleton, FormSkeleton } from './components/TableSkeleton'

{loading ? (
  <TableSkeleton rows={10} cols={5} hasCheckbox={true} />
) : (
  <table>...</table>
)}

5. Keyboard Shortcuts и Command Palette

⌨️ CommandPalette - Глобальный поиск (Ctrl+K)

Файлы:

  • frontend/src/components/CommandPalette.jsx
  • Интеграция в frontend/src/App.jsx

Возможности:

  • Открытие по Ctrl+K / Cmd+K
  • Навигация стрелками ↑↓
  • Фильтрация команд по keywords
  • Быстрый переход по страницам
  • Подсветка активной команды

Горячие клавиши:

  • Ctrl+K - Открыть command palette
  • - Навигация по списку
  • Enter - Выполнить команду
  • Esc - Закрыть
📋 KeyboardShortcutsButton - Справка по горячим клавишам

Использование: Добавлена кнопка в навбар

Список горячих клавиш:

  • Ctrl+K - Поиск команд
  • Ctrl+N - Добавить новую запись
  • Ctrl+S - Сохранить
  • Ctrl+F - Поиск по таблице
  • Esc - Закрыть / Отменить
  • - Навигация
  • Enter - Подтвердить

🎨 СРЕДНИЙ ПРИОРИТЕТ

6. Визуальная иерархия

📊 Sparkline - Мини-графики

Файл: frontend/src/components/Sparkline.jsx

Компоненты:

  1. Sparkline - линейный график
  2. SparklineWithTrend - с процентом изменения
  3. SparklineBar - столбчатый график

Возможности:

  • Чистый SVG без библиотек
  • Настраиваемые цвета и размеры
  • Опциональная заливка под графиком
  • Отображение точек на графике

Использование:

// Простой sparkline
<Sparkline 
  data={[10, 20, 15, 30, 25, 40]} 
  width={100} 
  height={30}
  strokeColor="#206bc4"
  fillColor="#206bc4"
/>

// С трендом
<SparklineWithTrend
  data={[100, 105, 110, 120]}
  label="за 7 дней"
  showPercentage={true}
/>

// Столбчатый
<SparklineBar
  data={[5, 8, 3, 12, 7]}
  width={100}
  height={30}
  barColor="#2fb344"
/>

🚀 КАК ИСПОЛЬЗОВАТЬ

Интеграция в существующие страницы

Пример: DomainsNewManager с новыми компонентами

import { useState } from 'react'
import Breadcrumbs from './components/Breadcrumbs'
import SavedFilters from './components/SavedFilters'
import BulkActionsBar from './components/BulkActionsBar'
import ValidatedInput from './components/ValidatedInput'
import TableSkeleton from './components/TableSkeleton'
import { useToast } from './components/ToastContainer'

function DomainsNewManager() {
  const [selectedItems, setSelectedItems] = useState(new Set())
  const [loading, setLoading] = useState(false)
  const [filters, setFilters] = useState({ searchTerm: '', community: '' })
  const toast = useToast()

  const handleBulkDelete = async () => {
    try {
      await api.delete('/domains-new/bulk', { ids: Array.from(selectedItems) })
      toast.success(`Удалено ${selectedItems.size} доменов`)
      setSelectedItems(new Set())
    } catch (e) {
      toast.error('Ошибка удаления', { duration: 0 })
    }
  }

  return (
    <div>
      {/* Breadcrumbs с кнопкой назад */}
      <Breadcrumbs
        items={[
          { label: 'Главная', to: '/dashboard' },
          { label: 'Данные' },
          { label: 'Домены', count: items.length }
        ]}
        showBack={true}
        filterInfo={filters.community ? `Community: ${filters.community}` : null}
      />

      {/* Сохраненные фильтры */}
      <div className="mb-3">
        <SavedFilters
          pageKey="domains"
          currentFilters={filters}
          onApplyFilter={setFilters}
        />
      </div>

      {/* Bulk actions */}
      <BulkActionsBar
        selectedCount={selectedItems.size}
        totalCount={items.length}
        onSelectAll={() => setSelectedItems(new Set(items.map(i => i.id)))}
        onDeselectAll={() => setSelectedItems(new Set())}
        onDelete={handleBulkDelete}
        onExport={handleBulkExport}
      />

      {/* Таблица с skeleton loader */}
      {loading ? (
        <TableSkeleton rows={10} cols={3} hasCheckbox={true} />
      ) : (
        <table className="table">
          {/* таблица */}
        </table>
      )}
    </div>
  )
}

📐 ДИЗАЙН-СИСТЕМА

Цветовая палитра Tabler

// Основные цвета
$blue: #206bc4;    // primary
$azure: #4299e1;   // info
$indigo: #4263eb;
$purple: #ae3ec9;
$pink: #d6336c;
$red: #d63939;     // danger
$orange: #f76707;  // warning
$yellow: #f59f00;
$lime: #74b816;
$green: #2fb344;   // success
$teal: #0ca678;
$cyan: #17a2b8;

// Semantic colors
$primary: $blue;
$success: $green;
$warning: $orange;
$danger: $red;
$info: $azure;

Использование badges

// Успех
<span className="badge bg-green-lt text-green">Активен</span>

// Ошибка
<span className="badge bg-red-lt text-red">Офлайн</span>

// Предупреждение
<span className="badge bg-yellow-lt text-yellow">Внимание</span>

// Информация
<span className="badge bg-blue-lt text-blue">123</span>

Иконки (Tabler Icons)

Все иконки из @tabler/icons-react:

import { 
  IconCheck, 
  IconX, 
  IconAlertTriangle,
  IconWorld,
  IconServer,
  IconFilter 
} from '@tabler/icons-react'

<IconCheck size={20} className="text-success" />

📊 СТАТИСТИКА УЛУЧШЕНИЙ

Созданные компоненты

Компонент Файл Строк кода Статус
Breadcrumbs Breadcrumbs.jsx 82
SavedFilters SavedFilters.jsx 170
BulkActionsBar BulkActionsBar.jsx 110
ToastContainer ToastContainer.jsx 160
ValidatedInput ValidatedInput.jsx 120
ProgressIndicator ProgressIndicator.jsx 180
Sparkline Sparkline.jsx 150
CommandPalette CommandPalette.jsx 250
Итого 8 компонентов ~1222 строки 100%

Улучшенные компоненты

  • TableSkeleton.jsx - добавлены CardSkeleton, ListSkeleton, FormSkeleton (+70 строк)
  • App.jsx - интеграция ToastContainer и CommandPalette

🎯 СЛЕДУЮЩИЕ ШАГИ (pending)

7. Графики и визуализация данных

  • Timeline chart для Dashboard (динамика за месяц)
  • Pie chart для распределения по community
  • Heatmap активности
  • Улучшенный GraphView с zoom controls

8. Мобильная адаптивность

  • Card view для таблиц на мобильных
  • Swipe actions (свайп для удаления/редактирования)
  • Bottom navigation для мобилок
  • Адаптивные модалки (bottom sheet)

💡 РЕКОМЕНДАЦИИ ПО ИСПОЛЬЗОВАНИЮ

1. Замена старых alert'ов на Toast

// Было
setSuccess('Данные сохранены')
setError('Ошибка')

// Стало
toast.success('Данные сохранены')
toast.error('Ошибка')

2. Добавление bulk operations в таблицы

  1. Добавить состояние const [selected, setSelected] = useState(new Set())
  2. Добавить чекбоксы в <th> и <td>
  3. Добавить <BulkActionsBar /> над таблицей

3. Использование ValidatedInput вместо обычного input

Заменить все критичные input'ы (IP, email, домены) на <ValidatedInput />

4. Skeleton loaders вместо спиннеров

// Вместо
{loading && <div className="spinner-border" />}

// Использовать
{loading ? <TableSkeleton /> : <Table />}

🐛 ИЗВЕСТНЫЕ ОГРАНИЧЕНИЯ

  1. SavedFilters хранит данные в localStorage (ограничение 5-10MB)
  2. BulkActionsBar sticky позиция может конфликтовать с другими sticky элементами
  3. CommandPalette не поддерживает вложенные команды
  4. Sparkline не имеет интерактивности (нет hover tooltips)

📝 ЗАКЛЮЧЕНИЕ

Все компоненты разработаны с использованием чистого Tabler UI без сторонних библиотек. Компоненты:

  • Полностью адаптивны
  • Поддерживают темную тему
  • Доступны (ARIA labels, keyboard navigation)
  • Легковесны (нет зависимостей)
  • Расширяемы через props

Итого внедрено: 8 новых компонентов, улучшено 3 существующих, добавлено ~1300 строк кода.


Версия документа: 1.0
Дата: 2 октября 2025
Автор: AI Assistant (Claude Sonnet 4.5)