Software de atención al cliente · Nuevo recurso

Sistema de diseño Zendesk Garden.

Una guía de Garden para tareas de soporte, con alias de tema reales, escalas tipográficas y de radio, un compositor de respuestas completo, borradores locales que respetan la visibilidad y recuperación de campos.

Guía de OpenDesign8 capítulos42 entradas de referenciaGuía de aplicación original
01

Vista previa de la interfaz del sistema de diseño Zendesk Garden

Cambia la visibilidad de las respuestas, valida un borrador breve, guarda una instantánea local y prepara el siguiente borrador.

Redacta una respuesta con el contexto del cliente a la vistaAbrir ejemplo completo
ThemeProvider, Buttons y Forms nativos de Garden 9.16.1 React; flujo de redacción local original. · Referencia de implementación
02

Referencia de diseño del sistema de diseño Zendesk Garden

ThemeProvider, Buttons y Forms nativos de Garden 9.16.1 React; flujo de redacción local original.

Control del radio

Fuente
Nombre / ReglaValor / ConfiguraciónUso
borderRadii.sm2pxElige la forma según la función del componente; el radio medio predeterminado no es una píldora.
borderRadii.md4pxElige la forma según la función del componente; el radio medio predeterminado no es una píldora.
borderRadii.lg8pxElige la forma según la función del componente; el radio medio predeterminado no es una píldora.

Puntos de interrupción adaptable

Fuente
Nombre / ReglaValor / ConfiguraciónUso
breakpoints.xs0pxPuntos de interrupción del tema; no implican que la aplicación cambie cada región en cada paso.
breakpoints.sm576pxPuntos de interrupción del tema; no implican que la aplicación cambie cada región en cada paso.
breakpoints.md768pxPuntos de interrupción del tema; no implican que la aplicación cambie cada región en cada paso.
breakpoints.lg992pxPuntos de interrupción del tema; no implican que la aplicación cambie cada región en cada paso.
breakpoints.xl1200pxPuntos de interrupción del tema; no implican que la aplicación cambie cada región en cada paso.

Tamaños de texto

Fuente
Nombre / ReglaValor / ConfiguraciónUso
fontSizes.xs10pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.sm12pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.md14pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.lg18pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.xl22pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.xxl26pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.
fontSizes.xxxl36pxMantén diferenciados los roles de texto del cuerpo, etiquetas, metadatos y encabezados.

Alturas de línea

Fuente
Nombre / ReglaValor / ConfiguraciónUso
lineHeights.sm16pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.
lineHeights.md20pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.
lineHeights.lg24pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.
lineHeights.xl28pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.
lineHeights.xxl32pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.
lineHeights.xxxl44pxÚsalo junto con el rol de texto; no deduzcas todas las alturas de línea a partir del tamaño de fuente.

Intervalos de espaciado

Fuente
Nombre / ReglaValor / ConfiguraciónUso
space.base4Valores de espaciado del tema para mantener un ritmo predecible.
space.xxs4pxValores de espaciado del tema para mantener un ritmo predecible.
space.xs8pxValores de espaciado del tema para mantener un ritmo predecible.
space.sm12pxValores de espaciado del tema para mantener un ritmo predecible.
space.md20pxValores de espaciado del tema para mantener un ritmo predecible.
space.lg32pxValores de espaciado del tema para mantener un ritmo predecible.
space.xl40pxValores de espaciado del tema para mantener un ritmo predecible.
space.xxl48pxValores de espaciado del tema para mantener un ritmo predecible.

Asignación de roles semánticos para el tema claro

Fuente
Nombre / ReglaValor / ConfiguraciónUso
colors.variables.light.background.defaultpalette.whiteAlias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.background.subtleneutralHue.100Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.background.dangerdangerHue.100Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.background.primaryEmphasisprimaryHue.700Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.foreground.defaultneutralHue.900Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.foreground.subtleneutralHue.700Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.foreground.onEmphasispalette.whiteAlias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.foreground.primaryprimaryHue.700Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.foreground.dangerdangerHue.700Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.border.defaultneutralHue.300Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.border.subtleneutralHue.200Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.border.dangerdangerHue.300Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
colors.variables.light.border.primaryEmphasisprimaryHue.700Alias de rol del tema; resuélvelo mediante el tono y la paleta seleccionados, en lugar de tratar el alias como un color CSS.
03

