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

Примитивы интерфейса

Формы, которыми компонент быть не может, потому что они оборачивают тело, известное только вызывающему: карточка раздела, сетка данных, раскрывающееся меню и собственная обвязка каркасов. tokens.css поставляет классы, а разметку пишет приложение. Всё, что ниже, — разметка, которую возвращает ui.Styleguide, со словами на вашем языке, и именно эту разметку тесты ui сверяют с tokens.css.

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

box

Карточка раздела с отступами и заголовок, который стоит вне её.

Какая карточка какая

У rst-list и rst-card намеренно нет отступов: они держат череду строк, а каждая строка отбивает себя сама. Положите внутрь форму, абзац, полосу ссылок или что угодно, что не строка, и это отрисуется вплотную к границе; текст, касающийся края, и есть примета. Карточка с отступами для произвольного содержимого: rst-box, а её заголовок стоит перед ней соседним rst-box-head.

Предпросмотр
<div rst-box-head>
  <h2>Выплата</h2>
  <a rst-btn href="/payout/edit">Изменить</a>
</div>
<section rst-box>
  <p>Всё на экране находится внутри блоков.</p>
  <div rst-box-foot>Обновлено 2 часа назад</div>
</section>

button

Кнопки бывают четырёх видов и трёх размеров, а ссылка может выглядеть как кнопка. Индикатор, который форма показывает во время отправки, смотрите в form-foot.

Предпросмотр
<p>
  <button rst-btn type="button">Отмена</button> <button rst-btn="primary" type="button">Сохранить</button> <button rst-btn="ghost" type="button">Предпросмотр</button> <button rst-btn="danger" type="button">Удалить</button>
</p>
<p>
  <button rst-btn="primary sm" type="button">Маленькая</button> <button rst-btn="primary" type="button">Обычная</button> <button rst-btn="primary lg" type="button">Большая</button> <a rst-btn href="/orders">Посмотреть заказы</a>
</p>
<p>
  <button rst-btn="primary block" type="button">Продолжить</button>
</p>
<p>
  <button rst-btn type="button" disabled>В архиве</button>
</p>

dropdown

Меню на details/summary, стоящее за меню переполнения в шапке и за фильтром панели списка, плюс применённый фильтр в виде снимаемой метки.

Предпросмотр
<details rst-dropdown name="rst-menus">
  <summary>
    Фильтр
    <span rst-caret 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="m6 9 6 6 6-6"/></svg>
    </span>
    <span class="rst-sr-only">Фильтр заказов: Оплачено</span>
  </summary>
  <div rst-dropdown-menu>
    <a aria-current="true" href="/orders?status=paid">Оплачено</a>
    <details rst-menu-group name="rst-menus-price" open>
      <summary>Цена</summary>
      <div>
        <a href="/orders?price=free">Бесплатно</a>
      </div>
    </details>
  </div>
</details>
<span rst-ftok>
  <span rst-ftok-k>Оплачено</span>
  <a href="/orders" aria-label="Убрать фильтр «Оплачено»">✕</a>
</span>

form-layout

Атрибуты, которые задают форме её ритм и её панель сохранения. Ни один партиал их не выводит; они оборачивают набор полей, который собрал вызывающий.

Предпросмотр
<form rst-form-flow method="post" action="/settings">
  <div rst-field>
    <label rst-field-label for="name">Имя</label>
    <input rst-input type="text" id="name" name="name">
  </div>
  <div rst-field>
    <label rst-field-label for="email">Электронная почта</label>
    <input rst-input type="email" id="email" name="email">
  </div>
  <div rst-field-row>
    <div class="rst-grow" rst-field>
      <label rst-field-label for="city">Город</label>
      <input rst-input type="text" id="city" name="city">
    </div>
    <div rst-field>
      <label rst-field-label for="zip">Индекс</label>
      <input rst-input="short" type="text" id="zip" name="zip">
    </div>
  </div>
  <div rst-form-bar>
    <span rst-form-bar-note>Изменения сохраняются сразу.</span>
    <div rst-form-actions>
      <a rst-btn href="/settings">Отмена</a>
      <button rst-btn="primary" type="submit">Сохранить</button>
    </div>
  </div>
