Уровни макета
Эта глава описывает уровни ответственности в макете, тип узла и встроенные типы Framework.
Три уровня ответственности
Макет читается сверху вниз.
| Уровень | За что отвечает | Чего не делает |
|---|---|---|
| Страница | граница одного документа, общий контейнер | не вставляется внутрь другой страницы |
| Секция | смысловая часть страницы: вступление, преимущества, выдача, контакты | не загружает данные и не выполняет действий |
| Компонент | конкретный элемент внутри секции: кнопка, карточка, поле | не управляет соседями |
Как выбрать уровень:
- часть нужна только для расположения соседей и общей темы — секция;
- часть страницы с одной темой повторяется на разных страницах — сохраните её как блок, то есть шаблон Recipe (Блок);
- нужен повторяемый элемент интерфейса — компонент из каталога;
- нужен элемент с поведением и состоянием — Smart-компонент (Smart-компоненты и составные компоненты в макете).
Не рекомендуется оборачивать каждый абзац отдельной секцией: лишняя вложенность усложняет документ и ничего не добавляет.
Например, на странице каталога секция содержит заголовок и колонки: в одной — фильтры, в другой — карточки товаров. Кнопка сброса фильтра остаётся компонентом. Документ этого каркаса:
{
"schema": "simai.composition.document",
"schema_version": 1,
"id": "catalog-page",
"profile": "ui-layout",
"locale": "ru",
"root": {
"id": "page",
"type": "layout.page",
"slots": {
"default": [
{
"id": "catalog",
"type": "layout.section",
"presentation": {"preset": "surface", "modifiers": ["contained"]},
"bindings": [{"owner": "project/catalog", "ref": "products", "target": "items", "revision": "42"}],
"slots": {
"default": [
{"id": "title", "type": "content.heading", "data": {"level": 1, "content": [{"type": "text", "value": "Каталог товаров"}]}},
{"id": "lead", "type": "content.paragraph", "data": {"content": [{"type": "text", "value": "Framework показывает макет, а проект получает товары и проверяет права."}]}},
{
"id": "columns",
"type": "layout.columns",
"props": {"columns": 2},
"presentation": {"modifiers": ["responsive"]},
"slots": {"columns": [
{"id": "filters", "type": "content.paragraph", "data": {"content": [{"type": "text", "value": "Фильтры"}]}},
{"id": "products", "type": "content.paragraph", "data": {"content": [{"type": "text", "value": "Карточки товаров"}]}}
]}
}
]
}
}
]
}
}
}
Тип узла
Каждый узел имеет тип. Тип — это контракт: какие данные и настройки узел принимает, какие у него слоты, как он отрисовывается и какие ресурсы нужны. Контракт записан в манифесте типа (Манифест типа), а набор манифестов образует реестр типов. Узел неизвестного типа отклоняется — Framework не угадывает.
Имя типа состоит из пространства и имени: layout.section,
content.paragraph, smart.buttons, project.product-card.
Встроенные типы
Framework поставляет базовые типы, на которых можно собрать страницу без единого собственного типа:
| Тип | Назначение | Отрисовка |
|---|---|---|
layout.page |
корень документа, слот default |
<main> |
layout.section |
смысловая секция, слот default |
<section> |
layout.columns |
колонки, слот columns, настройка columns от 1 до 12 |
сетка колонок |
content.heading |
заголовок уровня 1–6 со структурированным текстом | <h1>–<h6> |
content.paragraph |
абзац со структурированным текстом | <p> |
layout.regions, layout.region |
именованные области страницы (Области страницы) | ориентиры header, main, aside и др. |
layout.scope |
общий родитель для связи компонентов маршрутами (Составной компонент в макете) | <sf-composition-scope> |
Полный перечень с допустимыми значениями — в реестре типов
(distr/core/contracts/composition-types.v1.json поставки ui).
Каждый узел встроенного типа выводится с атрибутом data-sf-composition-id,
равным идентификатору узла. По нему редактор находит узел на холсте (Холст и оверлей).
Узел Smart-компонента выводится тегом компонента без этого атрибута;
рендерер собственного типа добавляет атрибут сам, если узел нужно выбирать
в редакторе.
Данные и настройки встроенных типов:
| Тип | Поля узла | Варианты presentation |
|---|---|---|
layout.page |
слот default |
— |
layout.section |
слот default |
пресеты surface, contrast; модификаторы contained, spacious |
layout.columns |
props.columns — целое от 1 до 12; слот columns — от 1 до 12 детей |
модификаторы equal, responsive |
content.heading |
data.level — от 1 до 6; data.content — структурированный текст |
— |
content.paragraph |
data.content — структурированный текст |
модификаторы lead, muted |
Слоты default и columns принимают узлы категорий layout, content и
smart.
Что выводят встроенные рендереры:
layout.columnsвыводит<div class="sf-composition-columns" data-composition-columns="N">, а каждого ребёнка слотаcolumnsоборачивает в<div class="sf-composition-column">: один ребёнок — одна колонка. Стилей для этих классов Framework не поставляет; сетку колонок задаёт CSS страницы. Несколько узлов в одной колонке объединяетlayout.section: она и есть группа, ребёнок слотаcolumns, а узлы колонки лежат в её слотеdefault. Это не та лишняя секция вокруг каждого абзаца, от которой предостерегает раздел выше. Число детей слота с настройкойcolumnsне сверяется: третий ребёнок приcolumns: 2без диагностики становится третьей колонкой.presentationпроверяется по манифесту типа, но встроенные рендереры его не выводят: пресеты и модификаторы не дают в HTML ни классов, ни атрибутов. Если вариант должен быть виден, его рисует рендерер собственного типа.content.headingиcontent.paragraphвыводят<h1>–<h6>и<p>без классов: их вид задают стили текста по умолчанию и CSS страницы (вывод отметок и ссылок — см. Структурированный текст).layout.pageвсегда выводит<main>. Если у страницы проекта уже есть свой<main>, корнем документа делают секцию (layout.section) или другой тип: корень документа не обязан быть страницей.- Для колонок
render()называет вassetsресурсcomposition/layout. Файла с таким именем в поставке нет: его роль играет CSS страницы.
CSS колонок в проекте
Колонки без стилей проекта идут одна под другой. Правила колонок кладите в
слой проекта, объявленный после core.css, например @layer project (см.
Каскадные слои). Рекомендуемый минимум —
сетка с промежутком из шкалы пространства, одна колонка на узком экране и
заданное число колонок от контрольной точки md. В примере ниже её ширина
записана числом, потому что медиазапрос не читает переменные; берите её из
выпуска, которым пользуется проект:
.sf-composition-columns {
display: grid;
gap: var(--sf-space-4);
}
.sf-composition-column {
min-inline-size: 0;
}
@media (min-width: 44rem) {
.sf-composition-columns[data-composition-columns="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sf-composition-columns[data-composition-columns="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sf-composition-columns[data-composition-columns="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
Добавьте правила для того числа колонок, которое встречается в ваших
документах. Модификаторы equal и responsive в HTML не попадают, поэтому
такое правило действует на все колонки одного числа (см. Значения интервалов и
Ширина экрана: контрольные точки).