Design de produto empresarial · Novo recurso

Sistema de design REI Cedar.

Crie um seletor de atendimento de pedidos concreto com Cedar, blocos nativos do Vue, valores reais de tokens, navegação completa pelo teclado e uma composição responsiva de produtos.

Guia OpenDesign7 capítulos37 entradas de referênciaGuia de aplicação original
01

Prévia da interface do sistema de design REI Cedar

Use blocos nativos do Cedar para selecionar entrega ou retirada, com navegação por teclado e uma opção indisponível.

Escolha um método de entregaAbrir exemplo completo
Composição nativa de Cedar 17.1.0 / Vue 3. · Referência de implementação
02

Referência de design do sistema de design REI Cedar

Valores extraídos do tema REI de @rei/cdr-tokens 14.0.1; comportamento nativo dos componentes verificado com @rei/cedar 17.1.0.

Funções das cores do tema REI

Fonte
Nome / RegraValor / ConfiguraçãoUso
cdr-color-background-button-primary-rest#1f513f Preenchimento do botão primário.
cdr-color-background-button-primary-hover#c7dfd1 Preenchimento ao passar o cursor sobre o elemento principal.
cdr-color-background-primary#ffffff Superfície de conteúdo padrão.
cdr-color-background-secondary#F4F2ED Superfície secundária.
cdr-color-text-button-primary#fafbf9 Rótulo do botão principal.
cdr-color-text-primary#4b4a48 Função do texto principal.
cdr-color-text-secondary#736e65 Texto de apoio.
cdr-color-text-error#811823 Texto da mensagem de erro.
cdr-color-border-primary#d5cfc3 Limite da superfície principal.
cdr-color-border-secondary#958e83 Função de borda secundária.

Espaçamento e raio com raiz de 10px

Fonte
Nome / RegraValor / ConfiguraçãoUso
cdr-space-zero0Na raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-sixteenth-x0.1remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-eighth-x0.2remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-three-sixteenth-x0.3remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-quarter-x0.4remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-three-eighth-x0.6remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-half-x0.8remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-three-quarter-x1.2remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-one-x1.6remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-one-and-a-half-x2.4remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-two-x3.2remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-three-x4.8remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-space-four-x6.4remNa raiz do Cedar, 1rem equivale a 10px; não use esses valores sem alterações em uma raiz de 16px.
cdr-radius-sharp0Formato dos cantos definido pelo pacote de tokens fixado.
cdr-radius-soft0.2remFormato dos cantos definido pelo pacote de tokens fixado.
cdr-radius-softer0.4remFormato dos cantos definido pelo pacote de tokens fixado.
cdr-radius-softest0.6remFormato dos cantos definido pelo pacote de tokens fixado.
cdr-radius-round999.9remFormato dos cantos definido pelo pacote de tokens fixado.

Bloco de entrega API

Fonte
Nome / RegraValor / ConfiguraçãoUso
checkedbooleanReflete o método selecionado.
disabledbooleanOpção indisponível; não permita alterar o estado.
roleradio | checkboxUse radio para escolher um único método de entrega.
tabindex0 / -1A aplicação gerencia uma única parada de tabulação e a navegação pelas teclas de seta.
header slotmethod labelNome da opção fácil de entender.
body slotsupporting detailsPrazo de entrega ou local de retirada.
footer slotprominent detailCusto ou disponibilidade.
icon-right slotselection indicatorO exemplo adiciona uma marca de seleção ao método escolhido.
loadingbooleanOculta o corpo e o rodapé, mantendo o cabeçalho e as dimensões.
03

Guia completo do sistema de design REI Cedar

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

DESIGN-rei-cedar.md

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

Baixar o guia

Dependências de runtime e estilos do Vue do sistema de design REI Cedar

Fixe as versões dos componentes e dos tokens em conjunto

O exemplo funcional usa @rei/cedar 17.1.0 com @rei/cdr-tokens 14.0.1 e Vue 3. O pacote de componentes oferece pontos de entrada modulares. Este exemplo importa apenas CdrButton e CdrFulfillmentTile, além dos CSS necessários para os componentes aninhados de superfície, layout e texto. O código-fonte lista todas as importações, pois o comportamento de JavaScript, por si só, não garante uma saída estilizada.

Com base neste guia de OpenDesign

Não inclua fontes proprietárias no exemplo

As instruções de instalação do Cedar diferenciam o uso dos componentes dos direitos de uso das fontes da REI. O exemplo não importa cdr-fonts.css nem a folha de estilos agregada que contém as declarações de fontes. Ele usa fontes sem serifa do sistema para o texto da interface e Georgia para o título editorial original. Essas fontes alternativas são escolhas da aplicação, não a tipografia da marca REI.

Unidades dos tokens e cores de superfície do sistema de design REI Cedar

Use a escala da raiz do Cedar

Os tokens do Cedar expressam um espaçamento de 16px como 1.6rem porque o tamanho esperado da raiz é 10px. Definir uma raiz de 16px aumentaria o mesmo valor para 25.6px. O exemplo isolado define html como 62.5% e usa um tamanho de corpo de 1.6rem. Um produto hospedeiro com outra raiz precisa de um limite de integração definido intencionalmente, em vez de uma redefinição global aplicada a um site existente.

Associe os tokens às funções dos componentes

O botão principal usa um preenchimento verde-escuro no estado padrão e um preenchimento verde-claro ao passar o cursor. As superfícies de conteúdo e as bordas usam tons neutros quentes. A tabela registra valores semânticos do tema REI, não do tema do site de documentação. A bolsa ilustrada usa cores decorativas originais; elas não são apresentadas como exportações oficiais de tokens do Cedar.

Composição do bloco de entrega do sistema de design REI Cedar

Apresente uma opção variável por bloco