Guía completa del sistema de diseño Zendesk Garden

Una guía práctica para elegir, aplicar y revisar este sistema en una interfaz real.

DESIGN-zendesk-garden.md

Orientación completa, un punto de partida para la implementación y enlaces al código fuente.

Descargar la guía

Estructura del espacio de trabajo del sistema de diseño Zendesk Garden

Mantén visible la solicitud del cliente

Un compositor de soporte necesita suficiente contexto para evitar respuestas pulidas, pero irrelevantes. El ejemplo muestra la solicitud del cliente encima del borrador, junto con la persona solicitante, la organización y el tema. La interfaz tiene la densidad justa para comparar el texto nuevo con la pregunta original sin cambiar de pantalla.

De esta guía de OpenDesign

Separa el historial del borrador activo

Las entradas locales guardadas aparecen encima del compositor con una etiqueta de visibilidad explícita. El borrador activo permanece en el componente Textarea nativo. Al guardar, se añade una instantánea y se borra ese campo, de modo que las ediciones posteriores no puedan reescribir silenciosamente una nota guardada anteriormente.

Zendesk Garden Roles de tema y paleta del sistema de diseño

Consulta los alias antes de copiar colores

Garden 9 DEFAULT_THEME asigna roles semánticos a familias de tonos y valores de paleta numerados. Un rol como background.primaryEmphasis no es un valor hexadecimal literal. La tabla de referencia conserva esos alias para que un tema personalizado pueda cambiar el tono principal sin dejar fragmentos azules codificados directamente en los controles nativos.

Mantén la compatibilidad de las áreas personalizadas con el proveedor

ThemeProvider proporciona estilos para los componentes nativos. Este ejemplo usa DEFAULT_THEME y un espacio de trabajo personalizado claro a juego; no añade un falso control de modo oscuro que solo cambia el fondo circundante. Si añades compatibilidad con color-scheme, adapta también los colores personalizados de los mensajes y la barra lateral junto con los del proveedor.

Zendesk Garden Tipografía y densidad del sistema de diseño

Mantén legible el texto de trabajo de 14px

El tema predeterminado ofrece un estilo mediano de 14px y una altura de línea mediana de 20px, además de estilos independientes de 12px para texto auxiliar y de 18px para encabezados. El ejemplo usa un título de ticket de 26px y metadatos contextuales más pequeños. El mensaje original del cliente y las notas guardadas se mantienen en texto normal, no se comprimen como etiquetas.

Permite que las respuestas largas se ajusten de forma natural

El texto guardado conserva los saltos de línea y ajusta las palabras largas. Así, una pantalla móvil estrecha muestra la nota completa en lugar de forzar el desplazamiento horizontal. El compositor crece verticalmente mediante su área de texto, en vez de convertir todo el historial de mensajes en un cuadro con desplazamiento interno.

Zendesk Garden Composición de campos y botones del sistema de diseño

Mantén vinculados la etiqueta, la indicación y el error

El componente Field nativo agrupa Label, Hint, Textarea y Message condicional. La propiedad de validación modifica la apariencia del área de texto cuando no se cumple la regla definida por la aplicación sobre la longitud mínima. Así se respeta la composición del componente, en vez de aplicar el color de error a un párrafo ajeno al campo.

Asigna un control propio a la visibilidad

Zendesk Garden Estado del borrador e historial local del sistema de diseño

Valida antes de añadir un mensaje

La aplicación exige al menos doce caracteres después de eliminar los espacios iniciales y finales. Si el envío no supera la validación, el borrador se conserva, aparece un mensaje en el campo y el foco vuelve al área de texto. Al editar, se borra el error obsoleto; un envío posterior vuelve a comprobar el texto actual. Esta regla es comportamiento de la aplicación, no un valor predeterminado de Garden documentado.

