# REI Cedar 设计系统

## REI Cedar 设计系统界面预览

使用原生 Cedar 磁贴选择配送或自取方式，支持键盘导航，并展示不可选选项。

## REI Cedar 设计系统设计参考

从 @rei/cdr-tokens 14.0.1 的 REI 主题中提取值；使用 @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-zero | 0 | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-sixteenth-x | 0.1rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-eighth-x | 0.2rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-three-sixteenth-x | 0.3rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-quarter-x | 0.4rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-three-eighth-x | 0.6rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-half-x | 0.8rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-three-quarter-x | 1.2rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-one-x | 1.6rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-one-and-a-half-x | 2.4rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-two-x | 3.2rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-three-x | 4.8rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-space-four-x | 6.4rem | 在 Cedar 根元素中，1rem 等于 10px；不要将这些值原样用于 16px 根字号。 |
| cdr-radius-sharp | 0 | 由固定版本的令牌包定义的圆角形状。 |
| cdr-radius-soft | 0.2rem | 由固定版本的令牌包定义的圆角形状。 |
| cdr-radius-softer | 0.4rem | 由固定版本的令牌包定义的圆角形状。 |
| cdr-radius-softest | 0.6rem | 由固定版本的令牌包定义的圆角形状。 |
| cdr-radius-round | 999.9rem | 由固定版本的令牌包定义的圆角形状。 |
### 履约方式磁贴 API

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| checked | boolean | 反映所选方式。 |
| disabled | boolean | 不可选选项；不允许更改状态。 |
| role | radio \| checkbox | 选择一种履约方式时使用 radio。 |
| tabindex | 0 / -1 | 由应用管理单个 Tab 停靠点和方向键导航。 |
| header slot | method label | 易于理解的选项名称。 |
| body slot | supporting details | 配送时间或自取地点。 |
| footer slot | prominent detail | 费用或可用性。 |
| icon-right slot | selection indicator | 示例为选中的方式添加了勾选标记。 |
| loading | boolean | 隐藏主体和页脚，同时保留页眉与尺寸。 |
## REI Cedar 设计系统完整指南

实用指南，介绍如何为真实界面选择、应用和评审此系统。

完整指导、实现起点和源代码链接。

## REI Cedar 设计系统 Vue 运行时与样式依赖

### 将组件与令牌版本固定搭配

> 可运行的示例使用 @rei/cedar 17.1.0、@rei/cdr-tokens 14.0.1 和 Vue 3。组件包提供模块化入口。本示例只导入 CdrButton、CdrFulfillmentTile，以及其嵌套的表面、布局和文本组件所需的 CSS。源码列出了所有导入项，因为仅凭 JavaScript 的行为并不能保证输出带样式的界面。

### 示例中不使用专有字体

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 设计系统履约方式卡片组合

### 每个磁贴呈现一种可切换的选择

履约方式磁贴将方式名称、时间和费用或可用性组合在一起。磁贴中不应再包含第二个可交互链接或按钮。示例将审核操作放在 radio 组之外，并为不可选的特快选项提供了始终清晰可读的说明。页眉、主体和页脚插槽使层级关系一目了然。

### 除了边框之外，也要呈现选中状态

选中的方式会设置为 checked=true，并在 icon-right 插槽中显示勾号。这样即使边框样式不明显，当前选项也一目了然。点击可用选项只会更新选择；本地选择需通过单独的复核步骤确认。禁用的方式不会更新模型。

## REI Cedar 设计系统：产品情境与响应式布局

### 将商品放在选项旁边

在较宽的屏幕上，原创的 CSS 日用背包插图和商品摘要会显示在配送选项旁边。商品为虚构商品，配送承诺也明确标注为示例。此布局展现 Cedar 温暖的界面表面风格，不会照搬 REI 的商品摄影，也不会虚构实时库存信息。

### 重新排布控件，而非缩小控件

屏幕宽度低于 700px 时，选项会调整为全宽区域，显示在精简的商品摘要之后。700px 是应用的布局决策，并非 Cedar 的断点令牌。卡片内容可以换行，示例整体高度随内容变化，而不是固定为视口高度。商品插图仍为装饰性内容。

## REI Cedar 设计系统：选择、键盘交互与反馈

### 实现应用级单选行为

这些卡片提供单选语义，但分组标签、选中值和焦点模型由应用负责。只有已选中的可用选项位于 Tab 键顺序中。使用方向键可在可用选项间切换，Home 和 End 键可选择首尾选项；不可用的加急配送会被跳过。这些行为已包含在完整源码中，而不是留作无障碍待办事项。

### 清除过时的复核反馈

复核选项会写入准确的本地状态，不会声称订单已经提交。更改选中的卡片会清除之前的结果。状态区域与方式描述分开，因此辅助技术可以播报反馈，而不会改变单选项的无障碍名称。

