Files
router-lists-ui/frontend/UX_IMPROVEMENTS.md
T

555 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎨 UX/UI Улучшения - Документация
Этот документ описывает все внедренные UX/UI улучшения в проект S3 Lists Manager.
## 📋 Содержание
1. [CSS Улучшения](#css-улучшения)
2. [Новые Компоненты](#новые-компоненты)
3. [Улучшенные Компоненты](#улучшенные-компоненты)
4. [Примеры Использования](#примеры-использования)
---
## CSS Улучшения
### Semantic Colors
Добавлена система семантических цветов для статусов и акцентов:
```css
--status-online: #2fb344;
--status-offline: #d63939;
--status-warning: #f59f00;
--status-unknown: #868e96;
--accent-primary: #206bc4;
--accent-danger: #d63939;
--accent-success: #2fb344;
```
### Улучшенная Типографика
- Увеличенный размер заголовков с лучшей читаемостью
- Оптимизированная межстрочная высота
- Letter-spacing для заголовков
### Enhanced Spacing
- Единая система отступов через CSS переменные
- Увеличенные padding в таблицах для лучшей читаемости
- Consistent spacing между карточками
### Интерактивные Элементы
- **Hover states**: кнопки поднимаются на 1px с тенью
- **Active states**: визуальный feedback при нажатии
- **Focus states**: улучшенные для accessibility
- **Touch targets**: минимум 44x44px на мобильных
---
## Новые Компоненты
### 1. Tooltip
Компонент для отображения подсказок с поддержкой keyboard shortcuts.
**Использование:**
```jsx
import Tooltip from './components/Tooltip.jsx'
<Tooltip content="Сохранить изменения" shortcut="Ctrl+S" position="top">
<button className="btn btn-primary">
<IconDeviceFloppy /> Сохранить
</button>
</Tooltip>
```
**Props:**
- `content` (string) - текст подсказки
- `shortcut` (string) - keyboard shortcut для отображения
- `position` (string) - позиция: 'top', 'bottom', 'left', 'right'
- `delay` (number) - задержка перед показом (ms)
---
### 2. TrendIndicator
Компонент для отображения изменения метрик со стрелками вверх/вниз.
**Использование:**
```jsx
import TrendIndicator from './components/TrendIndicator.jsx'
<TrendIndicator
value={1250}
previousValue={1180}
format="number" // или "percent"
inverse={false} // true если рост = плохо
/>
```
**Props:**
- `value` (number) - текущее значение
- `previousValue` (number) - предыдущее значение
- `format` ('number' | 'percent') - формат отображения
- `inverse` (boolean) - инвертировать цвета (рост = красный)
---
### 3. LastSaved
Компонент для отображения времени последнего сохранения с автообновлением.
**Использование:**
```jsx
import LastSaved from './components/LastSaved.jsx'
<LastSaved
timestamp="2025-01-15T10:30:00Z"
variant="compact" // 'default', 'badge', 'compact'
/>
```
**Варианты:**
- `default` - полный вид с иконкой
- `badge` - зеленый badge "Сохранено X мин назад"
- `compact` - компактный вид для toolbar
---
### 4. ContextMenu
Компонент контекстного меню для действий с поддержкой правого клика.
**Использование:**
```jsx
import ContextMenu from './components/ContextMenu.jsx'
import { IconEdit, IconTrash, IconCopy } from '@tabler/icons-react'
<ContextMenu
items={[
{ label: 'Редактировать', icon: IconEdit, onClick: handleEdit },
{ label: 'Копировать', icon: IconCopy, onClick: handleCopy },
{ divider: true },
{ label: 'Удалить', icon: IconTrash, onClick: handleDelete, variant: 'danger' }
]}
align="right"
>
{/* Trigger element или оставить пустым для кнопки с тремя точками */}
</ContextMenu>
```
---
### 5. ValidatedInput
Input с real-time валидацией и визуальным feedback.
**Использование:**
```jsx
import ValidatedInput from './components/ValidatedInput.jsx'
const validateDomain = (value) => {
const valid = /^([a-z0-9-]+\.)+[a-z]{2,}$/i.test(value)
return {
valid,
message: valid ? 'Домен валиден' : 'Введите корректный домен (example.com)'
}
}
<ValidatedInput
value={domain}
onChange={(e) => setDomain(e.target.value)}
validate={validateDomain}
label="Домен"
placeholder="example.com"
hint="Введите доменное имя без http://"
required
debounce={300}
/>
```
**Props:**
- `validate` (function) - функция валидации
- `debounce` (number) - задержка перед валидацией
- `showValidIcon` (boolean) - показывать иконку валидации
- `validateOnChange` (boolean) - валидировать при вводе или только при blur
---
### 6. ProgressBar & MultiStepProgress
Компоненты для отображения прогресса операций.
**ProgressBar:**
```jsx
import ProgressBar from './components/ProgressBar.jsx'
<ProgressBar
progress={65}
status="Загрузка данных..."
estimatedTime={45} // секунды
variant="primary"
striped
animated
/>
```
**MultiStepProgress:**
```jsx
import { MultiStepProgress } from './components/ProgressBar.jsx'
<MultiStepProgress
steps={['Валидация', 'Обработка', 'Сохранение', 'Завершение']}
currentStep={1} // текущий шаг (0-indexed)
variant="success"
/>
```
---
### 7. MobileCardView
Компонент для отображения таблиц в виде карточек на мобильных с swipe gestures.
**Использование:**
```jsx
import MobileCardView from './components/MobileCardView.jsx'
<MobileCardView
items={domains}
onItemClick={(item) => console.log('Clicked:', item)}
renderContent={(item) => (
<div>
<div className="fw-bold">{item.domain}</div>
<div className="text-muted small">{item.community}</div>
</div>
)}
actions={[
{ label: 'Редактировать', icon: IconEdit, onClick: handleEdit },
{ label: 'Удалить', icon: IconTrash, onClick: handleDelete, variant: 'danger' }
]}
/>
```
---
### 8. KeyboardShortcutHint
Компонент для отображения горячих клавиш.
**Использование:**
```jsx
import KeyboardShortcutHint, { ShortcutsList } from './components/KeyboardShortcutHint.jsx'
// Внутри кнопки:
<button className="btn btn-primary">
Сохранить
<KeyboardShortcutHint shortcut="Ctrl + S" />
</button>
// Список горячих клавиш:
<ShortcutsList
shortcuts={[
{ description: 'Сохранить изменения', keys: 'Ctrl + S' },
{ description: 'Отменить', keys: 'Ctrl + Z' },
{ description: 'Поиск', keys: 'Ctrl + F' }
]}
/>
```
---
## Улучшенные Компоненты
### ErrorAlert
Добавлены новые возможности:
- Кнопка "Копировать ошибку" для bug reports
- Кнопка "Повторить" для retry операций
- Раскрывающиеся детали ошибки
- Отображение кода ошибки
**Новое использование:**
```jsx
<ErrorAlert
message="Не удалось загрузить данные"
error={{ code: 'E_NETWORK', details: errorDetails }}
onRetry={fetchData}
onClose={() => setError(null)}
showDetails={true}
/>
```
---
### EmptyState
Добавлены:
- Поддержка иллюстраций
- Различные размеры (small, default, large)
- Варианты цветов (success, info, warning)
- Анимация иллюстраций
**Новое использование:**
```jsx
<EmptyState
icon={IconDatabase}
title="Нет доменов"
description="Начните с добавления первого домена"
size="large"
variant="info"
illustration="/illustrations/empty-state.svg"
action={<button className="btn btn-primary">Добавить домен</button>}
/>
```
---
### Pagination
Улучшения:
- Jump to Page для быстрого перехода (показывается при > 10 страниц)
- Иконки вместо текста для навигации
- Улучшенная accessibility
- Адаптивность для мобильных
**Автоматически используется везде, где был старый Pagination**
---
### Dashboard
Улучшения:
- StatCard теперь поддерживает trends
- Добавлен LastSaved в header
- Hover эффекты на карточках (card-hover)
- Tooltips на кнопках
**Изменения в коде:**
```jsx
<StatCard
icon={IconWorld}
value={stats.domainsCount}
title="Доменов"
to="/domains"
trend={true}
previousValue={previousStats?.domainsCount}
/>
```
---
## Примеры Использования
### Пример 1: Форма с валидацией
```jsx
function AddDomainForm() {
const [domain, setDomain] = useState('')
const [community, setCommunity] = useState('')
const validateDomain = (value) => ({
valid: /^([a-z0-9-]+\.)+[a-z]{2,}$/i.test(value),
message: 'Введите корректный домен'
})
const validateCommunity = (value) => ({
valid: /^\d+$/.test(value),
message: 'Введите числовой community'
})
return (
<form>
<ValidatedInput
value={domain}
onChange={(e) => setDomain(e.target.value)}
validate={validateDomain}
label="Домен"
placeholder="example.com"
required
/>
<ValidatedInput
value={community}
onChange={(e) => setCommunity(e.target.value)}
validate={validateCommunity}
label="Community"
placeholder="65000"
required
/>
<button type="submit" className="btn btn-primary">
Добавить
<KeyboardShortcutHint shortcut="Ctrl + Enter" />
</button>
</form>
)
}
```
### Пример 2: Таблица с ContextMenu и MobileCardView
```jsx
function DomainsTable({ domains, onEdit, onDelete }) {
return (
<>
{/* Desktop view */}
<div className="table-responsive d-none d-md-block">
<table className="table">
<tbody>
{domains.map(domain => (
<tr key={domain.id}>
<td>{domain.name}</td>
<td>{domain.community}</td>
<td>
<ContextMenu
items={[
{ label: 'Редактировать', icon: IconEdit, onClick: () => onEdit(domain) },
{ label: 'Удалить', icon: IconTrash, onClick: () => onDelete(domain), variant: 'danger' }
]}
/>
</td>
</tr>
))}
</tbody>
</table>
</div>
{/* Mobile view */}
<MobileCardView
items={domains}
renderContent={(domain) => (
<div>
<div className="fw-bold">{domain.name}</div>
<div className="text-muted small">{domain.community}</div>
</div>
)}
actions={[
{ label: 'Редактировать', icon: IconEdit, onClick: onEdit },
{ label: 'Удалить', icon: IconTrash, onClick: onDelete, variant: 'danger' }
]}
/>
</>
)
}
```
### Пример 3: Dashboard с трендами
```jsx
function Dashboard() {
const [stats, setStats] = useState({})
const [previousStats, setPreviousStats] = useState(null)
const [lastFetchTime, setLastFetchTime] = useState(null)
return (
<div>
<PageHeader
title="Панель"
actions={
<div className="d-flex gap-3">
<LastSaved timestamp={lastFetchTime} variant="compact" />
<Tooltip content="Обновить данные" shortcut="F5">
<button className="btn btn-outline-primary">
<IconRefresh /> Обновить
</button>
</Tooltip>
</div>
}
/>
<div className="row g-3">
<div className="col-md-3">
<StatCard
icon={IconWorld}
value={stats.domains}
title="Доменов"
trend={true}
previousValue={previousStats?.domains}
/>
</div>
</div>
</div>
)
}
```
---
## Best Practices
### 1. Accessibility
- Всегда добавляйте `aria-label` для иконочных кнопок
- Используйте semantic HTML
- Обеспечьте минимум 44x44px для touch targets на мобильных
- Добавляйте keyboard shortcuts для частых действий
### 2. Performance
- Используйте `useMemo` для тяжелых вычислений
- Debounce для валидации форм
- Lazy loading для больших списков
- Virtualization для таблиц > 1000 записей
### 3. User Experience
- Показывайте loading states для всех async операций
- Предоставляйте clear error messages с действиями
- Используйте optimistic updates где возможно
- Сохраняйте состояние форм при навигации
### 4. Mobile First
- Используйте MobileCardView для таблиц
- Убедитесь что все элементы кликабельны на touch screens
- Тестируйте swipe gestures
- Адаптируйте модальные окна для мобильных
---
## Roadmap
Планируемые улучшения:
- [ ] Виртуальный скроллинг для больших таблиц
- [ ] Drag & Drop для изменения порядка
- [ ] Сохранение пользовательских настроек
- [ ] Dark mode improvements
- [ ] Анимированные transitions между страницами
- [ ] PWA support
- [ ] Offline mode
---
## Вклад
При добавлении новых компонентов:
1. Следуйте существующим паттернам
2. Добавляйте JSDoc комментарии
3. Обеспечьте accessibility
4. Тестируйте на мобильных
5. Обновляйте эту документацию
---
**Версия:** 1.0.0
**Последнее обновление:** 2025-01-15