Software de atendimento ao cliente · Novo recurso

Sistema de design Zendesk Garden.

Um guia Garden para tarefas de suporte, com aliases de tema reais, escalas de tipografia e raio, um editor de resposta completo, rascunhos locais que levam em conta a visibilidade e recuperação de campos.

Guia OpenDesign8 capítulos42 referênciasGuia de aplicação original
01

Zendesk Garden Prévia da interface do sistema de design

Alterne a visibilidade da resposta, valide um rascunho curto, salve uma captura local e limpe o próximo rascunho.

Redija uma resposta com o contexto do cliente à vistaAbrir exemplo completo
ThemeProvider, Buttons e Forms nativos do Garden 9.16.1 React; fluxo de redação local original. · Referência de implementação
02

Referência do sistema de design Zendesk Garden

Garden nativo 9.16.1 React ThemeProvider, Buttons e Forms; fluxo original de criação de rascunho local.

Raio dos cantos

Fonte
Nome / RegraValor / ConfiguraçãoUso
borderRadii.sm2pxEscolha o formato conforme a função do componente; o canto médio padrão não é um formato de pílula.
borderRadii.md4pxEscolha o formato conforme a função do componente; o canto médio padrão não é um formato de pílula.
borderRadii.lg8pxEscolha o formato conforme a função do componente; o canto médio padrão não é um formato de pílula.

Pontos de quebra responsivos

Fonte
Nome / RegraValor / ConfiguraçãoUso
breakpoints.xs0pxPontos de quebra do tema, não uma garantia de que a aplicação alterne todas as regiões em cada etapa.
breakpoints.sm576pxPontos de quebra do tema, não uma garantia de que a aplicação alterne todas as regiões em cada etapa.
breakpoints.md768pxPontos de quebra do tema, não uma garantia de que a aplicação alterne todas as regiões em cada etapa.
breakpoints.lg992pxPontos de quebra do tema, não uma garantia de que a aplicação alterne todas as regiões em cada etapa.
breakpoints.xl1200pxPontos de quebra do tema, não uma garantia de que a aplicação alterne todas as regiões em cada etapa.

Tamanhos de fonte

Fonte
Nome / RegraValor / ConfiguraçãoUso
fontSizes.xs10pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.sm12pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.md14pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.lg18pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.xl22pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.xxl26pxMantenha distintas as funções de corpo, rótulo, metadados e título.
fontSizes.xxxl36pxMantenha distintas as funções de corpo, rótulo, metadados e título.

Alturas de linha

Fonte
Nome / RegraValor / ConfiguraçãoUso
lineHeights.sm16pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.
lineHeights.md20pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.
lineHeights.lg24pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.
lineHeights.xl28pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.
lineHeights.xxl32pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.
lineHeights.xxxl44pxUse em conjunto com a função de texto; não derive todas as alturas de linha do tamanho da fonte.

Escala de espaçamento

Fonte
Nome / RegraValor / ConfiguraçãoUso
space.base4Valores de espaçamento do tema para manter um ritmo previsível.
space.xxs4pxValores de espaçamento do tema para manter um ritmo previsível.
space.xs8pxValores de espaçamento do tema para manter um ritmo previsível.
space.sm12pxValores de espaçamento do tema para manter um ritmo previsível.
space.md20pxValores de espaçamento do tema para manter um ritmo previsível.
space.lg32pxValores de espaçamento do tema para manter um ritmo previsível.
space.xl40pxValores de espaçamento do tema para manter um ritmo previsível.
space.xxl48pxValores de espaçamento do tema para manter um ritmo previsível.

Mapeamento de funções semânticas para o tema claro

Fonte
Nome / RegraValor / ConfiguraçãoUso
colors.variables.light.background.defaultpalette.whiteAlias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.background.subtleneutralHue.100Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.background.dangerdangerHue.100Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.background.primaryEmphasisprimaryHue.700Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.foreground.defaultneutralHue.900Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.foreground.subtleneutralHue.700Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.foreground.onEmphasispalette.whiteAlias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.foreground.primaryprimaryHue.700Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.foreground.dangerdangerHue.700Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.border.defaultneutralHue.300Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.border.subtleneutralHue.200Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.border.dangerdangerHue.300Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
colors.variables.light.border.primaryEmphasisprimaryHue.700Alias de função do tema; resolva-o por meio do matiz e da paleta selecionados, em vez de tratá-lo como uma cor CSS literal.
03

Guia completo do sistema de design Zendesk Garden

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

DESIGN-zendesk-garden.md

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

Baixar o guia

Estrutura do espaço de trabalho de suporte do sistema de design Zendesk Garden

Mantenha a solicitação do cliente à vista

