15 KiB
🎨 UX/UI Улучшения - Документация
Этот документ описывает все внедренные UX/UI улучшения в проект S3 Lists Manager.
📋 Содержание
CSS Улучшения
Semantic Colors
Добавлена система семантических цветов для статусов и акцентов:
--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.
Использование:
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
Компонент для отображения изменения метрик со стрелками вверх/вниз.
Использование:
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
Компонент для отображения времени последнего сохранения с автообновлением.
Использование:
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
Компонент контекстного меню для действий с поддержкой правого клика.
Использование:
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.
Использование:
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:
import ProgressBar from './components/ProgressBar.jsx'
<ProgressBar
progress={65}
status="Загрузка данных..."
estimatedTime={45} // секунды
variant="primary"
striped
animated
/>
MultiStepProgress:
import { MultiStepProgress } from './components/ProgressBar.jsx'
<MultiStepProgress
steps={['Валидация', 'Обработка', 'Сохранение', 'Завершение']}
currentStep={1} // текущий шаг (0-indexed)
variant="success"
/>
7. MobileCardView
Компонент для отображения таблиц в виде карточек на мобильных с swipe gestures.
Использование:
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
Компонент для отображения горячих клавиш.
Использование:
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 операций
- Раскрывающиеся детали ошибки
- Отображение кода ошибки
Новое использование:
<ErrorAlert
message="Не удалось загрузить данные"
error={{ code: 'E_NETWORK', details: errorDetails }}
onRetry={fetchData}
onClose={() => setError(null)}
showDetails={true}
/>
EmptyState
Добавлены:
- Поддержка иллюстраций
- Различные размеры (small, default, large)
- Варианты цветов (success, info, warning)
- Анимация иллюстраций
Новое использование:
<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 на кнопках
Изменения в коде:
<StatCard
icon={IconWorld}
value={stats.domainsCount}
title="Доменов"
to="/domains"
trend={true}
previousValue={previousStats?.domainsCount}
/>
Примеры Использования
Пример 1: Форма с валидацией
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
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 с трендами
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
Вклад
При добавлении новых компонентов:
- Следуйте существующим паттернам
- Добавляйте JSDoc комментарии
- Обеспечьте accessibility
- Тестируйте на мобильных
- Обновляйте эту документацию
Версия: 1.0.0
Последнее обновление: 2025-01-15