Files
gitmost/docs/backlog/comments-panel-density.md
vvzvlad e7b7f48d35 docs(backlog): add AI chat collapse and comment density docs
Add two new backlog documentation files:
- ai-chat-collapse-on-page-focus.md describing auto‑collapse behavior for the AI chat window.
- comments-panel-density.md outlining UI density improvements for the comments panel.
2026-06-18 20:41:17 +03:00

12 KiB

Панель комментариев: сделать плотнее (меньше воздуха, меньше шрифт)

Статус: план, код не менялся. Чисто UI-задача на клиенте (CSS + пропсы Mantine). Бэкенда, схемы данных и логики не касается.

Суть

Сейчас панель комментариев (правый aside, вкладка «Comments») выглядит разреженной: крупные отступы между карточками и внутри них, большой межстрочный интервал, тело комментария набрано базовым размером редактора (16px). На узкой колонке это «съедает» вертикаль — на экран помещается мало комментариев, много пустого места.

Хотим: уплотнить раскладку — уменьшить внутренние/внешние отступы карточек, зазор «аватар ↔ текст», вертикальный ритм редактора — и уменьшить шрифт тела комментария, имени автора и цитаты выделения. Цель — больше комментариев на экран без потери читабельности.

Где сейчас живёт «воздух» (точные места)

Вся вёрстка панели — в фиче apps/client/src/features/comment/.

1. Карточка комментария — comment-list-with-tabs.tsx

  • renderComments, обёртка каждого треда (~строки 121-129): <Paper shadow="sm" radius="md" p="sm" mb="sm" withBorder>p="sm" (12px внутренний отступ) и mb="sm" (12px зазор между комментариями).
  • Разделитель перед редактором ответа (~строка 148): <Divider my={4} />.
  • Вкладки (Tabs.Panel pt="xs", строки 226 и 245) и пустое состояние (<Center py="xl">, строки 228 и 247) — второстепенные источники воздуха.
  • Нижнее поле ввода PageCommentInput (строки ~361-405): paddingTop = sm, paddingBottom: 25, аватар marginTop: 10, кнопка отправки спозиционирована bottom: 30. Эти величины связаны (плавающая кнопка над полем) — трогать осторожно.

2. Элемент комментария — comment-list-item.tsx

  • Внешняя обёртка (строка 119): <Box ref={ref} pb="xs"> — 10px снизу у каждого элемента (включая вложенные ответы).
  • Шапка «аватар ↔ контент» (строка 120): <Group> без gap → дефолтный gap="md" (16px) между аватаром и блоком с именем/телом. Это главный горизонтальный «воздух».
  • Имя автора (строка 129): <Text size="sm" fw={500} lineClamp={1}> — 14px.
  • Время (строки 157-161): уже <Text size="xs"> (12px) — оставить.
  • Цитата выделения (строка 180): <Text size="sm">{comment?.selection}</Text> — 14px, внутри блока .textSelection.

3. Стили — comment.module.css

  • .textSelection (строки 9-21): margin-top: 4px, padding: 8px.
  • .commentEditor .ProseMirror :global(.ProseMirror) (строки 35-44): margin-top: 10px, margin-bottom: 2px, паддинги 6px. font-size не задан — тело комментария наследует глобальный .ProseMirror { font-size: var(--mantine-font-size-md) } (16px) из core.css:10.
  • .wrapper (строки 1-3) — padding: md, в коде не используется (можно игнорировать или удалить заодно).

4. Внешняя рамка панели (ВНИМАНИЕ: общая) — aside.tsx

  • <Box p="md"> (строка 47) и шапка <Group ... mb="md"> с <Title order={2} size="h6"> (строки 50-51) дают 16px отступа по краям панели и под заголовком. Этот контейнер общий для трёх вкладок aside (comments / toc / details). Менять его — значит уплотнить заодно «Содержание» и «Детали». См. «Открытые вопросы».

Шкалы Mantine в проекте без переопределений (theme.ts палитру/контраст меняет, но не размеры): шрифт xs=12px / sm=14px / md=16px; spacing xs=10 / sm=12 / md=16.

Решение (точечное, в границах фичи comment)

Базовый объём — только компоненты features/comment/, чтобы вкладки «Содержание»/«Детали» (общий aside.tsx) не задеть. Уплотнение рамки панели — отдельный опциональный пункт (см. ниже).

Правки по файлам

comment-list-with-tabs.tsx

  • <Paper> в renderComments: p="sm"p="xs", mb="sm"mb="xs" (12 → 10px). shadow="sm", radius="md", withBorder — оставить.
  • <Divider my={4} />my={2}.