Um editor de respostas de suporte precisa de contexto suficiente para evitar uma resposta bem apresentada, mas irrelevante. O exemplo exibe a solicitação do cliente acima do rascunho, com a pessoa solicitante, a organização e o assunto ao lado. A interface é compacta o bastante para permitir comparar o novo texto com a pergunta original sem trocar de tela.

Com base neste guia de OpenDesign

Separe o histórico do rascunho ativo

As entradas locais salvas aparecem acima do editor com um rótulo explícito de visibilidade. O rascunho ativo permanece no Textarea nativo. Ao salvar, uma captura é adicionada e o campo é limpo, impedindo que edições posteriores alterem silenciosamente uma nota já salva.

Funções e paleta do tema do sistema de design Zendesk Garden

Entenda os aliases antes de copiar cores

O DEFAULT_THEME do Garden 9 mapeia funções semânticas para famílias de matizes e valores numerados da paleta. Uma função como background.primaryEmphasis não é um valor hexadecimal literal. A tabela de referência mantém esses aliases para que um tema personalizado possa alterar o matiz primário sem deixar trechos azuis codificados diretamente nos controles nativos.

Mantenha as áreas criadas compatíveis com o provider

ThemeProvider fornece a estilização dos componentes nativos. Este exemplo usa DEFAULT_THEME e um espaço de trabalho personalizado claro correspondente; não adiciona uma alternância fictícia de modo escuro que só altera o fundo ao redor. Se adicionar suporte a esquemas de cores, adapte as cores personalizadas das mensagens e da barra lateral junto com as do provider.

Tipografia e densidade do sistema de design Zendesk Garden

Mantenha legível o texto de trabalho de 14px

O tema padrão oferece uma função média de 14px e uma altura de linha média de 20px, além de funções distintas de 12px para informações auxiliares e de 18px para títulos. O exemplo usa um título de ticket de 26px e metadados contextuais menores. A mensagem original do cliente e as notas salvas permanecem no texto normal do corpo, em vez de serem reduzidas a rótulos.

Permita que respostas longas quebrem linhas naturalmente

O texto salvo preserva as quebras de linha e ajusta palavras longas à largura disponível. Assim, uma tela estreita de celular mantém a nota inteira visível sem exigir rolagem horizontal. O editor cresce verticalmente por meio do textarea, sem transformar todo o histórico de mensagens em uma área com rolagem interna.

Composição de campos e botões do sistema de design Zendesk Garden

Associe o rótulo, a orientação e o erro

O Field nativo agrupa Label, Hint, Textarea e Message condicional. A propriedade de validação altera a aparência do textarea quando a regra de comprimento mínimo definida pela aplicação não é atendida. Isso segue a composição do componente, em vez de aplicar a cor de erro a um parágrafo não relacionado fora do campo.

Use um controle próprio para a visibilidade

Estado do rascunho e histórico local do sistema de design Zendesk Garden

Valide antes de adicionar uma mensagem

A aplicação exige pelo menos doze caracteres após remover os espaços nas extremidades. Se o envio falhar, o rascunho permanece intacto, uma mensagem aparece no campo e o foco volta para o textarea. A edição limpa o erro antigo; um envio posterior verifica novamente o texto atual. Essa regra é um comportamento da aplicação, não um padrão não documentado do Garden.

Diferencie visualmente as notas internas

As entradas internas têm um fundo acolhedor e o rótulo escrito Rascunho de nota interna. As entradas públicas usam a superfície padrão. Ambas indicam explicitamente que não foram enviadas. Essa distinção demonstra o contexto de visibilidade sem imitar uma conversa ativa do Zendesk nem sugerir que outra pessoa recebeu algo.

Áreas de trabalho responsivas do sistema de design Zendesk Garden

Coloque o contexto abaixo da tarefa principal

No ponto de quebra da aplicação, o contexto do ticket passa para baixo da conversa e do editor. A ordem do documento subjacente permanece a mesma. Em um celular, o controle de visibilidade ocupa toda a largura disponível e a linha de ações quebra para que os rótulos dos botões não fiquem comprimidos.

Use raios moderados e divisórias finas

Os controles nativos usam a escala de raios de 2px, 4px e 8px. Os painéis da mensagem original usam cantos de 4px e bordas sutis. O destaque visual mais forte deve ficar na ação ativa e no estado de validação, não em sombras ao redor de cada mensagem.

Validação e recuperação pelo teclado do sistema de design Zendesk Garden

Teste todo o fluxo de criação de rascunho

Um teste útil começa com um envio inválido e, em seguida, verifica se digitar, alterar a visibilidade, salvar e limpar mantêm a interface compreensível. O código usa uma ref React para restaurar o foco após um erro ou uma ação de limpeza. A contagem de resultados é anunciada em uma região de status.

  1. Envie um rascunho curto e verifique o erro no campo.
  2. Selecione Nota interna, escreva uma nota útil e salve.
  3. Limpe um rascunho posterior e confirme que a captura local salva permanece.

