Интерфейс дерева комментариев. Сравниваем Хабр и клиенты Reddit; переделываем Хабр

Я люблю древовидные комментарии. Для них сложно найти лучшую альтернативу. Интерфейсы форумов из двухтысячных выглядят слишком огромными для сообщений в два-три предложения. В линейном потоке сообщений мессенджера бывает сложно понять, кому кто отвечает. А имиджборды мне приходилось на полном серьезе учиться читать.

Одна из самых старых и самых популярных площадок с деревьями комментариев — это Reddit. Правда, большая часть его пользователей едина в одном: его интерфейс ужасен. Но его API открыто, поэтому на выбор есть множество клиентских приложений, особенно для мобильных телефонов — на картинке ниже Joey, Relay, Slide и Boost, а есть еще и другие. Их авторы — как правило, и сами недовольные стандартным интерфейсом Реддита — потратили много времени и сил на поиск удобного интерфейса для комментариев. И большая их часть пришла к очень похожим вариантам дизайна.

В этой статье я хочу разобрать, чем мне так нравится такой дизайн деревьев комментариев, сравнить его с деревьями комментариев мобильной версии Хабра, и попробовать пофантазировать, как бы могли выглядеть комменты Хабра в интерфейсе клиентов для Reddit.

Основы

Какой паттерн интерфейса я называю в этой статье «деревом комментариев»?

  • Для каждого комментария есть не более одного другого, с которым он связан как продолжение диалога.

    Будем называть такой комментарий родительским, а комментарий-ответ — дочерним. Строго говоря, это не всегда именно ответ. Например, это может быть продолжение предыдущего комментария того же автора.

  • Дочерние комментарии расположены «ниже» в иерархии на странице, чем родительские.

    Как правило, это реализуется отступами слева, но почти всегда есть еще и другие маркеры. Из-за несоответствия этому признаку я не называю комменты в твиттере древовидными.

В пример приведу как раз те интерфейсы, которые хотел бы сегодня разобрать. Слева — комментарии на Хабре, справа — комментарии в одном из клиентов Реддита (Boost).

А теперь давайте разберем их по косточкам.

Отступы

В первую очередь, можно обратить внимание на то, как по-разному отображается иерархия комментариев. На Хабре это довольно большие отступы слева, плюс точки по числу уровней вложенности (до определенного максимума):

Комментарии в Boost тоже используют отступы, но намного меньшие. Это позволяет им использовать намного больше пространства для, собственно, текста. У Boost примерно такой же потолок глубины отступов — правда, продолжение он предлагает читать на другой странице. Но даже при такой вложенности текст на экране все еще занимает намного большую часть места.

Как бы выглядел Хабр с такими отступами? На реальном телефоне поменять стили сложновато, поэтому я использовал DevTools в Firefox, чтобы проверить. Включил Responsive Design Mode с пресетом Galaxy S10/S10+ Android 11 и набрал в консоли следующее:

$$(".tm-comment-thread__comment > *")
  .forEach(el => el.style.cssText += "margin-left: 0;")
$$(".tm-comment-thread")
  .forEach(el => el.style.cssText += "position: unset; margin-left: 5px;")
$$(".tm-comment-thread__breadcrumbs")
  .forEach(el => el.style.cssText += "display: none;")

Сразу видно, что теперь на один экран влезают не два комментария, а уже три. И они не ютятся на правой половине экрана. Но намного хуже стала считываться вложенность. Как с этим борется Boost?

Индикаторы вложенности

Посмотрим еще раз на комментарии в обоих приложениях. И там, и там есть дополнительные индикаторы вложенности: кружочки на Хабре, полосы в Boost. Но на Хабре, как мне кажется, они считываются гораздо хуже. Давайте сравним, и даже дадим Хабру фору — уберем влияние цвета:

Кружочки на Хабре расположены слишком далеко от кружочков соседних комментариев, и их слишком много, чтобы посчитать. В итоге, основную работу по обозначению глубины берут на себя отступы. Думаю, поэтому их и сделали настолько большими.