</form>

help

Вопросительный знак в рамке, ведущий к статье справки. Его CSS-подсказка — украшение; ссылка несёт собственную подпись целым предложением.

Предпросмотр
<a rst-help rst-tip href="/help/orders" target="_blank" rel="noopener" aria-label="Справка: заказы" data-tip="О заказах">
  <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.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
</a>

list-grid

Настоящий словарь таблиц данных: карточка задаёт колонки один раз, строки только выбирают ячейки.

Экраны складываются по вертикали

Экран — это столбец: page-header, затем section-header и карточка, затем следующий section-header и карточка, в порядке чтения. Горизонтальная раскладка оставлена тем приёмам, которые её несут: rst-box-head, rst-field-row, rst-lbar, ячейки rst-lrow, rst-seg-tabs.

Предпросмотр
<div rst-card style="--rst-cols: 2fr 110px var(--rst-col-menu)">
  <div rst-lrow="head">
    <span>Заказ</span>
    <span class="rst-m-hide">Статус</span>
    <span></span>
  </div>
  <div rst-lrow>
    <a class="rst-nm" href="/orders/AB3PX"><bdi>Grace Hopper</bdi>
      <small>AB3PX · <bdi>grace@example.com</bdi></small>
    </a>
    <span class="rst-m-hide rst-cell-mut">Оплачено</span>
    <details rst-row-menu name="rst-menus">
      <summary aria-label="Действия для Grace Hopper">
        <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="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
      </summary>
      <div rst-row-menu-panel>
        <a href="/orders/AB3PX">Открыть</a>
        <hr>
        <a class="rst-danger" href="/orders/AB3PX/refund">Вернуть деньги за заказ…</a>
      </div>
    </details>
  </div>
  <p rst-no-match>Подходящих заказов нет. <a href="/orders">Сбросить фильтры</a></p>
</div>
<p rst-count-line>Показаны <strong>1–20</strong> из <strong>412</strong></p>

modal

У модального окна есть собственный URL, а не состояние на клиенте: страница под ним помечена inert, панель над ней и обычная ссылка, чтобы закрыть.

Предпросмотр
<div rst-backdrop inert>
  <div rst-page>
    <h1>Настройки</h1>
  </div>
</div>
<div rst-modal-overlay>
  <dialog rst-modal-panel open aria-labelledby="modal-title">
    <nav>
      <a href="/settings/profile" aria-current="page">Профиль</a>
      <a href="/settings/billing">Оплата</a>
      <a href="/settings/notifications">Уведомления</a>
    </nav>
    <section>
      <a rst-modal-close href="/settings" aria-label="Закрыть настройки">✕</a>
      <h2 id="modal-title">Профиль</h2>
      <p>Измените имя и фото, которые показываются по всему аккаунту.</p>
    </section>
  </dialog>
</div>

Посмотрите его вживую по тому URL, которому он принадлежит (откроется в новой вкладке).

selbox

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

Предпросмотр
<label rst-selbox>
  <input type="checkbox" aria-label="Выбрать заказ AB3PX">
</label>

shell-sidebar

Обрамление оболочки sidebar на странице с содержимым: на телефоне это кнопка возврата к оглавлению.

