feat: Добавить новые компоненты и улучшения UX/UI, включая Breadcrumbs с динамическими фильтрами, ToastContainer для уведомлений и CommandPalette для глобального поиска. Обновить TableSkeleton с анимацией и добавить новые skeleton компоненты для карточек, списков и форм. Обновить документацию по новым компонентам и улучшениям.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s

This commit is contained in:
2025-10-02 18:02:22 +07:00
parent 495063a510
commit 339144fb11
12 changed files with 1950 additions and 24 deletions
+531
View File
@@ -0,0 +1,531 @@
# 🎨 UX/UI Улучшения Router Lists UI - 2025
## 📋 Обзор
Данный документ описывает комплексные UX/UI улучшения, внесенные в проект Router Lists UI. Все компоненты разработаны **исключительно на стилях Tabler UI** без использования сторонних UI библиотек.
---
## ✅ РЕАЛИЗОВАННЫЕ УЛУЧШЕНИЯ
### 🎯 ВЫСОКИЙ ПРИОРИТЕТ
#### 1. Оптимизация навигации и информационной архитектуры
##### 📍 Улучшенный компонент Breadcrumbs
**Файл**: `frontend/src/components/Breadcrumbs.jsx`
**Новые возможности**:
- ✅ Кнопка "Назад" с сохранением состояния навигации
- ✅ Динамические счетчики результатов в breadcrumbs
- ✅ Отображение информации об активных фильтрах
- ✅ Автоматический подсчет записей с правильными склонениями
**Использование**:
```jsx
<Breadcrumbs
items={[
{ label: 'Главная', to: '/dashboard' },
{ label: 'Домены', count: 1250 }
]}
showBack={true}
filterInfo="Community: Cloudflare"
count={1250}
/>
```
---
#### 2. Улучшения таблиц и списков данных
##### 🔖 SavedFilters - Сохраненные фильтры
**Файл**: `frontend/src/components/SavedFilters.jsx`
**Возможности**:
- ✅ Сохранение комбинаций фильтров в localStorage
- ✅ Быстрое применение сохраненных фильтров
- ✅ Удаление неактуальных фильтров
- ✅ Отображение даты создания фильтра
**Использование**:
```jsx
<SavedFilters
pageKey="domains" // уникальный ключ страницы
currentFilters={{ searchTerm, filterCommunity, sortField }}
onApplyFilter={(filters) => {
setSearchTerm(filters.searchTerm)
setFilterCommunity(filters.filterCommunity)
}}
/>
```
##### ☑️ BulkActionsBar - Массовые операции
**Файл**: `frontend/src/components/BulkActionsBar.jsx`
**Возможности**:
- ✅ Выбор множества элементов через чекбоксы
- ✅ Кнопка "Выбрать все" / "Снять выбор"
- ✅ Массовое удаление, редактирование, экспорт
- ✅ Sticky позиционирование при скролле
- ✅ Кастомные действия через props
**Использование**:
```jsx
<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 полей
- ✅ Автофокус
**Использование**:
```jsx
<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`
**Использование**:
```jsx
// Через 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** - кольцевой индикатор
**Использование**:
```jsx
// Полный индикатор
<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** - для форм
**Использование**:
```jsx
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 без библиотек
- ✅ Настраиваемые цвета и размеры
- ✅ Опциональная заливка под графиком
- ✅ Отображение точек на графике
**Использование**:
```jsx
// Простой 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 с новыми компонентами
```jsx
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
```scss
// Основные цвета
$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
```jsx
// Успех
<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`:
```jsx
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
```jsx
// Было
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 вместо спиннеров
```jsx
// Вместо
{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)