Mantenha uma ordem de leitura estável

A solicitação vem antes do rascunho, e as novas capturas locais salvas permanecem em ordem cronológica. Os botões nativos apresentam suas ações como texto. Não há atalhos de teclado nem envio automático ocultos no editor, e a escolha de visibilidade permanece em um select com rótulo.

Integração React do sistema de design Zendesk Garden

Instale versões compatíveis dos pacotes

O exemplo fixa a tematização, os botões e os formulários na versão 9.16.1 e usa React 18 com styled-components. Misturar versões mais antigas dos pacotes Garden pode gerar expectativas incompatíveis em relação ao tema. A entrada JSX completa inclui o provider, a composição do campo e o estado local, enquanto o arquivo CSS contém somente o layout definido aqui.

  • @zendeskgarden/react-theming 9.16.1
  • @zendeskgarden/react-buttons 9.16.1
  • @zendeskgarden/react-forms 9.16.1

Estenda somente a camada de serviço ausente

Exemplos de componentes do sistema de design Zendesk Garden

main.jsx — exemplo funcional completo

Escreva uma resposta com o contexto do cliente à vista. O código abaixo é a entrada React completa, incluindo todos os estados e a validação.

jsx
import React, { useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import { ThemeProvider, DEFAULT_THEME } from "@zendeskgarden/react-theming";
import { Button } from "@zendeskgarden/react-buttons";
import {
  Field,
  Label,
  Textarea,
  Hint,
  Message,
  Select,
} from "@zendeskgarden/react-forms";
import "./garden.css";
function App() {
  const [mode, setMode] = useState("public"),
    [text, setText] = useState(""),
    [error, setError] = useState(false),
    [items, setItems] = useState([]);
  const ref = useRef();
  function submit(e) {
    e.preventDefault();
    if (text.trim().length < 12) {
      setError(true);
      ref.current.focus();
      return;
    }
    setItems([...items, { mode, text: text.trim() }]);
    setText("");
    setError(false);
  }
  return (
    <ThemeProvider theme={DEFAULT_THEME}>
      <main className="garden-workspace">
        <header>
          <span>SUPPORT WORKSPACE / FICTIONAL TICKET</span>
          <h1>Help with an invoice address</h1>
          <p>Ticket #1028 · Nadia Walker · Email channel</p>
        </header>
        <div className="garden-grid">
          <section>
            <div className="message customer">
              <strong>Nadia Walker</strong>
              <small>Customer · example message</small>
              <p>
                Could you update the company address on our next invoice? The
                billing contact has changed.
              </p>
            </div>
            {items.map((i, n) => (
              <article className={"message " + i.mode} key={n}>
                <strong>
                  {i.mode === "public"
                    ? "Public reply draft"
                    : "Internal note draft"}
                </strong>
                <small>Saved locally · not sent</small>
                <p>{i.text}</p>
              </article>
            ))}
            <form onSubmit={submit} noValidate>
              <div className="composer-head">
                <h2>Compose a draft</h2>
                <Field>
                  <Label>Visibility</Label>
                  <Select
                    value={mode}
                    onChange={(e) => setMode(e.target.value)}
                  >
                    <option value="public">Public reply</option>
                    <option value="internal">Internal note</option>
                  </Select>
                </Field>
              </div>
              <Field>
                <Label>
                  {mode === "public" ? "Reply text" : "Internal note"}
                </Label>
                <Hint>
                  {mode === "public"
                    ? "Prepared for the customer; this demo will not send it."
                    : "Internal context for the support team; saved only in this page."}
                </Hint>
                <Textarea
                  ref={ref}
                  value={text}
                  rows={5}
                  validation={error ? "error" : undefined}
                  onChange={(e) => {
                    setText(e.target.value);
                    setError(false);
                  }}
                />
                {error && (
                  <Message validation="error">
                    Write at least 12 characters.
                  </Message>
                )}
              </Field>
              <div className="composer-actions">
                <span>{text.length} characters</span>
                <Button
                  type="button"
                  onClick={() => {
                    setText("");
                    setError(false);
                    ref.current.focus();
                  }}
                >
                  Clear draft
                </Button>
                <Button isPrimary type="submit">
                  Save local draft
                </Button>
              </div>
            </form>
            <p role="status">
              {items.length > 0
                ? `${items.length} draft${items.length === 1 ? "" : "s"} saved locally. No message sent.`
                : ""}
            </p>
          </section>
          <aside>
            <h2>Ticket context</h2>
            <dl>
              <dt>Requester</dt>
              <dd>Nadia Walker</dd>
              <dt>Organization</dt>
              <dd>Northstar Studio</dd>
              <dt>Priority</dt>
              <dd>Normal</dd>
              <dt>Topic</dt>
              <dd>Billing details</dd>
            </dl>
            <div className="context-note">
              <h3>Before replying</h3>
              <ul>
                <li>Confirm the billing contact.</li>
                <li>Keep invoice identifiers out of public examples.</li>
                <li>State whether the change affects future invoices.</li>
              </ul>
            </div>
          </aside>
        </div>
        <footer>
          Native Garden 9.16.1 React components. Original local drafting
          workflow; no Zendesk connection.
        </footer>
      </main>
    </ThemeProvider>
  );
}
createRoot(document.getElementById("root")).render(<App />);

Referência de código

  • Crie um projeto Vite React, mantenha <div id="root"></div> e carregue este arquivo como src/main.jsx.

garden.css — composição responsiva original

Layout da aplicação organizado em torno dos componentes nativos.

css
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  font:
    14px/1.5 system-ui,
    sans-serif;
  color: #293239;
  background: #f8f9f9;
}
.garden-workspace header {
  padding: 24px 32px;
  background: white;
  border-bottom: 1px solid #d8dcde;
}
.garden-workspace header span {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: #5c6970;
}
.garden-workspace h1 {
  font-size: 26px;
  line-height: 1.3;
  margin: 8px 0;
}
.garden-workspace header p {
  color: #5c6970;
  margin: 0;
}
.garden-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 24px;
  padding: 24px 32px;
}
.message {
  padding: 20px;
  background: white;
  border: 1px solid #d8dcde;
  border-radius: 4px;
  margin-bottom: 16px;
}
.message p {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 12px 0 0;
}
.message small {
  display: block;
  color: #5c6970;
  margin-top: 4px;
}
.message.internal {
  background: #fff8ed;
  border-color: #e7ce99;
}
form {
  padding: 24px;
  background: white;
  border: 1px solid #d8dcde;
  border-radius: 4px;
}
.composer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 24px;
}
.composer-head > div {
  max-width: 220px;
}
.garden-workspace h2 {
  font-size: 18px;
  margin: 0 0 12px;
}
.composer-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 20px;
}
.composer-actions span {
  font-size: 12px;
  color: #5c6970;
  margin-right: auto;
}
.garden-grid aside {
  background: white;
  border: 1px solid #d8dcde;
  border-radius: 4px;
  padding: 20px;
  align-self: start;
}
dl {
  margin: 0;
}
dt {
  font-size: 12px;
  color: #5c6970;
  margin-top: 16px;
}
dd {
  margin: 4px 0 0;
  font-weight: 600;
}
.context-note {
  margin-top: 24px;
  border-top: 1px solid #e8eaec;
  padding-top: 16px;
}
.context-note h3 {
  font-size: 14px;
}
.context-note ul {
  padding-left: 18px;
  font-size: 12px;
}
.context-note li {
  margin: 8px 0;
}
footer {
  padding: 16px 32px;
  font-size: 12px;
  color: #5c6970;
  border-top: 1px solid #d8dcde;
  background: white;
}
@media (max-width: 850px) {
  .garden-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 550px) {
  .garden-grid {
    padding: 16px;
  }
  .garden-workspace header {
    padding: 20px 16px;
  }
  .composer-head {
    display: block;
  }
  .composer-head > div {
    max-width: none;
  }
  .composer-actions {
    flex-wrap: wrap;
    justify-content: flex-start;
  }
  .composer-actions span {
    width: 100%;
  }
  form {
    padding: 16px;
  }
}

