Перейти к содержимому
Разделы
Язык, сейчас Русский
Дизайн-система Rastrillo

Отображение

Мелкие части словаря, из которых собирается экран: статус, личность, прогресс и единственная форма предупреждения.

Каждый пример работает, но его ссылки никуда не ведут. HTML показывает разметку для копирования.

status-pill

Статус записи в виде цветной плашки — цвет и подпись.

Предпросмотр

neutral

<span rst-status rst-tone="neutral">Черновик</span>

positive

<span rst-status rst-tone="positive">Опубликовано</span>

warning

<span rst-status rst-tone="warning">Запланировано</span>

negative

<span rst-status rst-tone="negative">Не удалось</span>

neutral

{{template "status-pill" dict "Label" "Черновик"}}

positive

{{template "status-pill" dict "Label" "Опубликовано" "Tone" "positive"}}

warning

{{template "status-pill" dict "Label" "Запланировано" "Tone" "warning"}}

negative

{{template "status-pill" dict "Label" "Не удалось" "Tone" "negative"}}

neutral По умолчанию Tone равен neutral, поэтому в этом вызове его нет.

badge

Небольшая рамочная метка прописными буквами для статичных пометок. Это не status-pill: тот показывает статус записи.

Предпросмотр

Без тона (тихое значение по умолчанию)

<span rst-badge>Черновик</span>

neutral

<span rst-badge="neutral">Внутреннее</span>

positive

<span rst-badge="positive">Активно</span>

warning

<span rst-badge="warning">Бета</span>

negative

<span rst-badge="negative">Распродано</span>

Без тона (тихое значение по умолчанию)

{{template "badge" dict "Label" "Черновик"}}

neutral

{{template "badge" dict "Label" "Внутреннее" "Tone" "neutral"}}

positive

{{template "badge" dict "Label" "Активно" "Tone" "positive"}}

warning

{{template "badge" dict "Label" "Бета" "Tone" "warning"}}

negative

{{template "badge" dict "Label" "Распродано" "Tone" "negative"}}

meter

Полоса заполнения вместе с числом.

Предпросмотр

Пусто

<span rst-meter>
  <meter rst-meter-bar value="0" min="0" max="100" aria-hidden="true"></meter>
  <span rst-meter-num>0/500</span>
</span>

Наполовину

<span rst-meter>
  <meter rst-meter-bar value="42" min="0" max="100" aria-hidden="true"></meter>
  <span rst-meter-num>210/500</span>
</span>

Почти заполнено

<span rst-meter>
  <meter rst-meter-bar value="82" min="0" max="100" aria-hidden="true"></meter>
  <span rst-meter-num>412/500</span>
</span>

Заполнено

<span rst-meter>
  <meter rst-meter-bar value="100" min="0" max="100" aria-hidden="true"></meter>
  <span rst-meter-num>500/500</span>
</span>

Сверх лимита

<span rst-meter>
  <meter rst-meter-bar value="100" min="0" max="100" aria-hidden="true"></meter>
  <span rst-meter-num>700/500</span>
</span>

Пусто

{{template "meter" dict "Percent" 0 "Text" "0/500"}}

Наполовину

{{template "meter" dict "Percent" 42 "Text" "210/500"}}

Почти заполнено

{{template "meter" dict "Percent" 82 "Text" "412/500"}}

Заполнено

{{template "meter" dict "Percent" 100 "Text" "500/500"}}

Сверх лимита

{{template "meter" dict "Percent" 140 "Text" "700/500"}}

Сверх лимита Заполнение ограничено 100% внутри партиала.

stat

Одно число на панели, с подписью и тем, насколько оно изменилось.

Большое число

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat="lead">
  <span rst-stat-label>Выручка за месяц</span>
  <span rst-stat-num>€48,210</span>
  <span rst-stat-delta rst-tone="positive">&#43;12%</span>
  <span rst-stat-note>к прошлому месяцу</span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict
    "Label" "Выручка за месяц"
    "Value" "€48,210"
    "Delta" "+12%"
    "Tone" "positive"
    "Note" "к прошлому месяцу"
    "Lead" true}}

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

Число поменьше

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat>
  <span rst-stat-label>Неоплаченные счета</span>
  <span rst-stat-num>24</span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict "Label" "Неоплаченные счета" "Value" "24"}}

Нужны только подпись и число. Всё остальное необязательно.

Когда снижение: это хорошо

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat>
  <span rst-stat-label>Время до первого ответа</span>
  <span rst-stat-num>1 ч 12 мин</span>
  <span rst-stat-delta rst-tone="positive">−38%</span>
  <span rst-stat-note>к прошлой неделе</span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict
    "Label" "Время до первого ответа"
    "Value" "1 ч 12 мин"
    "Delta" "−38%"
    "Tone" "positive"
    "Note" "к прошлой неделе"}}

Цвет задаёте вы, а не компонент. Здесь число снизилось, и это хорошая новость, поэтому изменение зелёное.

