Дизайн корпоративных продуктов · Новый ресурс

Дизайн-система REI Cedar.

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

Руководство OpenDesign7 глав37 справочных записейАвторское руководство по приложению
01

Предварительный просмотр интерфейса дизайн-системы REI Cedar

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

Выберите способ полученияОткрыть полный пример
Встроенные Cedar 17.1.0 / Vue 3 с авторской композицией. · Справочник по реализации
02

Справочник дизайн-системы REI Cedar

Значения извлечены из темы REI пакета @rei/cdr-tokens 14.0.1; поведение встроенных компонентов проверено с @rei/cedar 17.1.0.

Цветовые роли темы REI

Источник
Название / правилоЗначение / конфигурацияПрименение
cdr-color-background-button-primary-rest#1f513f Заливка основной кнопки.
cdr-color-background-button-primary-hover#c7dfd1 Заливка при наведении на основной элемент.
cdr-color-background-primary#ffffff Поверхность содержимого по умолчанию.
cdr-color-background-secondary#F4F2ED Вторичная поверхность.
cdr-color-text-button-primary#fafbf9 Подпись основной кнопки.
cdr-color-text-primary#4b4a48 Роль основного текста.
cdr-color-text-secondary#736e65 Вспомогательный текст.
cdr-color-text-error#811823 Текст сообщения об ошибке.
cdr-color-border-primary#d5cfc3 Граница основной поверхности.
cdr-color-border-secondary#958e83 Роль второстепенной границы.

Интервалы и радиусы при корневом размере 10px

Источник
Название / правилоЗначение / конфигурацияПрименение
cdr-space-zero0В Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-sixteenth-x0.1remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-eighth-x0.2remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-three-sixteenth-x0.3remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-quarter-x0.4remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-three-eighth-x0.6remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-half-x0.8remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-three-quarter-x1.2remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-one-x1.6remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-one-and-a-half-x2.4remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-two-x3.2remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-three-x4.8remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-space-four-x6.4remВ Cedar 1rem при корневом размере равен 10px; не применяйте эти значения без изменений при корневом размере 16px.
cdr-radius-sharp0Форма углов из зафиксированного пакета токенов.
cdr-radius-soft0.2remФорма углов из зафиксированного пакета токенов.
cdr-radius-softer0.4remФорма углов из зафиксированного пакета токенов.
cdr-radius-softest0.6remФорма углов из зафиксированного пакета токенов.
cdr-radius-round999.9remФорма углов из зафиксированного пакета токенов.

Плитка способа получения API

Источник
Название / правилоЗначение / конфигурацияПрименение
checkedbooleanОтражает выбранный способ.
disabledbooleanНедоступный вариант; изменение состояния запрещено.
roleradio | checkboxИспользуйте radio для выбора одного способа получения.
tabindex0 / -1Приложение управляет единственной точкой фокусировки и навигацией клавишами со стрелками.
header slotmethod labelПонятное название варианта.
body slotsupporting detailsСрок доставки или место самовывоза.
footer slotprominent detailСтоимость или доступность.
icon-right slotselection indicatorВ примере у выбранного способа появляется галочка.
loadingbooleanСкрывает содержимое и нижнюю часть, сохраняя заголовок и размеры.
03

REI Cedar: полное руководство по дизайн-системе

Практическое руководство по выбору, применению и оценке этой системы для реального интерфейса.

DESIGN-rei-cedar.md

Подробные рекомендации, отправная точка для реализации и ссылки на источники.

Скачать руководство

Среда выполнения Vue и зависимости стилей дизайн-системы REI Cedar

Фиксируйте версии компонентов и токенов вместе

В примере используются @rei/cedar 17.1.0, @rei/cdr-tokens 14.0.1 и Vue 3. Пакет компонентов предлагает модульные точки входа. В этом примере импортируются только CdrButton и CdrFulfillmentTile, а также CSS, необходимые для вложенных компонентов поверхности, компоновки и текста. В исходном коде перечислены все импорты: само по себе подключение компонентов JavaScript не гарантирует стилизованный результат.

Из этого руководства OpenDesign

Не используйте проприетарные шрифты в примере

В инструкциях по установке Cedar отдельно рассматриваются использование компонентов и права на шрифты REI. В примере не импортируются cdr-fonts.css и общая таблица стилей со встроенными шрифтами. Для текста интерфейса используются системный шрифт без засечек, а для авторского редакционного заголовка — Georgia. Это выбранные для приложения запасные шрифты, а не фирменный шрифт REI.

Единицы токенов и цвета поверхности в дизайн-системе REI Cedar

Используйте корневую шкалу Cedar

