Список, который вы теряете каждый раз, когда открываете заметку

Productivity

Этот цикл вы проходили сотню раз и не замечали.

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

Двадцать просмотренных заметок — это сорок переходов и девятнадцать попыток снова сориентироваться. Загрузка страницы тут ни при чём. Работали вы со списком, а каждая открытая заметка его сбрасывает.

Теперь заметки открываются в боковой панели поверх списка.

Что изменилось

Кликните на заметку в сетке, таблице или на доске, и она откроется в панели справа. Список остаётся ровно там, где был: та же прокрутка, те же фильтры, те же колонки доски, то же множественное выделение. J и K переходят к следующей и предыдущей заметке в том порядке, в каком вы их сейчас видите. Esc закрывает панель.

Панель — не превью. Это тот же редактор с тем же автосохранением, теми же тегами и свойствами, теми же разделами «Дочерние заметки», «Связанные заметки» и «Похожие заметки». Всё, что можно сделать с заметкой на её отдельной странице, можно сделать и в панели.

Полная страница никуда не делась: кнопка Открыть на всю страницу в шапке панели или клик средней кнопкой мыши по карточке.

Три решения, на которых всё держится

Панель — не модальное окно

Очевидная реализация — диалог: затемняющий слой, ловушка фокуса, блокировка прокрутки. Я сознательно не сделал ничего из этого.

Затемняющий слой убил бы весь смысл. Список остаётся на экране, чтобы им можно было пользоваться: прокручивать, перетаскивать карточку в другую колонку, выделять рамкой пачку заметок, пока одна открыта. Тусклый слой, который глотает клики, показывает картинку вашего списка, а не сам список.

Поэтому панель немодальная: без затемнения, без ловушки фокуса, без блокировки прокрутки, и клик снаружи её не закрывает. Закрываете её всегда вы сами: крестиком ✕, клавишей Esc, кнопкой «назад» в браузере или кликом по шву на левом краю панели.

Про шов подробнее. Он там уже был: за него панель тянут, чтобы сделать шире. Нажатие на шов без движения мыши раньше ничего не делало, поэтому теперь такой клик сворачивает панель. Тот же жест работает на левой боковой панели и на панели ИИ-чата, а левая панель заодно получила переключатель ⌘\.

Открытая заметка живёт в URL

Панелью управляет параметр запроса — /notes?peek=<id>, — а не состояние компонента.

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

Карточки остались ссылками

Каждая карточка заметки и строка таблицы — по-прежнему настоящая <a href="/notes/...">. Перехватывается только обычный клик левой кнопкой.

Именно поэтому клик средней кнопкой, правый клик → «Открыть ссылку в новой вкладке» и «Копировать адрес ссылки» работают без единой строки кода. <div> с onClick тихо сломал бы их все, и никто не завёл бы баг: люди просто перестали бы пробовать.

Два бага, о которых стоит рассказать

Защита сохранения срабатывала на каждую букву

Заметки сохраняются автоматически, и есть защита, которая перехватывает переход, пока сохранение не завершилось, чтобы нельзя было уйти из заметки посреди записи.

С панелью у этой защиты резко вырос радиус поражения. Поиск в шапке делает переход на каждое нажатие клавиши: каждый символ — новый URL. Если вы печатали в поиске, пока в панели была открыта несохранённая заметка, защита срабатывала на каждый символ: над списком мелькало модальное окно «Сохраняем заметку…», и сохранение запускалось на каждую букву.

Теперь защита блокирует только переходы, после которых эта заметка пропадает с экрана: закрытие, переключение на другую заметку, уход с маршрута. Пересортировка списка под панелью не уводит из заметки, поэтому ничего не срабатывает.

Стрелка подсказки закрыла ручку перетаскивания

Шов для изменения ширины панели — четыре пикселя. Наведите на него, и появится подсказка: тяните, чтобы изменить ширину, или кликните, чтобы закрыть.

Только подсказка рисует стрелку — маленький повёрнутый SVG, — а подсказки в Notez по умолчанию прилегают к своему триггеру вплотную. Так стрелка легла ровно поверх четырёхпиксельного шва. Вы наводили курсор на шов, нажимали, и mousedown попадал в стрелку, а не в ручку. Панель не меняла ширину и не закрывалась.

Поучительно здесь то, как баг нашёлся. Его поймал end-to-end-тест, и поймал только потому, что двигает настоящую мышь. Раньше я проверял вручную и отправлял синтетические события прямо в элемент: так hit-testing обходится полностью, и проверка бодро сообщает, что всё работает. Какой элемент лежит под курсором, спрашивает только настоящий указатель.

document.elementFromPoint() на шве вернул <svg>, и этим всё объяснилось.

Где панель не используется

  • На телефонах заметка по-прежнему открывается на всю страницу. Полноэкранная выдвижная панель — та же страница, только с кнопкой «назад» похуже.

  • На доске переход к следующей и предыдущей заметке не выходит за пределы колонки. У доски нет единого порядка между колонками, поэтому J и K идут по колонке той карточки, которую вы открыли.

  • Ссылки внутри заметки — плашки [[, граф связей, свойства-связи — по-прежнему открывают полную страницу. Переход по ссылке ведёт куда-то ещё, а не к следующему пункту списка. Панель нужна, чтобы идти по списку, а не чтобы уходить от него.

На этом различии держится вся функция: карточки заметок и строки таблицы открываются в панели, любой другой путь к заметке открывает страницу. Одно предложение — и понятно, что сделает любой клик.


Все подробности — в справке об организации заметок и о горячих клавишах.

Читайте также