Когда рост: это плохо

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat>
  <span rst-stat-label>Неудачные платежи</span>
  <span rst-stat-num>9</span>
  <span rst-stat-delta rst-tone="negative">&#43;3</span>
  <span rst-stat-note>к прошлой неделе</span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict
    "Label" "Неудачные платежи"
    "Value" "9"
    "Delta" "+3"
    "Tone" "negative"
    "Note" "к прошлой неделе"}}

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

Когда сказать нельзя

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat>
  <span rst-stat-label>Средняя длительность сеанса</span>
  <span rst-stat-num>4 мин 12 с</span>
  <span rst-stat-delta rst-tone="neutral">&#43;18 с</span>
  <span rst-stat-note>с пятницы</span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict
    "Label" "Средняя длительность сеанса"
    "Value" "4 мин 12 с"
    "Delta" "+18 с"
    "Note" "с пятницы"}}

Не задавайте цвет, и изменение будет серым. Так и делайте, когда нельзя сказать, хорошо это или плохо.

Сокращённое число

Предпросмотр

Поместите это внутрь <div rst-stats>.

<div rst-stat>
  <span rst-stat-label>Отправлено сообщений</span>
  <span rst-stat-num><data value="4120">4.1k</data></span>
</div>

Поместите это внутрь <div rst-stats>.

{{template "stat" dict
    "Label" "Отправлено сообщений"
    "Value" "4.1k"
    "Exact" "4120"}}

Показываете 4.1k вместо 4120? Полное число положите в Exact. Программы чтения с экрана читают только то, что на экране, поэтому всё, что нужно человеку, держите в самом числе.

person

Аватар с инициалами, имя и почта. Помогает быстро узнать записи о людях.

Имя и почта

Предпросмотр
<a rst-person href="/people/1">
  <span rst-person-av aria-hidden="true">G</span>
  <span rst-person-meta>
    <span rst-person-name>Grace Hopper</span>
    <span rst-person-email>grace@example.com</span>
  </span>
</a>
{{template "person" dict
    "Href" "/people/1"
    "Name" "Grace Hopper"
    "Email" "grace@example.com"
    "Initial" "G"}}

Крупный: размер для шапки экрана просмотра

Предпросмотр
<a rst-person="lg" href="/people/2">
  <span rst-person-av aria-hidden="true">A</span>
  <span rst-person-meta>
    <span rst-person-name>Ada Lovelace</span>
    <span rst-person-email>ada@example.com</span>
  </span>
</a>
{{template "person" dict
    "Href" "/people/2"
    "Name" "Ada Lovelace"
    "Email" "ada@example.com"
    "Initial" "A"
    "Large" true}}

Без инициала

Предпросмотр
<a rst-person href="/people/3">
  <span rst-person-av="empty" aria-hidden="true"></span>
  <span rst-person-meta>
    <span rst-person-name>Непринятое приглашение</span>
    <span rst-person-email>invited@example.com</span>
  </span>
</a>
{{template "person" dict
    "Href" "/people/3"
    "Name" "Непринятое приглашение"
    "Email" "invited@example.com"}}

actor

Кто что сделал, словами: имя человека, либо агент и человек, от имени которого он действовал. Без значка и без иконки.

Агент, действующий от имени человека

Предпросмотр
<span rst-actor>Claude от имени Grace Hopper</span>
{{template "actor" dict "Actor" .Actor}}

Задайте ui.ActorName один раз при запуске, чтобы превращать субъект в имя. Само приложение, нулевой Actor, ничего не отображает.

Человек

Предпросмотр
<span rst-actor>Grace Hopper</span>
{{template "actor" dict "Actor" .Actor}}

callout

Единственный словарь предупреждений: цветная полоса, значок тона, необязательный жирный заголовок и один абзац текста.

info

Предпросмотр
<div rst-callout rst-tone="info">
  <span rst-callout-ic aria-hidden="true">
    <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
  </span>
  <div rst-callout-body>
    <p>Пока сайт не опубликован, записи видны только участникам.</p>
  </div>
</div>
{{template "callout" dict
    "Body" "Пока сайт не опубликован, записи видны только участникам."
    "Tone" "info"}}

positive

Предпросмотр
<div rst-callout rst-tone="positive">
  <span rst-callout-ic aria-hidden="true">
    <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
  </span>
  <div rst-callout-body>
    <strong>Платежи подключены</strong>
    <p>Теперь можно принимать оплату за билеты.</p>
  </div>
</div>
{{template "callout" dict
    "Body" "Теперь можно принимать оплату за билеты."
    "Title" "Платежи подключены"
    "Tone" "positive"}}

warning

Предпросмотр
<div rst-callout rst-tone="warning">
  <span rst-callout-ic aria-hidden="true">
    <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
  </span>
  <div rst-callout-body>
    <strong>Подключите платежи, чтобы начать продажи</strong>
    <p>Мероприятие опубликовано, но пока не может принимать оплату.</p>
  </div>