В токенах Cedar расстояние 16px записано как 1.6rem, поскольку предполагается размер корневого шрифта 10px. Если задать корневой размер 16px, то это же значение составит 25.6px. В изолированном примере для html задано значение 62.5%, а размер шрифта body — 1.6rem. Если в основном продукте используется другой корневой размер, интеграцию нужно продумать отдельно, а не добавлять глобальный сброс стилей на существующий сайт.

Сопоставьте токены с ролями компонентов

В обычном состоянии основная кнопка залита тёмно-зелёным цветом, а при наведении — светло-зелёным. Для поверхностей содержимого и границ используются тёплые нейтральные оттенки. В таблице приведены семантические значения из темы REI, а не темы сайта с документацией. В иллюстрации сумки используются авторские декоративные цвета; они не выдаются за официальные токены Cedar.

Компоновка плиток способов получения в дизайн-системе REI Cedar

Размещайте один изменяемый вариант на плитке

Плитка способа получения объединяет название, срок и стоимость либо доступность. Она не должна содержать вторую интерактивную ссылку или кнопку. В примере действие проверки расположено за пределами группы переключателей, а у недоступного экспресс-варианта есть понятное пояснение. Слоты заголовка, основного содержимого и нижней части явно задают иерархию.

Показывайте выбор не только рамкой

Для выбранного способа устанавливается checked=true, а в слоте icon-right появляется галочка. Благодаря этому текущий выбор заметен, даже если тонкие различия в оформлении границ трудно различить. Нажатие на доступный вариант меняет только выбор; отдельный этап проверки подтверждает выбор в приложении. Отключённые способы не обновляют модель.

Контекст продукта и адаптивная компоновка дизайн-системы REI Cedar

Размещайте товар рядом с вариантами получения

На широких экранах авторская иллюстрация рюкзака CSS и краткая информация о товаре располагаются рядом с вариантами получения. Товар вымышленный, а сроки доставки обозначены как примеры. Компоновка демонстрирует тёплые поверхности Cedar без использования фотографий товаров REI и выдуманных сведений о наличии.

Перестраивайте компоновку, а не уменьшайте элементы управления

Выбор, клавиатура и обратная связь в дизайн-системе REI Cedar

Реализуйте поведение группы переключателей на уровне приложения

Для плиток заданы роли переключателей, но приложение отвечает за название группы, выбранное значение и модель фокуса. В порядке перехода по клавише Tab находится только выбранный доступный вариант. Клавиши со стрелками переключают доступные варианты по кругу, Home и End выбирают крайние варианты, а недоступный экспресс-способ пропускается. Всё это реализовано в полном исходном коде, а не оставлено в виде TODO по доступности.

Сбрасывайте устаревшую обратную связь при проверке

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

Полная реализация на Vue для дизайн-системы REI Cedar

Воспроизведите тот же экран в нативном окружении

Создайте проект Vue на Vite, установите закреплённые версии пакетов и используйте приведённые ниже полные примеры main.js и cedar.css. Оставьте корневому элементу имя root или измените селектор монтирования в соответствии с шаблоном Vite. В примере используются функции render Vue, поэтому читателю не нужно учитывать скрытую предварительную обработку SFC.

  1. Установите компоненты и токены закреплённых версий.
  2. Сохраните все импорты CSS из main.js.
  3. Смонтируйте приложение в корневой элемент.
  4. Используйте клавиши со стрелками, чтобы выбрать способ получения, и проверьте локальный результат.

Перед отладкой компоновки проверьте стили

При первой проверке интеграции убедитесь, что у плиток есть фон, границы и внутренние отступы, а у кнопки — стили Cedar. Если интерфейс работает, но выглядит как простой текст, проверьте импорты компонентов CSS и токенов CSS. Если отступы слишком большие, проверьте размер корневого шрифта. Это разные причины, и способы их устранения тоже различаются.

Передача задания AI-агенту и критерии приёмки для дизайн-системы REI Cedar

Определите границы интеграции

Попросите AI-агента создать селектор способов получения на Vue 3 с закреплёнными версиями компонентов Cedar и пакета токенов, без проприетарных шрифтов. Укажите точные состояния плиток и поведение с клавиатуры. Для реального товара замените вымышленные сроки контрактом с серверной частью и предусмотрите состояния загрузки и ошибок, прежде чем активировать действие оформления заказа.

Проверяйте поведение и исходный код вместе

Локальная проверка охватывает выбор клавишами со стрелками, видимое состояние выбора, локальное подтверждение, сброс устаревшего результата и узкие экраны. Загружаемое руководство содержит тот же код приложения, что и предпросмотр. Проверка в нативном окружении не превращает примерные сроки доставки в реальные и не даёт разрешения использовать фирменный стиль REI.

  • Недоступные способы нельзя выбрать.
  • При смене варианта старое подтверждение сбрасывается.
  • Файлы шрифтов и вызовы сервисов не требуются.

