Тултипам нужна задержка, а потом её нужно уметь пропускать

Тултипам нужна задержка, а потом её нужно уметь пропускать

Автор блога рассказывает, как решал проблему всплывающих подсказок (tooltip) на страницах своего продукта FrontPrep, где рядом с вопросами для собеседований показаны логотипы компаний: при наведении на логотип должна появляться подсказка с названием компании. Изначально задержка перед показом подсказки была выставлена в 0 мс, из-за чего при простом перемещении курсора по странице подсказки мгновенно выскакивали над каждым логотипом на пути курсора. Автор добавил задержку в 200 мс перед открытием, это убрало случайные срабатывания, но создало новую проблему: в строках, где несколько логотипов компаний стоят рядом (одни и те же вопросы задают в разных компаниях), переход от одного логотипа к соседнему заставлял каждый раз заново ждать те же 200 мс, из-за чего интерфейс ощущался медленным.

Решение, паттерн с двумя состояниями страницы, «тёплым» и «холодным», и тремя числами. Первое: задержка открытия (open delay), 200 мс, столько подсказка ждёт перед появлением, если страница «холодная». Второе: «тёплое окно» (warm window), 300 мс; этот таймер запускается в момент, когда предыдущая подсказка закрывается, и пока он идёт, страница считается «тёплой», если за это время навести курсор на другой логотип, его подсказка откроется мгновенно, без задержки и анимации. Третье: задержка закрытия (close delay), 0 мс, то есть уход курсора с логотипа закрывает подсказку без промедления. Если «тёплое окно» истекает без нового наведения, страница снова становится «холодной», и следующая подсказка опять ждёт полные 200 мс, без этого шага первая же открытая подсказка отключила бы задержку для всей страницы навсегда.

Автор объясняет, почему выбраны именно эти числа: если задержка открытия меньше 150 мс, подсказка почти наверняка появится, даже когда курсор просто пролетает мимо логотипа по пути; если больше 250 мс, осознанная наводка курсора ощущается медленной и «сломанной», 200 мс выбраны как баланс между этими крайностями.

В статье разобрана реализация на React: единый провайдер контекста хранит состояние «тёплая ли страница» в ref-переменной (не в state, чтобы не перерисовывать все подсказки на странице). При открытии подсказки провайдер помечает страницу тёплой и отменяет запущенный таймер остывания; при закрытии, запускает 300-миллисекундный таймер остывания заново. Если курсор покидает логотип раньше, чем истекли 200 мс задержки, ожидающий таймер открытия просто отменяется, и подсказка не открывается вовсе. В реальном продукте FrontPrep подсказки построены на библиотеках Radix и Motion, но в посте показана упрощённая версия на чистом React; автор также ссылается на отдельную статью, где похожий эффект воспроизведён без JavaScript.

Завершает пост рассуждение автора о балансе между ИИ и человеческим вкусом: ИИ способен собрать полностью рабочую подсказку, но решить, отточена ли она, может только человек с наработанным вкусом и опытом, и такой вкус можно ускоренно перенимать через переиспользуемые «навыки» (skills) других разработчиков. В качестве примера автор оформил описанный паттерн в виде готового skill-файла для Claude (.claude/skills/tooltip/SKILL.md), с ним можно проверить код своего проекта на соответствие этому паттерну таймингов подсказок, вне зависимости от того, на какой библиотеке тултипы реализованы.

Ключевые факты

  • При задержке открытия 0 мс подсказки всплывали над каждым логотипом, который курсор проходил по пути, простое перемещение мыши превращалось в каскад подсказок
  • Плоская задержка в 200 мс убрала случайные срабатывания, но сделала переход между соседними логотипами в одном ряду ощутимо медленным
  • Решение, три таймера: задержка открытия 200 мс на «холодной» странице, 300-миллисекундное «тёплое окно» после закрытия подсказки, в течение которого следующая подсказка открывается мгновенно, и задержка закрытия 0 мс
  • Автор обосновывает выбор чисел экспериментально: меньше 150 мс, подсказка срабатывает на случайное движение курсора, больше 250 мс, наведение ощущается медленным
  • Паттерн оформлен в виде skill-файла для Claude, который можно применить, чтобы проверить тултипы в своём коде на соответствие этой схеме таймингов

Почему это важно

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

Кому это важно

Разбор адресован фронтенд-разработчикам и дизайнерам интерфейсов, которые строят собственные компоненты с подсказками, всплывающими меню или похожими hover-взаимодействиями, особенно там, где рядом друг с другом расположено много элементов, вызывающих одинаковую реакцию на наведение.

Как это применить

Схема воспроизводима буквально по трём числам: задержка открытия 200 мс, «тёплое окно» 300 мс, задержка закрытия 0 мс. В посте приведена реализация на React через контекст-провайдер с ref-флагом «тёплая ли страница»: открытие подсказки помечает страницу тёплой и отменяет таймер остывания, закрытие, запускает его заново на 300 мс; CSS отдельно отключает анимацию появления, если подсказка открылась «тёпло». Автор также упаковал паттерн в skill-файл для Claude, которым можно прогнать по своей кодовой базе, чтобы проверить, соответствуют ли уже существующие тултипы этой схеме.

Можно ли доверять

Это личный разбор автора на основе его собственного продукта (FrontPrep), с приведённым кодом, числами и объяснением, откуда они взяты экспериментально. Формальных исследований или сторонних измерений в тексте нет, это практический опыт одного разработчика, а не проверенный сторонними данными стандарт, но логика и код изложены прозрачно и проверяемы.

Риски и подводные камни

Числа (200/300/0 мс) подобраны под конкретный интерфейс автора и могут не подойти без проверки другому набору логотипов, размеров кнопок или скорости взаимодействия. Автор отдельно предупреждает: ИИ-инструмент способен собрать полностью рабочий тултип, но отличить рабочий результат от отточенного по-прежнему может только человек с развитым вкусом, слепое доверие к сгенерированному коду тултипа не гарантирует такой же выверенности тайминга.

«Клик, это всегда осознанное действие, а наведение курсора, нет. Курсор просто движется по странице туда, куда ему нужно, и по пути проходит над элементами, поэтому подсказка не может понять по одному наведению, хочет ли пользователь её открыть.»

— автор поста, в файле SKILL.md