Урок 12. Частые ошибки

📁 Раздел: Состояния и темы ⏱️ Время изучения: ~50 мин 🎯 Сложность: Средняя

⚡ Кратко

Только hover без focus, состояние одним цветом, hidden вместо opacity, забытый порядок peer.

Ошибка 1. hover без focus

Как ломается: с клавиатуры невозможно понять, где вы находитесь, а на сенсорном экране эффект вообще не появляется.

❌ Только мышь

<button class="hover:bg-slate-100">Действие</button>

✅ Мышь и клавиатура

<button class="hover:bg-slate-100
               focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-600">
  Действие
</button>

Ошибка 2. Скрывать кнопку через hidden

Как ломается: кнопка недоступна с клавиатуры — display: none убирает её из порядка обхода.

Как правильно: opacity-0 плюс focus-visible:opacity-100, как в решении задания 1. Либо оставлять кнопку видимой на сенсорных устройствах (pointer-coarse:opacity-100).

Ошибка 3. peer стоит после зависимого элемента

❌ Не сработает

<span class="peer-checked:text-emerald-600">Подпись</span>
<input type="checkbox" class="peer">

✅ Сначала peer

<input type="checkbox" class="peer">
<span class="peer-checked:text-emerald-600">Подпись</span>

Почему: селектор соседа (~) работает только вперёд. Если поменять порядок нельзя — используйте has-* у общего родителя.

Ошибка 4. Состояние передано только цветом

Как ломается: выбранный элемент неотличим для человека с нарушением цветовосприятия и для скринридера.

Как правильно: добавляйте второй признак — галочку, рамку, подпись — и правильный ARIA-атрибут (aria-selected, aria-current).

Ошибка 5. Слишком много вариантов в одной строке

❌ Нечитаемо

<button class="bg-white hover:bg-slate-50 focus:bg-slate-100 active:bg-slate-200 disabled:bg-slate-100 dark:bg-slate-800 dark:hover:bg-slate-700 dark:focus:bg-slate-600 md:hover:bg-slate-50">…</button>

✅ Вынести в компонент

// src/components/ui/button.tsx
const buttonVariants = cva("rounded-md px-4 py-2 text-sm font-medium", {
  variants: { variant: { default: "bg-slate-900 text-white hover:bg-slate-700" } },
})

Почему: набор состояний — это и есть описание компонента. Когда он стабилизировался, ему место в одном файле, а не в каждой разметке. Как это делается — уроки 15 и 18.

Ошибка 6. hover на мобильных

На сенсорных экранах hover либо не срабатывает, либо «залипает» после нажатия. Не прячьте за наведением ничего важного: считайте его украшением, а не способом добраться до функции.