Примеры компонентов дизайн-системы REI Cedar

main.js — полный селектор способов получения на Vue

Нативные компоненты, локальное состояние, циклическая навигация по переключателям и все необходимые импорты стилей.

js
import { createApp, h, ref } from "vue";
import CdrButton from "@rei/cedar/CdrButton";
import CdrFulfillmentTile from "@rei/cedar/CdrFulfillmentTile";
import "@rei/cedar/dist/cdr-reset.css";
import "@rei/cedar/dist/style/cdr-button.css";
import "@rei/cedar/dist/style/cdr-fulfillment-title.css";
import "@rei/cedar/dist/style/cdr-surface-selection.css";
import "@rei/cedar/dist/style/cdr-layout.css";

import "@rei/cdr-tokens/css";
import "@rei/cedar/dist/style/cdr-surface.css";
import "@rei/cedar/dist/style/cdr-body.css";
import "@rei/cedar/dist/style/cdr-subheading-sans.css";
import "./cedar.css";
const choices = [
  {
    id: "ship",
    label: "Ship to home",
    detail: "Sample delivery: 3–5 days",
    price: "No delivery charge",
    available: true,
  },
  {
    id: "pickup",
    label: "Pick up nearby",
    detail: "Sample location: North Trail",
    price: "Ready tomorrow",
    available: true,
  },
  {
    id: "express",
    label: "Express delivery",
    detail: "Unavailable for this sample item",
    price: "Choose another method",
    available: false,
  },
];
createApp({
  setup() {
    const selected = ref("ship"),
      result = ref("");
    function choose(id) {
      selected.value = id;
      result.value = "";
    }
    function keyboard(e, id) {
      if (
        [
          "ArrowRight",
          "ArrowDown",
          "ArrowLeft",
          "ArrowUp",
          "Home",
          "End",
        ].includes(e.key)
      ) {
        e.preventDefault();
        const ids = choices.filter((x) => x.available).map((x) => x.id);
        let next =
          e.key === "Home"
            ? ids[0]
            : e.key === "End"
              ? ids.at(-1)
              : ids[
                  (ids.indexOf(id) +
                    (e.key === "ArrowRight" || e.key === "ArrowDown"
                      ? 1
                      : ids.length - 1)) %
                    ids.length
                ];
        choose(next);
        document.getElementById("choice-" + next).focus();
      }
    }
    return () =>
      h("main", [
        h("header", [
          h("p", { class: "eyebrow" }, "OUTDOOR GEAR / ORIGINAL SPECIMEN"),
          h("h1", "Ready for the next trail"),
          h("p", "Choose a fulfillment method for this fictional daypack."),
        ]),
        h("div", { class: "composition" }, [
          h("section", { class: "product", "aria-label": "Sample product" }, [
            h("div", { class: "art", "aria-hidden": "true" }, [
              h("div", { class: "pack" }, [h("i"), h("span"), h("b")]),
            ]),
            h("div", [
              h("h2", "Ridge daypack · 24 L"),
              h("p", "A lightweight everyday pack for short outings."),
              h(
                "p",
                { class: "note" },
                "Illustrated sample product · no inventory or purchase connection",
              ),
            ]),
          ]),
          h("section", { class: "options" }, [
            h(
              "h2",
              { id: "fulfillment-label" },
              "How would you like to receive it?",
            ),
            h(
              "div",
              {
                class: "tiles",
                role: "radiogroup",
                "aria-labelledby": "fulfillment-label",
              },
              choices.map((c) =>
                h(
                  CdrFulfillmentTile,
                  {
                    id: "choice-" + c.id,
                    role: "radio",
                    tabindex: c.available && selected.value === c.id ? 0 : -1,
                    checked: selected.value === c.id,
                    disabled: !c.available,
                    "aria-label": c.label,
                    onClick: () => c.available && choose(c.id),
                    onKeydown: (e) => keyboard(e, c.id),
                  },
                  {
                    header: () => c.label,
                    "icon-right": () =>
                      selected.value === c.id
                        ? h(
                            "span",
                            {
                              "aria-hidden": "true",
                              style: "font-size:2rem;color:#1f513f",
                            },
                            "✓",
                          )
                        : null,
                    body: () => c.detail,
                    footer: () => c.price,
                  },
                ),
              ),
            ),
            h("div", { class: "review" }, [
              h(
                CdrButton,
                {
                  onClick: () => {
                    result.value = `Local selection: ${choices.find((c) => c.id === selected.value).label}. No order has been placed.`;
                  },
                },
                () => "Review selection",
              ),
              h("p", { role: "status", class: "result" }, result.value),
            ]),
          ]),
        ]),
        h(
          "footer",
          "Native Cedar 17.1.0 fulfillment tiles and button. Original composition with system-font fallback; no REI proprietary fonts or photography.",
        ),
      ]);
  },
}).mount("#root");