Um cartão de modalidade de recebimento agrupa o nome do método, o prazo e o custo ou a disponibilidade. Ele não deve conter um segundo link ou botão interativo. No exemplo, a ação de revisar fica fora do grupo de opções, e a opção de entrega expressa indisponível inclui uma explicação que continua legível. Os espaços de cabeçalho, corpo e rodapé deixam a hierarquia explícita.

Indique a seleção além da borda

O método selecionado recebe checked=true e um sinal de confirmação no espaço icon-right. Assim, a opção atual fica evidente mesmo quando é difícil distinguir bordas sutis. Clicar em uma opção disponível atualiza apenas a seleção; a etapa separada de revisão confirma a escolha local. Métodos desabilitados nunca atualizam o modelo.

Contexto do produto e layout responsivo do sistema de design REI Cedar

Mantenha o item ao lado das opções

Em telas mais largas, uma ilustração original de uma mochila CSS e o resumo do produto ficam ao lado das opções de recebimento. O produto é fictício, e os prazos de entrega estão identificados como exemplos. A composição demonstra as superfícies acolhedoras do Cedar sem copiar fotos de produtos da REI nem inventar informações de estoque em tempo real.

Reorganize o layout em vez de reduzir os controles

Seleção, teclado e feedback no sistema de design REI Cedar

Implemente o comportamento de opções de rádio no nível da aplicação

Os cartões expõem a semântica de opções de rádio, mas a aplicação controla o rótulo do grupo, o valor selecionado e o modelo de foco. Apenas a opção disponível selecionada faz parte da ordem de tabulação. As teclas de seta percorrem as opções disponíveis, Home e End selecionam a primeira e a última opção, e a entrega expressa indisponível é ignorada. Isso está incluído no código-fonte completo, em vez de ficar como uma pendência de acessibilidade.

Invalide feedback de revisão desatualizado

A revisão da seleção grava um status local preciso, sem afirmar que um pedido foi feito. Ao mudar o cartão selecionado, o resultado anterior é apagado. A região de status fica separada da descrição do método, para que a tecnologia assistiva possa anunciar o feedback sem alterar o nome acessível da opção de rádio.

Implementação completa em Vue do sistema de design REI Cedar

Reproduza a mesma tela nativa

Crie um projeto Vue com Vite, instale os pacotes fixados e use os exemplos completos de main.js e cedar.css abaixo. Mantenha o nome do elemento raiz como root ou atualize o seletor de montagem para corresponder ao modelo do Vite. O exemplo usa funções de renderização do Vue para que nenhum pré-processamento de SFC fique oculto para quem lê.

  1. Instale os pacotes fixados de componentes e tokens.
  2. Mantenha todos os imports de CSS de main.js.
  3. Monte o aplicativo no elemento root.
  4. Use as teclas de seta para mudar a modalidade de recebimento e revisar o resultado local.

Confira os estilos antes de depurar o layout

A primeira verificação de integração é confirmar que os cartões têm superfícies, contornos e espaçamento interno, e que o botão está estilizado com Cedar. Se a interface funciona, mas parece texto simples, confira os imports de componente CSS e de token CSS. Se o espaçamento estiver grande demais, verifique o tamanho da fonte raiz. São causas distintas e exigem soluções diferentes.

Entrega para agentes e critérios de aceitação do sistema de design REI Cedar

Defina os limites da integração

Peça ao agente uma interface de seleção de modalidade de recebimento em Vue 3 usando os componentes Cedar fixados e o pacote de tokens, sem fontes proprietárias. Forneça os estados exatos dos cartões e o comportamento do teclado. Para um produto real, substitua os prazos fictícios por um contrato de backend e trate carregamento e falhas antes de habilitar uma ação de pedido.

Revise o comportamento e o código-fonte em conjunto

A verificação local cobre a seleção pelas teclas de seta, o estado selecionado visível, a confirmação local, a limpeza de resultados desatualizados e layouts estreitos. O guia para download inclui o mesmo código da aplicação usado na prévia. A verificação no ambiente de execução nativo não torna reais os prazos de entrega do exemplo nem concede permissão para reutilizar a marca da REI.

  • Métodos indisponíveis não podem ser selecionados.
  • Ao mudar uma opção, a confirmação anterior é apagada.
  • Não são necessários arquivos de fontes nem chamadas a serviços.

Exemplos de componentes do sistema de design REI Cedar

main.js — seletor completo de modalidade de recebimento em Vue

Componentes nativos, estado local, foco móvel entre opções de rádio e todos os imports de estilo necessários.

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

Referência de código

  • Use <div id="root"></div> em index.html.

cedar.css — composição original do produto

Layout responsivo, ilustração CSS e alternativas de fonte explícitas.

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;
  }
}

Referência de código

  • Nenhum arquivo de fonte proprietária da REI é importado.
04

Configuração de agente para o sistema de design REI Cedar

Ponto de partida para implementação

A prévia inclui estes módulos nativos localmente. As fontes usam alternativas do sistema.

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

Um prompt para seu projeto

Prompt para agente de IA
Crie um seletor de modalidade de recebimento em Vue 3 com Cedar 17.1.0 e tokens 14.0.1 usando este código-fonte completo. Mantenha isolada a escala de 10px da raiz, importe o componente e o pacote de tokens CSS necessários, evite fontes proprietárias e preserve o foco móvel entre opções de rádio e as opções desabilitadas. Use disponibilidade fictícia até que seja fornecido um contrato de estoque real.
05

Fontes e escopo do sistema de design REI Cedar

Um guia de OpenDesign para REI Cedar. O exemplo usa Cedar 17.1.0 e tokens 14.0.1. Os detalhes de produto, ilustração, loja e entrega são fictícios; fontes proprietárias e fotografias da REI não estão incluídas.