## REI Cedar 设计系统：完整 Vue 实现

### 复现相同的原生界面

创建 Vite Vue 项目，安装固定版本的依赖包，并使用下方完整的 main.js 和 cedar.css 示例。根元素应命名为 root；也可以相应修改挂载选择器以匹配 Vite 模板。示例使用 Vue 渲染函数，因此读者无需处理未展示的单文件组件预处理步骤。

1. 安装固定版本的组件包和令牌包。

2. 保留 main.js 中所有 CSS 导入。

3. 将应用挂载到 root 元素。

4. 使用方向键更改配送方式，并查看本地结果。

### 调试布局前先检查样式

集成检查的第一步是确认卡片具有界面表面、边界和内边距，并且按钮应用了 Cedar 样式。如果界面可以交互，但看起来只有纯文本，请检查组件 CSS 和令牌 CSS 的导入。如果间距过大，请检查根元素的字号。这些问题成因不同，需要分别处理。

## REI Cedar 设计系统：AI Agent 交接与验收

### 明确集成边界

请 AI Agent 使用固定版本的 Cedar 组件和令牌包，构建一个 Vue 3 配送方式选择器，不使用专有字体。提供准确的卡片状态和键盘交互行为。对于真实商品，在启用下单操作前，应以后台接口约定替换虚构的配送时效，并处理加载和失败状态。

### 结合行为与源码进行审核

本地验证涵盖方向键选择、可见的选中状态、本地确认、过时结果清除和窄屏布局。可下载指南包含与预览相同的应用代码。通过原生运行时验证，并不意味着示例配送承诺真实有效，也不代表获得了使用 REI 品牌的许可。

- 不可用的方式无法被选中。

- 更改选项会清除之前的确认结果。

- 无需字体资源或服务调用。

## REI Cedar 设计系统组件示例

### main.js — 完整的 Vue 配送方式选择器

原生组件、本地状态、单选项循环焦点，以及所有必需的样式导入。

```
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");
```

代码参考

- 在 index.html 中使用 <div id="root"></div>。

### cedar.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 专有字体文件。

## REI Cedar 设计系统：AI Agent 设置

### 实现起点

此预览会在本地打包这些原生模块。字体使用系统回退字体。

```
npm create vite@latest cedar-study -- --template vue
cd cedar-study
npm install
npm install @rei/cedar@17.1.0 @rei/cdr-tokens@14.0.1
# 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
```

### 适用于你项目的提示词

```
使用此完整源码，结合 Cedar 17.1.0 和 tokens 14.0.1 构建 Vue 3 配送方式选择器。将 10px 根字号设置单独隔离，导入所需的组件和令牌 CSS，避免使用专有字体，并保留单选项循环焦点和禁用选项。在提供真实库存接口约定前，请使用虚构的库存信息。
```

## REI Cedar 设计系统：来源与范围

OpenDesign REI Cedar 指南。示例使用 Cedar 17.1.0 和 tokens 14.0.1。商品、插图、门店和配送详情均为虚构内容；不包含 REI 专有字体或摄影作品。

- 安装 Cedar Vue 设置、CSS 集成与字体使用边界。

- 配送方式卡片 插槽、状态与应用的无障碍职责。

- 令牌参考 Web 令牌角色与取值。

- Cedar 源码 组件源码与软件包版本。

## REI Cedar 设计系统相关资源

### Sainsbury's 设计系统

将 Sainsbury’s 的公开设计指南应用于完整的配送时段选择流程：使用真实的配色和尺寸参考、无障碍单选项、动态更新的摘要，以及如实说明的本地操作反馈。

### Salesforce Lightning

一份 Lightning 蓝图指南，适用于密集的记录处理场景：真实的间距、字体与语义色，一个可编辑的案例工作区、字段验证，以及能反映本地变更的活动历史记录。

### Samsung One UI

通过完整的原创阅读偏好预览，了解 One UI 的浏览与交互结构、24dp 边距建议、200% 文本缩放要求，以及深色外观和明确的重置恢复方式。


- [实现参考](https://cedar.rei.com/components/fulfillment-tile)
- [来源](https://cedar.rei.com/tokens/web)
- [来源](https://cedar.rei.com/components/fulfillment-tile)
- [代码参考](https://cedar.rei.com/components/fulfillment-tile)
- [代码参考](https://cedar.rei.com/tools-resources/installing-cedar)
- [安装 Cedar Vue 设置、CSS 集成与字体使用边界。](https://cedar.rei.com/tools-resources/installing-cedar)
- [配送方式卡片 插槽、状态与应用的无障碍职责。](https://cedar.rei.com/components/fulfillment-tile)
- [令牌参考 Web 令牌角色与取值。](https://cedar.rei.com/tokens/web)
- [Cedar 源码 组件源码与软件包版本。](https://github.com/rei/rei-cedar)