Referência de código

  • Salve junto de main.jsx. Estas regras de composição personalizadas são distintas da referência de tokens da biblioteca.
04

Configuração do agente do sistema de design Zendesk Garden

Ponto de partida para implementação

O exemplo nativo com versões fixadas foi empacotado e verificado localmente no navegador. O exemplo usa apenas o estado local da aplicação.

sh
npm create vite@latest garden-draft -- --template react
cd garden-draft
npm install
npm install [email protected] [email protected] styled-components @zendeskgarden/[email protected] @zendeskgarden/[email protected] @zendeskgarden/[email protected]
# Replace src/main.jsx and add src/garden.css.
npm run dev

Um prompt para seu projeto

Prompt para agente de IA
Crie um editor de respostas de suporte Garden com a composição nativa de Field/Label/Hint/Textarea/Message. Mantenha a visibilidade em cada captura de rascunho salva, valide antes de adicionar, preserve o contexto do cliente e diferencie salvar localmente de enviar. Use as funções exatas do tema e o código-fonte completo disponíveis aqui.
05

Fontes e escopo do sistema de design Zendesk Garden

Guia da aplicação OpenDesign. Os componentes nativos do Garden renderizam o exemplo; o conteúdo fictício do ticket e os rascunhos locais não se conectam ao Zendesk nem enviam mensagens.