Справочник по коду

  • Используйте <div id="root"></div> в index.html.

cedar.css — авторская компоновка товара

Адаптивная компоновка, иллюстрация CSS и явно заданные запасные шрифты.

css
html {
  font-size: 62.5%;
}
body {
  margin: 0;
  color: #2e2e2b;
  background: #fafbf9;
  font:
    1.6rem/1.5 system-ui,
    sans-serif;
}
* {
  box-sizing: border-box;
}
main {
  padding: 3.2rem;
}
header {
  border-bottom: 1px solid #dcd6cb;
  margin-bottom: 3.2rem;
  padding-bottom: 2.4rem;
}
h1 {
  font:
    700 3.6rem/1.1 Georgia,
    serif;
  margin: 1.2rem 0;
}
h2 {
  font:
    700 2.2rem/1.25 system-ui,
    sans-serif;
  margin: 0 0 1.6rem;
}
p {
  margin: 0.8rem 0;
}
.eyebrow,
footer,
.note {
  font-size: 1.4rem;
  color: #4b4a48;
}
.composition {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 4.8rem;
}
.product {
  display: grid;
  gap: 2.4rem;
  align-content: start;
}
.art {
  height: 25rem;
  background: #edeae3;
  border-radius: 0.4rem;
  display: grid;
  place-items: center;
}
.pack {
  position: relative;
  width: 12rem;
  height: 17rem;
  border-radius: 4rem 4rem 2rem 2rem;
  background: #48633c;
  border: 0.6rem solid #34492c;
  box-shadow: 2rem 1rem 0 -1.2rem #b3ad9f;
}
.pack i {
  position: absolute;
  top: -2.2rem;
  left: 3.2rem;
  width: 4.4rem;
  height: 2.4rem;
  border: 0.7rem solid #34492c;
  border-bottom: 0;
  border-radius: 1.4rem 1.4rem 0 0;
}
.pack span {
  position: absolute;
  left: 1.2rem;
  right: 1.2rem;
  bottom: 1.2rem;
  height: 7rem;
  border-radius: 1rem;
  background: #607b52;
  border-top: 0.5rem solid #34492c;
}
.pack b {
  position: absolute;
  left: 4.4rem;
  top: 4rem;
  width: 2rem;
  height: 2rem;
  background: #edeae3;
  border-radius: 50%;
}
.tiles {
  display: grid;
  gap: 1.6rem;
}
.tiles > * {
  font-family: system-ui, sans-serif !important;
}
.review {
  margin-top: 2.4rem;
}
.result {
  color: #355e28;
  font-size: 1.4rem;
  margin-top: 1.6rem;
}
footer {
  margin-top: 3.2rem;
  padding-top: 1.6rem;
  border-top: 1px solid #dcd6cb;
}
:focus-visible {
  outline: 3px solid #406eb5;
  outline-offset: 3px;
}
@media (max-width: 700px) {
  main {
    padding: 2rem;
  }
  .composition {
    grid-template-columns: 1fr;
    gap: 3.2rem;
  }
  .product {
    grid-template-columns: 12rem 1fr;
    gap: 1.6rem;
  }
  .art {
    height: 17rem;
  }
  .pack {
    transform: scale(0.7);
  }
  h1 {
    font-size: 2.8rem;
  }
  .product h2 {
    font-size: 1.8rem;
  }
}

Справочник по коду

  • Проприетарные файлы шрифтов REI не импортируются.
04

Настройка AI-агента для дизайн-системы REI Cedar

Отправная точка для реализации

Предпросмотр локально включает эти нативные модули. Для шрифтов используются системные запасные варианты.

sh
npm create vite@latest cedar-study -- --template vue
cd cedar-study
npm install
npm install @rei/[email protected] @rei/[email protected]
# Replace src/main.js and add src/cedar.css with the complete examples.
# Change the index.html mount element to id="root".
npm run dev

Запрос для вашего проекта

Промпт для AI-агента
Создайте селектор способов получения на Vue 3 с Cedar 17.1.0 и tokens 14.0.1, используя этот полный исходный код. Изолируйте корневую шкалу 10px, импортируйте необходимые компоненты и токены CSS, не используйте проприетарные шрифты и сохраните циклическую навигацию по переключателям и отключённые варианты. Используйте вымышленные сведения о доступности, пока не будет предоставлен реальный контракт с системой учёта запасов.
05

Источники и область применения дизайн-системы REI Cedar

Руководство OpenDesign по REI Cedar. В примере используются Cedar 17.1.0 и tokens 14.0.1. Данные о товаре, иллюстрации, магазине и доставке вымышленные; проприетарные шрифты и фотографии REI не включены.