Предпросмотр
<div rst-shell-sidebar="page">
  <a rst-skip href="#main">Перейти к содержимому</a>
  <div rst-shell-back>
    <a href="/#nav-reports" rel="up" aria-label="Назад к разделам">Разделы</a>
  </div>
  <aside rst-shell-rail>
    <h1 rst-shell-title>
      <span><a rst-shell-brand href="/">Notes</a></span><span>Отчёты</span>
    </h1>
    <a rst-shell-brand href="/">Notes</a>
    <nav rst-shell-nav>
      <span rst-shell-group>Работа</span>
      <a id="nav-dashboard" href="/dashboard">Сводка</a>
      <a id="nav-reports" href="/reports" aria-current="page">Отчёты</a>
    </nav>
    <div rst-shell-rail-foot>
      <details rst-dropdown rst-shell-profile name="rst-shell-menu">
        <summary>
          <span rst-shell-avatar>
            <span rst-person-av aria-hidden="true">A</span>
            <span rst-person-name>Ada Lovelace</span>
          </span>
        </summary>
        <div rst-dropdown-menu>
          <div rst-shell-who>
            <span rst-person-av aria-hidden="true">A</span>
            <span rst-person-name>Ada Lovelace</span>
            <span rst-person-email>ada@example.com</span>
          </div>
          <a href="/settings">Настройки</a>
        </div>
      </details>
    </div>
  </aside>
  <main rst-shell-main id="main">
    <div rst-page>Содержимое.</div>
  </main>
</div>

Откройте демо каркаса с боковой панелью — отдельный просмотр. (откроется в новой вкладке).

shell-topbar

Собственная обвязка каркаса с верхней панелью, в виде разметки. Layout поставляет её как целый шаблон.

Предпросмотр
<div rst-shell-topbar>
  <a rst-skip href="#main">Перейти к содержимому</a>
  <header rst-shell-bar>
    <a rst-shell-brand href="/">Notes</a>
    <details rst-shell-menu name="rst-shell-menu">
      <summary>
        <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="M4 12h16"/><path d="M4 6h16"/><path d="M4 18h16"/></svg>Меню</summary>
    </details>
    <div rst-shell-tail>
      <nav rst-shell-nav>
        <a href="/" aria-current="page">Главная</a>
        <a href="/archive">Архив</a>
      </nav>
      <details rst-dropdown rst-shell-account name="rst-menus">
        <summary>
          Аккаунт
          <span rst-caret 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="m6 9 6 6 6-6"/></svg>
          </span>
        </summary>
        <div rst-dropdown-menu>
          <a href="/settings">Настройки</a>
        </div>
      </details>
    </div>
  </header>
  <main rst-page id="main">Содержимое.</main>
  <footer rst-shell-foot>Сделано на rastrillo</footer>
</div>

Откройте демо каркаса с верхней панелью — отдельный просмотр для него. (откроется в новой вкладке).

stat-band

Ряд показателей вдоль верха панели.

Предпросмотр
<div rst-stats>
  <div rst-stat="lead">
    <span rst-stat-label>Выручка за месяц</span>
    <span rst-stat-num>&euro;48,210</span>
    <span rst-stat-delta rst-tone="positive">+12%</span>
    <span rst-stat-note>к прошлому месяцу</span>
  </div>
  <div rst-stat>
    <span rst-stat-label>Заказов сегодня</span>
    <span rst-stat-num>318</span>
  </div>
  <div rst-stat>
    <span rst-stat-label>Средний чек</span>
    <span rst-stat-num>&euro;41.20</span>
    <span rst-stat-delta rst-tone="negative">&minus;3%</span>
  </div>
  <div rst-stat>
    <span rst-stat-label>Возвраты</span>
    <span rst-stat-num>7</span>
  </div>
</div>

tblock

Карточка с рамкой, тело которой раскрывается только при включённом переключателе, через :has(). Главное — переключатель; раскрытие лишь удобство отображения.

Предпросмотр
<div rst-tblock>
  <label rst-tblock-head>
    <input type="checkbox" name="notify" checked>
    <span rst-switch-track aria-hidden="true"></span>
    <span>
      <span rst-tblock-title>Уведомления по почте</span>
      <span rst-tblock-desc>Приходят на каждый ответ в обсуждении, где вы участвуете.</span>
    </span>
  </label>
  <div rst-tblock-body>
    <div rst-field>
      <label rst-field-label for="notify-freq">Частота</label>
      <input rst-input type="text" id="notify-freq" name="notify_freq" value="Ежедневная сводка">
    </div>
  </div>
</div>