Distingue visualmente las notas internas

Las entradas internas tienen un fondo cálido personalizado y la etiqueta Nota interna (borrador) escrita. Las entradas públicas usan la superficie normal. Ambas indican explícitamente que no se han enviado. La distinción muestra el contexto de visibilidad sin imitar una conversación activa de Zendesk ni dar a entender que otra persona ha recibido algo.

Zendesk Garden Áreas de trabajo adaptables del sistema de diseño

Coloca el contexto debajo de la tarea principal

En el punto de quiebre de la aplicación, el contexto del ticket pasa debajo de la conversación y el compositor. El orden del documento subyacente no cambia. En un teléfono, el control de visibilidad ocupa todo el ancho disponible y la fila de acciones se ajusta para que las etiquetas de los botones no queden comprimidas.

Usa radios moderados y divisores finos

Los controles nativos usan la escala de radios de 2px, 4px y 8px. Los paneles del mensaje original tienen esquinas de 4px y bordes sutiles. La mayor prominencia visual corresponde a la acción activa y al estado de validación, no a las sombras alrededor de cada mensaje.

Zendesk Garden Validación y recuperación del teclado del sistema de diseño

Prueba el flujo completo del borrador

Una comprobación útil empieza con un envío no válido y luego verifica que escribir, cambiar la visibilidad, guardar y borrar mantengan una interfaz comprensible. El código usa una referencia React para devolver el foco tras un error o una acción de borrado. El recuento de resultados se anuncia en una región de estado.

  1. Envía un borrador breve y comprueba el error del campo.
  2. Elige Nota interna, escribe una nota útil y guárdala.
  3. Borra un borrador posterior y confirma que la instantánea local guardada se conserva.

Mantén un orden de lectura estable

La solicitud precede al borrador, y las instantáneas locales recién guardadas se mantienen en orden cronológico. Los botones nativos muestran sus acciones como texto. El compositor no oculta atajos de teclado ni envíos automáticos, y la opción de visibilidad sigue siendo un selector con etiqueta.

Zendesk Garden Integración del sistema de diseño React

Instala versiones compatibles de los paquetes

El ejemplo fija los paquetes de tematización, botones y formularios en la versión 9.16.1, y usa React 18 con styled-components. Combinar versiones anteriores de los paquetes Garden puede generar expectativas incompatibles sobre el tema. La entrada JSX completa incluye el proveedor, la composición del campo y el estado local, mientras que el archivo CSS contiene únicamente el diseño de la aplicación.

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

Amplía solo la capa de servicio que falta

Zendesk Garden Ejemplos de componentes del sistema de diseño

main.jsx — ejemplo completo y funcional

Redacta una respuesta sin perder de vista el contexto del cliente. El código siguiente es la entrada React completa, con todo el estado y la validación.

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

Referencia de código

  • Crea un proyecto Vite React, conserva <div id="root"></div> y cárgalo como src/main.jsx.

garden.css — composición adaptable original

Diseño de la aplicación con capas alrededor de los 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;
  }
}

Referencia de código

  • Guárdalo junto a main.jsx. Estas reglas de composición personalizadas se distinguen de la referencia de tokens de la biblioteca.
04

Zendesk Garden Configuración del agente del sistema de diseño

Punto de partida para la implementación

El ejemplo nativo fijado se empaquetó y se comprobó localmente en el navegador. El ejemplo utiliza únicamente el estado local de la aplicación.

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

Una instrucción para tu proyecto

Instrucción para el agente
Crea un compositor de respuestas de Garden con la composición nativa Field/Label/Hint/Textarea/Message. Conserva la visibilidad en cada instantánea de borrador guardada, valida antes de añadir, preserva el contexto del cliente y distingue entre guardar localmente y enviar. Usa los roles de tema exactos y consulta aquí el código fuente completo.
05

Zendesk Garden Fuentes y alcance del sistema de diseño

OpenDesign guía de aplicación. Los componentes nativos de Garden representan el espécimen; el contenido ficticio de los tickets y los borradores locales no se conectan a Zendesk ni envían mensajes.