Boost же использует вертикальные полосы на всю высоту комментария. Из-за того, что верхние и нижние концы этих полос очень близко к соседним, намного легче сравнить их вложенность.

$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += `border-left: solid 5px grey; margin-left: -10px;`)
$$(".tm-comment-thread__children")
  .forEach(el => el.style.cssText += "padding-top: 0;")
$$(".tm-comment-thread")
  .forEach(el => el.style.cssText += "margin-bottom: 0;")
$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += "padding-top: 10px; border-top: solid 1px grey;")

Посмотрим, что получилось. Слева — оригинал, в центре — до применения последнего блока кода, справа — после.

Цвет как индикатор глубины вложенности

Еще одним важным индикатором вложенности в Boost является цвет полосы слева. Основной принцип прост — комментарии на близких, но различных уровнях вложенности должны иметь разные цвета, причем чем ближе вложенность, тем ближе цвет. Давайте накостылим это для мобильного Хабра:

var depth = el => {
  let d
  for (d = 0; el; el = el.parentElement) {
    if (el.classList.contains("tm-comment-thread")) d++
  }
  return d
}

var color = el => `hsl(${30 * depth(el)} 70% 60%)`

$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += `border-left: solid 5px ${color(el)};`)

Панель действий

В Boost панель с кнопками действий для комментариев по умолчанию скрыта и открывается по длинному нажатию на комментарий. Это позволяет использовать еще больше пространства под сам текст комментариев. На Хабре, видимо, по инерции с десктопного интерфейса, кнопки отображаются под каждым из комментов.

Важную метаинформацию, вроде даты и рейтинга, Boost отображает справа от имени пользователя, там много пространства для этого. Для нашей демонстрации я немножко считерю, и скрою футер совсем. Просто представьте в своем воображении числа справа от ника.

$$(".tm-comment-footer").forEach(el => el.style.cssText += "display: none;")

Результаты

Что у нас получилось? На один экран теперь влезает чуть ли не в два раза больше комментариев, при этом их глубина и вложенность считываются как минимум не хуже. Я не уверен, вписывается ли такой дизайн в стиль Хабра, но как минимум Реддит так читать очень удобно. Да и в целом, мне сложно придумать более удачный дизайн для дерева комментариев, чем тот, к которому — возможно, даже независимо! — пришли почти все приложения для Реддита.

Весь мой костыльный код из статьи

Проверялось в Responsive Design Mode из Firefox с пресетом Galaxy S10/S10+ Android 11.

// Отступы
$$(".tm-comment-thread__comment > *")
  .forEach(el => el.style.cssText += "margin-left: 0;")
$$(".tm-comment-thread")
  .forEach(el => el.style.cssText += "position: unset; margin-left: 5px;")
$$(".tm-comment-thread__breadcrumbs")
  .forEach(el => el.style.cssText += "display: none;")

// Индикаторы вложенности
$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += `border-left: solid 5px grey; margin-left: -10px;`)
$$(".tm-comment-thread__children")
  .forEach(el => el.style.cssText += "padding-top: 0;")
$$(".tm-comment-thread")
  .forEach(el => el.style.cssText += "margin-bottom: 0;")
$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += "padding-top: 10px; border-top: solid 1px grey;")

// Цвет как индикатор глубины вложенности
var depth = el => {
  let d
  for (d = 0; el; el = el.parentElement) {
    if (el.classList.contains("tm-comment-thread")) d++
  }
  return d
}

var color = el => `hsl(${30 * depth(el)} 70% 60%)`

$$(".tm-comment-thread__comment")
  .forEach(el => el.style.cssText += `border-left: solid 5px ${color(el)};`)

// Панель действий
$$(".tm-comment-footer").forEach(el => el.style.cssText += "display: none;")

© Habrahabr.ru