comment-list-item.tsx

  • <Box ref={ref} pb="xs">pb={6}.
  • Шапка <Group> (аватар + контент, строка 120): добавить gap="xs" (дефолтные 16px → 10px). НЕ трогать внутренние <Group justify="space-between"> и <Group gap="xs">, у них зазор уже задан.
  • Имя: <Text size="sm" ...>size="xs". fw={500} и lineClamp={1} — оставить (см. «иерархия шрифта» ниже).
  • Цитата: <Text size="sm">{comment?.selection}</Text>size="xs".

comment.module.css

  • В .ProseMirror :global(.ProseMirror) добавить font-size: var(--mantine-font-size-sm); (16 → 14px) и line-height: 1.4;, заменить margin-top: 10pxmargin-top: 4px. Остальные декларации (border-radius, max-width, white-space, word-break, паддинги, margin-bottom) — без изменений.
  • .textSelection: margin-top: 4px2px, padding: 8px6px.

Эскиз (ключевой фрагмент CSS)

.commentEditor {
  /* ... */
  .ProseMirror :global(.ProseMirror) {
    border-radius: var(--mantine-radius-sm);
    max-width: 100%;
    white-space: pre-wrap;
    word-break: break-word;
    padding-left: 6px;
    padding-right: 6px;
    /* Denser comments: shrink body text from the global 16px ProseMirror size
       to 14px and tighten the rhythm vs. the comment header. */
    font-size: var(--mantine-font-size-sm);
    line-height: 1.4;
    margin-top: 4px;   /* was 10px */
    margin-bottom: 2px;
  }
}

.textSelection {
  margin-top: 2px;   /* was 4px */
  padding: 6px;      /* was 8px */
  /* ...остальное без изменений... */
}

Тонкие моменты / edge cases

  • Не трогать aside.tsx в базовом объёме. Его p="md" и шапка общие для вкладок toc/details — правка уплотнит и их. Если это нежелательно, держать изменения строго внутри features/comment/.
  • Иерархия шрифта (принято). После правок: имя — xs (12px, fw=500), тело — sm (14px), время — xs (12px). Тело крупнее имени — это норма (имя/мета как «капс-лейбл», тело как основной текст).
  • font-size ставится на внутренний :global(.ProseMirror), т.к. размер приходит из глобального правила core.css. Класс-модуль .commentEditor скоупит переопределение только на редактор комментариев — основной редактор страницы не затрагивается.
  • Тёмная тема. Меняем только размеры/отступы, цвета берутся из токенов Mantine — отдельной проверки палитры не требуется, но визуально глянуть стоит.
  • Вложенные ответы рендерятся тем же CommentListItem → уплотнение pb, gap, шрифтов применится и к ним автоматически (так и нужно).
  • Markdown/код в теле. pre/code/списки внутри комментария наследуют font-size от .ProseMirror контейнера — после font-size: sm они тоже станут компактнее; проверить, что код-блоки не разъезжаются.
  • Цитата выделения кликабельна (role="button", переход к месту в тексте) — уменьшение padding/size не должно сломать зону клика; визуально проверить.
  • Нижнее поле ввода (PageCommentInput) с плавающей кнопкой: величины paddingBottom: 25 / bottom: 30 связаны. В базовом объёме не трогаем; если захотим уплотнить и его — менять обе согласованно и проверить, что кнопка отправки не наезжает на текст.

Тесты / проверка

  • Прогнать pnpm --filter client lint и pnpm --filter client test (изменения косметические — падений быть не должно).
  • Ручная проверка во вкладке Comments: тред с длинным телом, тред с цитатой выделения, вложенные ответы, режим редактирования, светлая/тёмная тема, узкая ширина aside. Убедиться, что вкладки «Содержание»/«Детали» не изменились (если aside.tsx не трогали).

Опционально / расширения (вне базового объёма)

  • Уплотнить рамку панелиaside.tsx: p="md"p="sm", шапка mb="md"mb="sm". Даст ощутимо меньше воздуха по краям, но затронет все вкладки aside (см. «Открытые вопросы»).
  • Компактные вкладки TabsTabs.Panel pt="xs"pt={6}, бейджи счётчиков уже size="sm".
  • Удалить мёртвый .wrapper из comment.module.css (не используется).
  • Уменьшить аватары с size="sm" до size="xs" в CommentListItem и PageCommentInput для ещё большей плотности (проверить, что инициалы/картинка не мельчат до нечитаемости).

Принятые решения

Решения зафиксированы — реализовать можно сразу, без доп. согласований:

  • Границы правки: строго features/comment/. Общую рамку aside (p="md", шапка mb="md") не трогаем — она общая с вкладками «Содержание»/«Детали», и правка задела бы их (см. «Опционально», если позже захотим уплотнить и их).
  • Шрифт тела: sm (14px) — не мельче.
  • Иерархия: имя xs (12px, fw=500), тело sm (14px), время xs (12px).
  • Нижнее поле ввода и размер аватаров: оставляем как есть.