</div>
{{template "callout" dict
    "Body" "Мероприятие опубликовано, но пока не может принимать оплату."
    "Title" "Подключите платежи, чтобы начать продажи"
    "Tone" "warning"}}

negative

Предпросмотр
<div rst-callout rst-tone="negative">
  <span rst-callout-ic aria-hidden="true">
    <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>
  </span>
  <div rst-callout-body>
    <strong>Последний импорт не удался</strong>
    <p>Ничего не изменено. Исправьте строку 91 и повторите попытку.</p>
  </div>
</div>
{{template "callout" dict
    "Body" "Ничего не изменено. Исправьте строку 91 и повторите попытку."
    "Title" "Последний импорт не удался"
    "Tone" "negative"}}

negative, объявляется как предупреждение

Предпросмотр
<div rst-callout rst-tone="negative" role="alert">
  <span rst-callout-ic aria-hidden="true">
    <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>
  </span>
  <div rst-callout-body>
    <strong>Импорт остановлен</strong>
    <p>Ничего не изменено. Исправьте строку 91 и повторите попытку.</p>
  </div>
</div>
{{template "callout" dict
    "Body" "Ничего не изменено. Исправьте строку 91 и повторите попытку."
    "Title" "Импорт остановлен"
    "Tone" "negative"
    "Alert" true}}

alert добавляет role="alert", чтобы показывать важные сообщения.

detail-list

Список определений о записи на экране подробностей. Моноширинная пометка — для машинных значений.

Четыре факта, один машинный

Предпросмотр

Поместите это внутрь <section rst-box>.

<dl rst-detail>
  <dt>Аудитория</dt>
  <dd>Участники</dd>
  <dt>Главная страница</dt>
  <dd>Нет</dd>
  <dt>Опубликовано</dt>
  <dd>
    <time datetime="2026-08-02">2 августа 2026 г.</time>
  </dd>
  <dt>Номер</dt>
  <dd class="rst-mono">post_01H9ZQ</dd>
</dl>

Поместите это внутрь <section rst-box>.

{{template "detail-list" dict
    "Items" (list
        (dict "Label" "Аудитория" "Value" "Участники")
        (dict "Label" "Главная страница" "Value" "Нет")
        (dict "DateTime" "2026-08-02" "Label" "Опубликовано" "Value" "2 августа 2026 г.")
        (dict "Label" "Номер" "Mono" true "Value" "post_01H9ZQ"))}}

notice

Однострочное подтверждение после перенаправления. Принимает обычную строку, а не dict, и при пустой не выводит ничего.

Сообщение о сохранении

Предпросмотр
<p rst-notice role="status">Запись сохранена.</p>
{{template "notice" "Запись сохранена."}}

region:notice

Уведомление, которое каждая оболочка держит на странице: оно показывает Notice из данных страницы, чтобы экранный диктор услышал сообщение, а live.js мог заполнить его на месте.

Сообщение о сохранении

Предпросмотр
<div id="notice" role="status">
  <p rst-notice>Запись сохранена.</p>
</div>
{{template "region:notice" dict "Notice" "Запись сохранена."}}

form-error

Строка со сводкой ошибок формы, role="alert". Принимает обычную строку; при отсутствии ошибки не выводит ничего.

Отклонённая отправка

Предпросмотр
<p rst-form-error role="alert">Это название уже занято.</p>
{{template "form-error" "Это название уже занято."}}

job-status

Опрашиваемый фрагмент фоновой задачи. Атрибут data-poll выводится, только пока задача выполняется: не вывести его и значит остановить опрос.

Выполняется

Предпросмотр

<div rst-job data-poll="/jobs/1/fragment" data-poll-every="2">
  <span rst-spin aria-hidden="true"></span> Задача «<bdi><strong>Импорт</strong></bdi>» выполняется: <bdi>128 из 400</bdi>…
  <progress rst-job-bar value="32" min="0" max="100" aria-hidden="true"></progress>
</div>
{{template "job-status" dict
    "Name" "Импорт"
    "Percent" 32
    "PollSeconds" 2
    "PollURL" "/jobs/1/fragment"
    "Progress" "128 из 400"
    "Status" "running"}}

Этот опрашивает: единственный образец на странице, который вообще что-то просит у сети, — и на статическом сайте он просто никогда не дождётся ответа.

Готово

Предпросмотр

<div rst-job>
  Задача «<bdi><strong>Импорт</strong></bdi>» завершена.
</div>
{{template "job-status" dict "Name" "Импорт" "Status" "done"}}

Не удалось

Предпросмотр

<div rst-job>
  Задача «<bdi><strong>Импорт</strong></bdi>» завершилась с ошибкой: <bdi>row 91: no such column &#34;published&#34;</bdi>
</div>
{{template "job-status" dict
    "Err" "row 91: no such column \"published\""
    "Name" "Импорт"
    "Status" "failed"}}