- 74 brands: airbnb, stripe, apple, figma, linear, vercel, etc. - 147 files: DESIGN.md + README.md per brand (~2.1 MB) - Each DESIGN.md contains structured brand analysis (colors, typography, components) - Updated 00-overview.md with new design-systems directory
1183 lines
26 KiB
Markdown
1183 lines
26 KiB
Markdown
---
|
||
name: concepts/ux-guidelines-99
|
||
title: 99 UX Guidelines
|
||
description: 99 practical UX rules with code examples, sorted by category and severity.
|
||
tags: [ux, guidelines, accessibility, performance, mobile, forms, responsiveness, feedback]
|
||
source: ui-ux-pro-max-skill
|
||
---
|
||
|
||
# 99 UX Guidelines
|
||
|
||
Практические правила UX, проверенные на реальных продуктах. Каждое правило содержит: что делать, чего НЕ делать, код-пример.
|
||
|
||
## Severity Legend
|
||
|
||
| Бейдж | Значение |
|
||
|-------|----------|
|
||
| 🔴 High | Критично — влияет на доступность, конверсию, Core Web Vitals |
|
||
| 🟡 Medium | Важно — ухудшает UX, но не критично |
|
||
| 🟢 Low | Рекомендуется — мелкое улучшение |
|
||
|
||
---
|
||
|
||
## Navigation (6 правил)
|
||
|
||
### 1. Smooth Scroll — High
|
||
|
||
Anchor links должны прокручивать плавно к целевому разделу.
|
||
|
||
```css
|
||
html { scroll-behavior: smooth; }
|
||
```
|
||
|
||
❌ `<a href='#section'>` без CSS — прыжок
|
||
|
||
### 2. Sticky Navigation — Medium
|
||
|
||
Фиксированная навигация не должна перекрывать контент.
|
||
|
||
```html
|
||
<div class="pt-20"> <!-- если nav height = h-20 -->
|
||
```
|
||
|
||
❌ Нет компенсации padding
|
||
|
||
### 3. Active State — Medium
|
||
|
||
Текущая страница/секция должна быть визуально обозначена.
|
||
|
||
```html
|
||
<span class="text-primary border-b-2">Home</span>
|
||
```
|
||
|
||
❌ Все ссылки одного стиля
|
||
|
||
### 4. Back Button — High
|
||
|
||
На мобильных пользователи ожидают предсказуемого «назад».
|
||
|
||
```js
|
||
history.pushState(null, '', '/page');
|
||
```
|
||
|
||
❌ `location.replace()` — ломает историю
|
||
|
||
### 5. Deep Linking — Medium
|
||
|
||
URL должны отражать текущее состояние для шаринга.
|
||
|
||
```html
|
||
<!-- /page?sort=price&dir=asc -->
|
||
```
|
||
|
||
❌ Один URL для всех состояний
|
||
|
||
### 6. Breadcrumbs — Low
|
||
|
||
Показывать путь пользователя в иерархии сайта (3+ уровней).
|
||
|
||
```html
|
||
<nav><ol>
|
||
<li><a href="/">Home</a></li>
|
||
<li><a href="/cat">Category</a></li>
|
||
<li>Product</li>
|
||
</ol></nav>
|
||
```
|
||
|
||
❌ Только на глубоких вложенных страницах
|
||
|
||
---
|
||
|
||
## Animation (8 правил)
|
||
|
||
### 7. Excessive Motion — High
|
||
|
||
Слишком много анимаций отвлекают и вызывают укачивание.
|
||
|
||
✅ Анимировать 1-2 ключевых элемента на экран.
|
||
|
||
❌ `animate-bounce` на 5+ элементах
|
||
|
||
### 8. Duration Timing — Medium
|
||
|
||
Анимации должны ощущаться отзывчивыми, а не вялыми.
|
||
|
||
```css
|
||
transition-all duration-200; /* 150-300ms */
|
||
```
|
||
|
||
❌ `duration-1000` для UI
|
||
|
||
### 9. Reduced Motion — High
|
||
|
||
Уважать настройки пользователя о движении.
|
||
|
||
```css
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*, *::before, *::after {
|
||
animation-duration: 0.01ms !important;
|
||
transition-duration: 0.01ms !important;
|
||
}
|
||
}
|
||
```
|
||
|
||
❌ Нет проверки media query
|
||
|
||
### 10. Loading States — High
|
||
|
||
Показывать обратную связь во время асинхронных операций.
|
||
|
||
```html
|
||
<div class="animate-pulse"><div class="h-4 bg-gray-200 rounded w-3/4"></div></div>
|
||
```
|
||
|
||
❌ Пустой экран во время загрузки
|
||
|
||
### 11. Hover vs Tap — High
|
||
|
||
Hover-эффекты не работают на тач-устройствах.
|
||
|
||
```html
|
||
<button onClick={handler}>Click</button>
|
||
```
|
||
|
||
❌ Только `onMouseEnter` для важных действий
|
||
|
||
### 12. Continuous Animation — Medium
|
||
|
||
Бесконечные анимации отвлекают.
|
||
|
||
✅ `animate-spin` только на лоадерах.
|
||
|
||
❌ `animate-bounce` на иконках
|
||
|
||
### 13. Transform Performance — Medium
|
||
|
||
Некоторые CSS-свойства вызывают дорогостоящие repaints.
|
||
|
||
```css
|
||
transform: translateY(-10px); /* GPU-accelerated */
|
||
opacity: 0.8;
|
||
```
|
||
|
||
❌ Анимация `top: 10px` — trigger layout
|
||
|
||
### 14. Easing Functions — Low
|
||
|
||
Линейное движение выглядит роботизированным.
|
||
|
||
```css
|
||
transition-timing-function: ease-out; /* вход */
|
||
transition-timing-function: ease-in; /* выход */
|
||
```
|
||
|
||
❌ `linear` для UI
|
||
|
||
---
|
||
|
||
## Layout (7 правил)
|
||
|
||
### 15. Z-Index Management — High
|
||
|
||
Конфликты stacking context'а прячут элементы.
|
||
|
||
```html
|
||
<div class="z-10"><div class="z-20"></div></div>
|
||
```
|
||
|
||
❌ `z-[9999]` — хаос
|
||
|
||
### 16. Overflow Hidden — Medium
|
||
|
||
Скрытый overflow может обрезать контент.
|
||
|
||
```html
|
||
<div class="overflow-auto"><div class="w-max">...</div></div>
|
||
```
|
||
|
||
❌ `overflow-hidden` на контейнере с текстом
|
||
|
||
### 17. Fixed Positioning — Medium
|
||
|
||
Фиксированные элементы могут перекрывать друг друга.
|
||
|
||
```html
|
||
<header class="fixed top-0 left-0 right-0 h-20 z-50">
|
||
<main class="pt-20">
|
||
```
|
||
|
||
❌ Несколько overlapping fixed без gap
|
||
|
||
### 18. Stacking Context — Medium
|
||
|
||
Новый stacking context сбрасывает z-index.
|
||
|
||
```html
|
||
<!-- Parent creates new stacking context -->
|
||
<div class="relative z-10">
|
||
<div class="z-50"></div> <!-- только внутри parent -->
|
||
</div>
|
||
```
|
||
|
||
❌ `z-index: 9999` не работает через контекст
|
||
|
||
### 19. Content Jumping — High
|
||
|
||
Сдвиг layout при загрузке контента — дёргает.
|
||
|
||
```html
|
||
<img src="..." class="aspect-video" alt="..." />
|
||
```
|
||
|
||
❌ Нет размеров на изображениях — контент прыгает
|
||
|
||
### 20. Viewport Units — Medium
|
||
|
||
`100vh` проблематичен на мобильных (адресная строка).
|
||
|
||
```html
|
||
<div class="min-h-dvh"> <!-- dynamic viewport height -->
|
||
```
|
||
|
||
❌ `h-screen` на мобильных — обрезка контента
|
||
|
||
### 21. Container Width — Medium
|
||
|
||
Слишком широкий текст трудно читать.
|
||
|
||
```html
|
||
<p class="max-w-prose">...</p> <!-- ~65ch -->
|
||
```
|
||
|
||
❌ Текст на всю ширину viewport
|
||
|
||
---
|
||
|
||
## Touch (6 правил)
|
||
|
||
### 22. Touch Target Size — High
|
||
|
||
Маленькие кнопки трудно нажимать точно.
|
||
|
||
```html
|
||
<button class="min-h-[44px] min-w-[44px]">Tap</button>
|
||
```
|
||
|
||
❌ `w-6 h-6` — 24px, ниже минимума
|
||
|
||
### 23. Touch Spacing — Medium
|
||
|
||
Расстояние между тач-целями — минимум 8px.
|
||
|
||
```html
|
||
<button class="gap-2">Buttons</button>
|
||
```
|
||
|
||
❌ `gap-0` или `gap-1` между кнопками
|
||
|
||
### 24. Gesture Conflicts — Medium
|
||
|
||
Кастомные жесты могут конфликтовать с системой.
|
||
|
||
```html
|
||
<!-- Vertical scroll primary, horizontal only in carousels -->
|
||
<div class="overflow-x-auto overflow-y-visible">
|
||
```
|
||
|
||
❌ Горизонтальный свайп на основном контенте
|
||
|
||
### 25. Tap Delay — Medium
|
||
|
||
300ms tap delay ощущается как лаг.
|
||
|
||
```css
|
||
button { touch-action: manipulation; }
|
||
```
|
||
|
||
❌ Нет touch-оптимизации — 300ms задержка
|
||
|
||
### 26. Pull to Refresh — Low
|
||
|
||
Случайное обновление — раздражает.
|
||
|
||
```html
|
||
<body style="overscroll-behavior: contain;">
|
||
```
|
||
|
||
❌ Стандартное поведение (pull-down на всём)
|
||
|
||
### 27. Haptic Feedback — Low
|
||
|
||
Тактильная обратная связь улучшает взаимодействие.
|
||
|
||
```js
|
||
if ('vibrate' in navigator) navigator.vibrate(10);
|
||
```
|
||
|
||
❌ Вибрация при каждом тапе
|
||
|
||
---
|
||
|
||
## Interaction (8 правил)
|
||
|
||
### 28. Focus States — High
|
||
|
||
Клавиатурные пользователи видят фокус только через visible focus.
|
||
|
||
```html
|
||
<button class="focus:ring-2 focus:ring-blue-500">
|
||
```
|
||
|
||
❌ `outline-none` без замены
|
||
|
||
### 29. Hover States — Medium
|
||
|
||
Визуальная обратная связь на интерактивных элементах.
|
||
|
||
```html
|
||
<button class="hover:bg-gray-100 cursor-pointer">
|
||
```
|
||
|
||
❌ Нет hover-стиля на кликабельных элементах
|
||
|
||
### 30. Active States — Medium
|
||
|
||
Немедленная обратная связь при нажатии.
|
||
|
||
```html
|
||
<button class="active:scale-95 transition-transform">
|
||
```
|
||
|
||
❌ Нет active state
|
||
|
||
### 31. Disabled States — Medium
|
||
|
||
Чётко указывать неинтерактивные элементы.
|
||
|
||
```html
|
||
<button disabled class="opacity-50 cursor-not-allowed">
|
||
```
|
||
|
||
❌ Disabled выглядит как enabled
|
||
|
||
### 32. Loading Buttons — High
|
||
|
||
Предотвращать двойную отправку формы.
|
||
|
||
```html
|
||
<button disabled={loading} className={loading ? 'animate-pulse' : ''}>
|
||
{loading ? 'Processing...' : 'Submit'}
|
||
</button>
|
||
```
|
||
|
||
❌ Кнопка кликабельна во время загрузки
|
||
|
||
### 33. Error Feedback — High
|
||
|
||
Пользователь должен знать об ошибке.
|
||
|
||
```html
|
||
<div class="text-red-600 text-sm mt-1">Invalid email</div>
|
||
```
|
||
|
||
❌ Тихий fail — нет индикации
|
||
|
||
### 34. Success Feedback — Medium
|
||
|
||
Подтверждать успешные действия.
|
||
|
||
```html
|
||
<div className="text-green-600 flex items-center gap-2">
|
||
<CheckIcon /> Saved successfully
|
||
</div>
|
||
```
|
||
|
||
❌ Действие завершается без подтверждения
|
||
|
||
### 35. Confirmation Dialogs — High
|
||
|
||
Подтверждать деструктивные действия.
|
||
|
||
```html
|
||
<button onClick={() => setShowModal(true)}>Delete</button>
|
||
<!-- Modal: Are you sure? -->
|
||
```
|
||
|
||
❌ Удаление без подтверждения
|
||
|
||
---
|
||
|
||
## Accessibility (10 правил)
|
||
|
||
### 36. Color Contrast — High
|
||
|
||
Текст должен быть читаемым на фоне.
|
||
|
||
```css
|
||
/* #333 on white = 7:1 ✅ | #999 on white = 2.8:1 ❌ */
|
||
.color { color: #333333; background: #ffffff; }
|
||
```
|
||
|
||
❌ `#999` на `#ffffff` — fails WCAG AA
|
||
|
||
### 37. Color Only — High
|
||
|
||
Не передавать информацию только цветом.
|
||
|
||
```html
|
||
<span class="text-red-600">
|
||
<AlertIcon /> Error: insufficient funds
|
||
</span>
|
||
```
|
||
|
||
❌ Только красная рамка без текста
|
||
|
||
### 38. Alt Text — High
|
||
|
||
У изображений должен быть текстовый эквивалент.
|
||
|
||
```html
|
||
<img src="dog.jpg" alt="Dog playing in park" />
|
||
```
|
||
|
||
❌ `alt=""` для контентных изображений
|
||
|
||
### 39. Heading Hierarchy — Medium
|
||
|
||
Экранные читалки используют заголовки для навигации.
|
||
|
||
```html
|
||
<h1>Home</h1><h2>About</h2><h3>Team</h3>
|
||
```
|
||
|
||
❌ `h1` → `h4` — пропуск уровней
|
||
|
||
### 40. ARIA Labels — High
|
||
|
||
Интерактивные элементы нужны доступные имена.
|
||
|
||
```html
|
||
<button aria-label="Close menu"><X /></button>
|
||
```
|
||
|
||
❌ `<button><Icon/></button>` без aria-label
|
||
|
||
### 41. Keyboard Navigation — High
|
||
|
||
Весь функционал доступен через клавиатуру.
|
||
|
||
```html
|
||
<a href="#" tabindex="0">Link</a>
|
||
```
|
||
|
||
❌ Недоступные элементы (tabindex не совпадает с визуальным порядком)
|
||
|
||
### 42. Screen Reader — Medium
|
||
|
||
Контент должен иметь смысл при чтении вслух.
|
||
|
||
```html
|
||
<nav>...</nav><main>...</main><article>...</article>
|
||
```
|
||
|
||
❌ `<div>` для всего — "div soup"
|
||
|
||
### 43. Form Labels — High
|
||
|
||
Каждый input должен иметь associated label.
|
||
|
||
```html
|
||
<label for="email">Email</label>
|
||
<input type="email" id="email" />
|
||
```
|
||
|
||
❌ Только `placeholder='Email'`
|
||
|
||
### 44. Error Messages — High
|
||
|
||
Ошибки должны анонсироваться.
|
||
|
||
```html
|
||
<div role="alert" class="text-red-600">Error message</div>
|
||
```
|
||
|
||
❌ Только красная рамка — screen reader не прочитает
|
||
|
||
### 45. Skip Links — Medium
|
||
|
||
Клавиатурные пользователи должны пропускать навигацию.
|
||
|
||
```html
|
||
<a href="#main" className="sr-only focus:not-sr-only">
|
||
Skip to main content
|
||
</a>
|
||
```
|
||
|
||
❌ 100 тапов до контента
|
||
|
||
---
|
||
|
||
## Performance (8 правил)
|
||
|
||
### 46. Image Optimization — High
|
||
|
||
Большие изображения замедляют загрузку.
|
||
|
||
```html
|
||
<img src="small.webp" srcset="small.webp 400w, medium.webp 800w, large.webp 1600w"
|
||
sizes="(max-width: 640px) 100vw, 50vw" alt="..." />
|
||
```
|
||
|
||
❌ 4000px изображение для 400px display
|
||
|
||
### 47. Lazy Loading — Medium
|
||
|
||
Загружать контент по мере необходимости.
|
||
|
||
```html
|
||
<img src="below-fold.jpg" loading="lazy" alt="..." />
|
||
```
|
||
|
||
❌ Все изображения `loading="eager"`
|
||
|
||
### 48. Code Splitting — Medium
|
||
|
||
Большие бандлы замедляют начальный рендер.
|
||
|
||
```js
|
||
const Dashboard = lazy(() => import('./Dashboard'));
|
||
```
|
||
|
||
❌ Весь код в main bundle
|
||
|
||
### 49. Caching — Medium
|
||
|
||
Повторные визиты должны быть быстрыми.
|
||
|
||
```http
|
||
Cache-Control: public, max-age=31536000, immutable
|
||
```
|
||
|
||
❌ Каждый запрос на сервер
|
||
|
||
### 50. Font Loading — Medium
|
||
|
||
Шрифты не должны блокировать рендер.
|
||
|
||
```css
|
||
font-display: swap;
|
||
```
|
||
|
||
❌ FOIT (Flash of Invisible Text)
|
||
|
||
### 51. Third Party Scripts — Medium
|
||
|
||
Внешние скрипты блокируют рендер.
|
||
|
||
```html
|
||
<script async src="https://analytics.js/tracker.js"></script>
|
||
```
|
||
|
||
❌ `<script src="...">` в head без async
|
||
|
||
### 52. Bundle Size — Medium
|
||
|
||
Большой JavaScript замедляет интерактивность.
|
||
|
||
```bash
|
||
# Bundle analyzer
|
||
npx webpack-bundle-analyzer stats.json
|
||
```
|
||
|
||
❌ Без мониторинга размера бандла
|
||
|
||
### 53. Render Blocking — Medium
|
||
|
||
CSS/JS могут блокировать первый рендер.
|
||
|
||
```html
|
||
<link rel="preload" href="/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||
```
|
||
|
||
❌ Весь CSS в head блокирует paint
|
||
|
||
---
|
||
|
||
## Forms (9 правил)
|
||
|
||
### 54. Input Labels — High
|
||
|
||
Каждый input — видимый label.
|
||
|
||
```html
|
||
<label class="block text-sm font-medium mb-1" for="email">Email</label>
|
||
<input id="email" type="email" />
|
||
```
|
||
|
||
❌ Только `placeholder='Email'`
|
||
|
||
### 55. Error Placement — Medium
|
||
|
||
Ошибки — рядом с полем.
|
||
|
||
```html
|
||
<input /><div class="text-red-500 text-sm mt-1">Invalid email</div>
|
||
```
|
||
|
||
❌ Все ошибки вверху формы
|
||
|
||
### 56. Inline Validation — Medium
|
||
|
||
Валидация при blur (не только при submit).
|
||
|
||
```js
|
||
input.addEventListener('blur', validate);
|
||
```
|
||
|
||
❌ Только `onSubmit` валидация
|
||
|
||
### 57. Input Types — Medium
|
||
|
||
Использовать правильные типы input.
|
||
|
||
```html
|
||
<input type="email" />
|
||
<input type="tel" />
|
||
<input type="number" />
|
||
```
|
||
|
||
❌ `type='text'` для email
|
||
|
||
### 58. Autofill Support — Medium
|
||
|
||
Помогать браузерам автозаполнять.
|
||
|
||
```html
|
||
<input autocomplete="email" />
|
||
<input autocomplete="current-password" />
|
||
```
|
||
|
||
❌ `autocomplete='off'` везде
|
||
|
||
### 59. Required Indicators — Medium
|
||
|
||
Обозначать обязательные поля.
|
||
|
||
```html
|
||
<label><span class="after:content-['*'] after:text-red-500">Email</span></label>
|
||
```
|
||
|
||
❌ Без индикации — пользователь гадает
|
||
|
||
### 60. Password Visibility — Medium
|
||
|
||
Позволять видеть пароль при вводе.
|
||
|
||
```html
|
||
<input type={showPassword ? 'text' : 'password'} />
|
||
<button onClick={() => setShowPassword(!showPassword)}>
|
||
{showPassword ? 'Hide' : 'Show'}
|
||
</button>
|
||
```
|
||
|
||
❌ Пароль всегда скрыт
|
||
|
||
### 61. Submit Feedback — High
|
||
|
||
Подтверждать статус отправки формы.
|
||
|
||
```html
|
||
{loading && <span>Submitting...</span>}
|
||
{success && <span className="text-green-600">Saved!</span>}
|
||
```
|
||
|
||
❌ Клик — нет ответа
|
||
|
||
### 62. Input Affordance — Medium
|
||
|
||
Inputs должны выглядеть интерактивными.
|
||
|
||
```html
|
||
<input class="border rounded px-3 py-2 bg-white" />
|
||
```
|
||
|
||
❌ Borderless inputs — выглядят как текст
|
||
|
||
### 63. Mobile Keyboards — Medium
|
||
|
||
Показывать правильную клавиатуру.
|
||
|
||
```html
|
||
<input inputmode="numeric" pattern="[0-9]*" />
|
||
```
|
||
|
||
❌ Текстовая клавиатура для чисел
|
||
|
||
---
|
||
|
||
## Responsive (8 правил)
|
||
|
||
### 64. Mobile First — Medium
|
||
|
||
Сначала мобильный, потом улучшаем.
|
||
|
||
```css
|
||
/* Default mobile styles */
|
||
.container { padding: 1rem; }
|
||
@media (min-width: 768px) {
|
||
.container { padding: 2rem; } /* tablet+ */
|
||
}
|
||
```
|
||
|
||
❌ Desktop-first с `max-width` query
|
||
|
||
### 65. Breakpoint Testing — Medium
|
||
|
||
Тестировать на всех экранах.
|
||
|
||
```html
|
||
<!-- Test at: 320, 375, 414, 768, 1024, 1440 -->
|
||
```
|
||
|
||
❌ Только на своём устройстве
|
||
|
||
### 66. Touch Friendly — High
|
||
|
||
Мобильные лейауты — большие touch targets.
|
||
|
||
```html
|
||
<button class="md:min-h-[48px] min-h-[56px]">
|
||
```
|
||
|
||
❌ Desktop-sized targets на мобильных
|
||
|
||
### 67. Readable Font Size — High
|
||
|
||
Минимум 16px body на мобильных.
|
||
|
||
```html
|
||
<p class="text-base md:text-lg">...</p> <!-- 16px+ -->
|
||
```
|
||
|
||
❌ `text-xs` для body текста
|
||
|
||
### 68. Viewport Meta — High
|
||
|
||
Установить viewport для мобильных.
|
||
|
||
```html
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
```
|
||
|
||
❌ Нет viewport meta
|
||
|
||
### 69. Horizontal Scroll — High
|
||
|
||
Избегать горизонтального скролла.
|
||
|
||
```html
|
||
<div class="max-w-full overflow-x-hidden">
|
||
```
|
||
|
||
❌ Горизонтальный скролл на мобильных
|
||
|
||
### 70. Image Scaling — Medium
|
||
|
||
Изображения — пропорционально контейнеру.
|
||
|
||
```html
|
||
<img class="max-w-full h-auto" />
|
||
```
|
||
|
||
❌ `width='800'` fixed — overflow
|
||
|
||
### 71. Table Handling — Medium
|
||
|
||
Таблицы — горизонтальный скролл на мобильных.
|
||
|
||
```html
|
||
<div class="overflow-x-auto">
|
||
<table class="min-w-full">...</table>
|
||
</div>
|
||
```
|
||
|
||
❌ Таблица выходит за viewport
|
||
|
||
---
|
||
|
||
## Typography (6 правил)
|
||
|
||
### 72. Line Height — Medium
|
||
|
||
Адекватный line-height улучшает читаемость.
|
||
|
||
```html
|
||
<p class="leading-relaxed">...</p> <!-- 1.625 -->
|
||
```
|
||
|
||
❌ `leading-none` (1) для body
|
||
|
||
### 73. Line Length — Medium
|
||
|
||
Длинные строки трудно читать.
|
||
|
||
```html
|
||
<p class="max-w-prose">...</p> <!-- ~65ch -->
|
||
```
|
||
|
||
❌ Текст на всю ширину viewport
|
||
|
||
### 74. Font Size Scale — Medium
|
||
|
||
Консистентный тип-масштаб.
|
||
|
||
```html
|
||
<!-- 12 14 16 18 24 32 40 48 56 64 -->
|
||
```
|
||
|
||
❌ Произвольные размеры
|
||
|
||
### 75. Font Loading — Medium
|
||
|
||
Шрифты без сдвигов layout.
|
||
|
||
```css
|
||
font-display: swap;
|
||
/* + похожий fallback */
|
||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||
```
|
||
|
||
❌ Нет fallback шрифта
|
||
|
||
### 76. Contrast Readability — High
|
||
|
||
Body текст — хороший контраст.
|
||
|
||
```html
|
||
<p class="text-gray-900 bg-white">...</p>
|
||
```
|
||
|
||
❌ `text-gray-400` на `gray-100`
|
||
|
||
### 77. Heading Clarity — Medium
|
||
|
||
Заголовки — отличаются от body.
|
||
|
||
```html
|
||
<h2 class="text-2xl font-bold">...</h2>
|
||
<p class="text-base font-normal">...</p>
|
||
```
|
||
|
||
❌ Заголовок того же размера, что body
|
||
|
||
---
|
||
|
||
## Feedback (6 правил)
|
||
|
||
### 78. Loading Indicators — High
|
||
|
||
Показать статус системы во время ожидания.
|
||
|
||
```html
|
||
{isLoading && <Skeleton className="h-4 w-3/4 animate-pulse" />}
|
||
```
|
||
|
||
❌ Замороженный UI
|
||
|
||
### 79. Empty States — Medium
|
||
|
||
Направлять пользователя, когда нет контента.
|
||
|
||
```html
|
||
<div className="text-center py-12">
|
||
<p className="text-gray-500">No items yet. <a href="/create" className="text-blue-600">Create one!</a></p>
|
||
</div>
|
||
```
|
||
|
||
❌ Пустое белое пространство
|
||
|
||
### 80. Error Recovery — Medium
|
||
|
||
Помогать восстанавливаться после ошибок.
|
||
|
||
```html
|
||
<div className="text-red-600">
|
||
Failed to load. <button className="underline">Try again</button>
|
||
</div>
|
||
```
|
||
|
||
❌ Сообщение об ошибке без пути назад
|
||
|
||
### 81. Progress Indicators — Medium
|
||
|
||
Показывать прогресс multi-step.
|
||
|
||
```html
|
||
<div className="flex gap-2">
|
||
<div className="h-2 flex-1 bg-blue-600 rounded"></div>
|
||
<div className="h-2 flex-1 bg-gray-200 rounded">Step 2 of 4</div>
|
||
</div>
|
||
```
|
||
|
||
❌ Нет step info
|
||
|
||
### 82. Toast Notifications — Medium
|
||
|
||
Всплывающие сообщения для не-критичной инфы.
|
||
|
||
```html
|
||
<div className="fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-3 rounded shadow-lg"
|
||
autoDismiss={3000}>
|
||
Item saved!
|
||
</div>
|
||
```
|
||
|
||
❌ Toast, который не исчезает
|
||
|
||
### 83. Confirmation Messages — Medium
|
||
|
||
Подтверждать успешные действия.
|
||
|
||
```html
|
||
<div className="text-green-600 flex items-center gap-2">
|
||
<CheckIcon /> Saved successfully
|
||
</div>
|
||
```
|
||
|
||
❌ Без подтверждения
|
||
|
||
---
|
||
|
||
## Content (4 правила)
|
||
|
||
### 84. Truncation — Medium
|
||
|
||
Обрезать длинный контент.
|
||
|
||
```html
|
||
<p className="line-clamp-2 cursor-pointer" onClick={expand}>
|
||
Long text...
|
||
</p>
|
||
```
|
||
|
||
❌ Overflow: hidden — обрезка без expand
|
||
|
||
### 85. Date Formatting — Low
|
||
|
||
Использовать локализованные форматы дат.
|
||
|
||
```js
|
||
new Date().toLocaleDateString('ru-RU', { dateStyle: 'medium' })
|
||
// "20 июн 2026 г."
|
||
```
|
||
|
||
❌ `01/02/03` — неоднозначно
|
||
|
||
### 86. Number Formatting — Low
|
||
|
||
Форматировать большие числа.
|
||
|
||
```js
|
||
(1234567).toLocaleString('ru-RU') // "1 234 567"
|
||
// или (1.2M)
|
||
```
|
||
|
||
❌ `1234567` — без разделителей
|
||
|
||
### 87. Placeholder Content — Low
|
||
|
||
Использовать реалистичный placeholder.
|
||
|
||
```html
|
||
<input defaultValue="john@example.com" />
|
||
```
|
||
|
||
❌ Lorem ipsum везде
|
||
|
||
---
|
||
|
||
## Onboarding / Search / Data Entry (3 правила)
|
||
|
||
### 88. User Freedom — Medium
|
||
|
||
Пользователь должен уметь пропустить туториал.
|
||
|
||
```html
|
||
<button className="text-gray-500 underline">Skip Tutorial</button>
|
||
```
|
||
|
||
❌ Запертый overlay до конца
|
||
|
||
### 89. Search Autocomplete — Medium
|
||
|
||
Помогать находить результаты быстрее.
|
||
|
||
```html
|
||
<input type="search" debounced onChange={showSuggestions} />
|
||
```
|
||
|
||
❌ Полное вбивание + Enter
|
||
|
||
### 90. No Results — Medium
|
||
|
||
Показывать «Нет результатов» с подсказками.
|
||
|
||
```html
|
||
<div>
|
||
<p>Try searching for: shoes, hats, bags</p>
|
||
</div>
|
||
```
|
||
|
||
❌ «No results found.» — тупик
|
||
|
||
### 91. Bulk Actions — Low
|
||
|
||
Массовое редактирование.
|
||
|
||
```html
|
||
<div className="flex items-center gap-4">
|
||
<input type="checkbox" className="row-checkbox" />
|
||
<div className="flex gap-2">
|
||
<button className="btn-sm">Delete Selected</button>
|
||
<button className="btn-sm">Archive</button>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
❌ Одиночные действия на каждую строку
|
||
|
||
---
|
||
|
||
## AI Interaction (4 правила)
|
||
|
||
### 92. AI Disclaimer — High
|
||
|
||
Пользователи должны знать, что общаются с ИИ.
|
||
|
||
```html
|
||
<div className="flex items-center gap-2 text-sm text-gray-500 mb-4">
|
||
<BotIcon /> AI Assistant
|
||
</div>
|
||
```
|
||
|
||
❌ Фейковое человеческое имя без лейбла
|
||
|
||
### 93. Streaming — Medium
|
||
|
||
Потоковая подача текста вместо ожидания 100%.
|
||
|
||
```html
|
||
<div className="typewriter">
|
||
{streamedText}
|
||
<span className="animate-pulse">▌</span>
|
||
</div>
|
||
```
|
||
|
||
❌ Spinner до 100% completion
|
||
|
||
### 94. Spatial UI — High (VisionOS)
|
||
|
||
Элементы должны реагировать на gaze.
|
||
|
||
```swift
|
||
// VisionOS
|
||
.hoverEffect(.scale, enabled: true)
|
||
```
|
||
|
||
❌ Статичный элемент до pinch
|
||
|
||
### 95. Depth Layering — Medium (VisionOS)
|
||
|
||
Z-глубина для контента.
|
||
|
||
```swift
|
||
.material(.thin)
|
||
.offsetZ(10)
|
||
```
|
||
|
||
❌ Плоские непрозрачные панели
|
||
|
||
---
|
||
|
||
## Sustainability (2 правила)
|
||
|
||
### 96. Auto-Play Video — Medium
|
||
|
||
Видео потребляет данные и энергию.
|
||
|
||
```html
|
||
<video playsInline muted preload="none" poster="cover.jpg">
|
||
<source src="video.mp4" type="video/mp4" />
|
||
</video>
|
||
```
|
||
|
||
❌ `autoplay loop` — трафик
|
||
|
||
### 97. Asset Weight — Medium
|
||
|
||
Тяжёлые 3D/изображения увеличивают carbon footprint.
|
||
|
||
```js
|
||
const Model = lazy(() => import('./model.glb?draco')); // Draco compression
|
||
```
|
||
|
||
❌ Raw `.obj` файлы 50MB
|
||
|
||
---
|
||
|
||
## Additional AI Interaction (1 правило)
|
||
|
||
### 98. Feedback Loop — Low
|
||
|
||
ИИ нуждается в обратной связи для улучшения.
|
||
|
||
```html
|
||
<div className="flex gap-2 mt-4">
|
||
<button className="btn-sm">👍 Helpful</button>
|
||
<button className="btn-sm">👎 Not helpful</button>
|
||
<button className="btn-sm">Regenerate</button>
|
||
</div>
|
||
```
|
||
|
||
❌ Только текст, без возможности оценки
|
||
|
||
---
|
||
|
||
## Accessibility (1 правило)
|
||
|
||
### 99. Motion Sensitivity — High
|
||
|
||
Параллакс/Scroll-jacking вызывает тошноту.
|
||
|
||
```css
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.parallax { transform: none !important; }
|
||
}
|
||
```
|
||
|
||
❌ `ScrollTrigger.create()` без проверки prefers-reduced-motion
|
||
|
||
---
|
||
|
||
## Quick Reference by Category
|
||
|
||
| Category | Count | High Severity |
|
||
|----------|-------|---------------|
|
||
| Navigation | 6 | 1 |
|
||
| Animation | 8 | 2 |
|
||
| Layout | 7 | 1 |
|
||
| Touch | 6 | 1 |
|
||
| Interaction | 8 | 2 |
|
||
| Accessibility | 11 | 7 |
|
||
| Performance | 8 | 1 |
|
||
| Forms | 10 | 2 |
|
||
| Responsive | 8 | 3 |
|
||
| Typography | 6 | 1 |
|
||
| Feedback | 6 | 1 |
|
||
| Content | 4 | 0 |
|
||
| Onboarding/Search/Data | 4 | 0 |
|
||
| AI Interaction | 4 | 1 |
|
||
| Sustainability | 2 | 0 |
|
||
| Spatial UI | 2 | 1 |
|
||
| **Total** | **99** | **27** 🔴 |
|