система · не рескин

SelfPost — грамматика интерфейса

Это проект системы. Экраны складываются из регионов и контролов. Запрещённые состояния нельзя «починить паддингом» — их не из чего собрать. Знак, кирпич и IBM Plex не меняются. Живая панель (internal/web) пока не трогается.

Зачем

Первый макет скопировал грамматику живой панели: страница помечается ops или form, карточки стопкой, пара полей — два независимых .code, Save внутри <form>, Delete снаружи. Дальше каждая мелочь чинилась отдельно — как в panel.css годами. Новый интерфейс должен не давать собрать пустую колонку, разные высоты Host/Type и кнопки на двух строках.

Три оси, которые больше не выбираются «на глаз» у каждой страницы:

  1. Регион — как блок занимает ширину окна.
  2. Карточка — заголовок, справка, тело, действия.
  3. Контрол — одно поле или пара полей одной высоты.

Регионы

Страница — это stack регионов, не класс на <main>. Оболочка одна: навбар прижат влево, контент забирает остаток. Навбар не прыгает, когда меняется содержимое.

РегионШиринаКогда
measure до 42rem, влево Одна читаемая форма: login, setup, подтверждение удаления, форма пользователя. Не «вся страница Settings».
pair две колонки до 90rem Две равноправные задачи на одном экране. Один ребёнок — сам сжимается в measure (domain-admin без DMARC).
fill до 90rem Таблица, лог, DNS-статус, список приложений. Ячейки не переносят однострочные значения; карточка скроллится по X.
stack колонка с зазором Вертикальный порядок регионов. Зазор даёт gap, не .card + .card.
Нельзя — страница-форма, две задачи стопкой

Full backup

Карточка узкая. Справа пустое поле на 1600px.

Import a domain

Вторая задача под первой — та же пустота.

Надо — pair

Full backup

Секрет. Шифрование — внутри карточки, поля не растягиваются на 1440px.

Import a domain

Тот же экран, вторая задача. Не «ещё одна форма ниже».

Карточка

Один хром: card-head (заголовок + слот «?»), тело, при необходимости actions-row. Справка — часть хрома, её не расставляют после того, как карточки уже собраны. Нет «?» — слот пустой, заголовки соседних карточек всё равно на одной линии.

Показания (очередь, PTR, CPU) остаются на карточке. В drawer уходит только то, чего на карточке быть не должно: что такое kernel counter, зачем PTR у провайдера, почему пароль показывают один раз.

Хром карточки

DNS status ok

?

Чтение и Re-check здесь. Абзац «зачем MX» — в справке.

Danger zone

Без «?»: действие очевидное. Карточка всё равно пара к форме, не на всю ширину.

Контролы

Одно поле — field (подпись + контроль). Два поля в ряд — field-row: подписи в первой сетке-строке, значения во второй. Высота значений общая, потому что это одна строка грида, а не два блока с подобранным padding. Баг «Type ниже Host» (b0ebe06) из этой разметки не собирается.

field-row с узкой второй колонкой — Host / name ‖ Type. field-row equal — два равноправных инпута (лимит и окно).

field-row — Host ‖ Type, с Copy и без

With Copy

mail._domainkey.example.com
TXT

Lookup, no Copy

lists.example.com
MX
field-row equal — лимит ‖ окно

Level-2 rate limit

Действия

Primary, secondary и danger — всегда actions-row. Для вёрстки неважно, POST это или переход на confirm: ряд один. Форма либо оборачивает всю карточку, либо кнопки несут form=. Нельзя оставить Submit внутри блочной формы, а Delete — следующим соседом: блок формы занимает строку целиком.

Save и Delete в одном ряду

Edit user

Нельзя

Если хочется добавить правило «только на этой странице» — сначала проверить, какого региона не хватило.

Рецепты экранов

Экраны — отдельные HTML-файлы рядом с этой спецификацией. Собираются только так:

ЭкранСтек регионов
Login / setup центр оболочки, measure 24rem, полный stamp
Status stack: overall → pair очередь‖TLS → pair milters‖PTR → inbound если есть → pair machine‖processes → configuration. На карточках остаются числа и Detail.
Domains / Deliveries / log / queue fill таблица. Добавление домена — measure или узкая карточка над таблицей, не растянутый инпут.
Domain fill DNS status → pair DKIM/SPF ‖ DMARC → pair connection ‖ add app → fill applications → pair domain settings (две половины) → pair export ‖ danger. «?» на рабочих карточках.
Inbound domain fill MX DNS → pair upstream ‖ MX to publish → pair recipients ‖ danger
Backup pair full backup ‖ import
Settings global: pair credentials ‖ DMARC, затем fill rate limits. Domain-admin: один ребёнок в pair → сам measure
Users fill таблица. Create/Editmeasure + actions-row
Confirm delete measure одна карточка

Телефон

Аварийный доступ, не продукт. pair складывается в одну колонку. Таблица заменяется списком (как сейчас в прототипе). field-row не складывается: Type — токен. Навбар — выезжающая колонка на checkbox, без обязательного JS. Знак в шапке — SP-иконка, не второй wordmark.

Как внедрять

  1. Новый экран или правка макета — только классы из system.css (stack, pair, measure, fill, field-row, actions-row).
  2. Не добавлять исключения в mock.css «для этой страницы», если это ширина, высота пары полей или ряд кнопок.
  3. Click-through — отдельные страницы (status.html, domain.html, …), не простыня с якорями. Оболочка общая: shell.js.
  4. Вёрстка internal/web — отдельная задача после утверждения системы, не параллельный рескин шаблонов.

Классы живут в docs/assets/panel-ui/system.css. Этот файл — спецификация. Экраны — status.html и соседние страницы; оглавление — index.html.