Программное обеспечение для поддержки клиентов · Новый ресурс

Дизайн-система Zendesk Garden.

Руководство по Garden для работы с запросами в службу поддержки: реальные псевдонимы тем, шкалы типографики и радиусов, полноценный редактор ответа, локальные черновики с учётом видимости и восстановление полей.

Руководство OpenDesign8 глав42 справочные записиАвторское руководство по приложению
01

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

Измените видимость ответа, проверьте короткий черновик, сохраните локальный снимок и очистите поле для следующего черновика.

Подготовьте ответ, не теряя из виду контекст клиентаОткрыть полный пример
Нативные ThemeProvider, Buttons и Forms библиотеки Garden 9.16.1 React; оригинальный локальный процесс подготовки черновиков. · Справочник по реализации
02

Справочник по дизайн-системе Zendesk Garden

Нативные ThemeProvider, Buttons и Forms библиотеки Garden 9.16.1 React; оригинальный локальный процесс подготовки черновиков.

Радиус скругления

Источник
Название / правилоЗначение / конфигурацияПрименение
borderRadii.sm2pxПодбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула.
borderRadii.md4pxПодбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула.
borderRadii.lg8pxПодбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула.

Адаптивные контрольные точки

Источник
Название / правилоЗначение / конфигурацияПрименение
breakpoints.xs0pxКонтрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге.
breakpoints.sm576pxКонтрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге.
breakpoints.md768pxКонтрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге.
breakpoints.lg992pxКонтрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге.
breakpoints.xl1200pxКонтрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге.

Размеры текста

Источник
Название / правилоЗначение / конфигурацияПрименение
fontSizes.xs10pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.sm12pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.md14pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.lg18pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.xl22pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.xxl26pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.
fontSizes.xxxl36pxСохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков.

Высота строки

Источник
Название / правилоЗначение / конфигурацияПрименение
lineHeights.sm16pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.
lineHeights.md20pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.
lineHeights.lg24pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.
lineHeights.xl28pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.
lineHeights.xxl32pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.
lineHeights.xxxl44pxИспользуйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта.

Шаги отступов

Источник
Название / правилоЗначение / конфигурацияПрименение
space.base4Значения отступов темы для предсказуемого ритма.
space.xxs4pxЗначения отступов темы для предсказуемого ритма.
space.xs8pxЗначения отступов темы для предсказуемого ритма.
space.sm12pxЗначения отступов темы для предсказуемого ритма.
space.md20pxЗначения отступов темы для предсказуемого ритма.
space.lg32pxЗначения отступов темы для предсказуемого ритма.
space.xl40pxЗначения отступов темы для предсказуемого ритма.
space.xxl48pxЗначения отступов темы для предсказуемого ритма.

Сопоставление семантических ролей для светлой темы

Источник
Название / правилоЗначение / конфигурацияПрименение
colors.variables.light.background.defaultpalette.whiteПсевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.background.subtleneutralHue.100Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.background.dangerdangerHue.100Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.background.primaryEmphasisprimaryHue.700Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.foreground.defaultneutralHue.900Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.foreground.subtleneutralHue.700Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.foreground.onEmphasispalette.whiteПсевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.foreground.primaryprimaryHue.700Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.foreground.dangerdangerHue.700Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.border.defaultneutralHue.300Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.border.subtleneutralHue.200Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.border.dangerdangerHue.300Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
colors.variables.light.border.primaryEmphasisprimaryHue.700Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS.
03

Полное руководство по дизайн-системе Zendesk Garden

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

DESIGN-zendesk-garden.md

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

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

Структура рабочего пространства поддержки в дизайн-системе Zendesk Garden

Сохраняйте запрос клиента перед глазами

Чтобы ответ поддержки был не только хорошо сформулированным, но и уместным, автору нужен контекст. В примере запрос клиента расположен над черновиком, а рядом указаны автор обращения, организация и тема. Интерфейс достаточно компактный, чтобы можно было сопоставить новый текст с исходным вопросом, не переключаясь между экранами.

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

Отделите историю от активного черновика

Сохранённые локальные записи отображаются над редактором с явной пометкой о видимости. Активный черновик остаётся во встроенном Textarea. Сохранение добавляет снимок и очищает это поле, поэтому последующие правки не могут незаметно изменить ранее сохранённую заметку.

Роли темы и палитра дизайн-системы Zendesk Garden

Разберитесь в псевдонимах, прежде чем копировать цвета

Garden 9 DEFAULT_THEME сопоставляет семантические роли с семействами оттенков и пронумерованными значениями палитры. Роль вроде background.primaryEmphasis — это не буквальное шестнадцатеричное значение. В справочной таблице сохранены эти псевдонимы: благодаря им можно изменить основной оттенок пользовательской темы, не оставляя в стандартных элементах управления жёстко заданные синие фрагменты.

Сохраняйте совместимость собственных областей с провайдером

ThemeProvider задаёт оформление встроенных компонентов. В этом примере используются DEFAULT_THEME и соответствующее ему светлое пользовательское рабочее пространство; фиктивный переключатель тёмного режима, который меняет только окружающий фон, не добавляется. Если вы добавляете поддержку цветовых схем, адаптируйте цвета пользовательских сообщений и боковой панели вместе с провайдером.

Типографика и плотность дизайн-системы Zendesk Garden

Сохраняйте читаемость рабочего текста размером 14px

В стандартной теме предусмотрена роль среднего начертания размером 14px с высотой строки 20px, а также отдельные роли для вспомогательного текста размером 12px и заголовков размером 18px. В примере заголовок обращения имеет размер 26px, а метаданные контекста — меньший. Исходное сообщение клиента и сохранённые заметки остаются обычным текстом, а не сжатыми подписями.

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

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

Композиция полей и кнопок в дизайн-системе Zendesk Garden

Свяжите подпись, подсказку и ошибку

Встроенный Field объединяет Label, Hint, Textarea и условный Message. Свойство validation меняет оформление textarea, когда текст не соответствует заданному в приложении минимальному ограничению по длине. Так используется композиция компонентов, а цвет ошибки не применяется к постороннему абзацу за пределами поля.

Предусмотрите отдельный элемент управления видимостью

Состояние черновика и локальная история в дизайн-системе Zendesk Garden

Проверяйте текст до добавления сообщения

Приложение требует не менее двенадцати символов после удаления пробелов по краям. Если проверка не пройдена, черновик остаётся в поле, появляется сообщение об ошибке, а фокус перемещается в textarea. При редактировании устаревшая ошибка сбрасывается; при следующей отправке текст проверяется заново. Это поведение приложения, а не незадокументированное значение по умолчанию в Garden.

Визуально отделяйте внутренние заметки

Для внутренних записей используется тёплый фон и подпись «Черновик внутренней заметки». Для публичных записей используется обычная поверхность. Для обоих режимов явно указано, что сообщение не отправлено. Это помогает показать контекст видимости, не имитируя рабочий диалог Zendesk и не создавая впечатления, что сообщение уже получил другой человек.

Адаптивные рабочие области дизайн-системы Zendesk Garden

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

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

Используйте умеренные радиусы и тонкие разделители

Во встроенных элементах управления используются радиусы 2px, 4px и 8px. В исходных панелях сообщений применены скругление 4px и ненавязчивые границы. Более сильное визуальное выделение нужно активному действию и состоянию проверки, а не теням вокруг каждого сообщения.

Проверка и восстановление клавиатурной навигации в дизайн-системе Zendesk Garden

Проверьте весь сценарий работы с черновиком

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

  1. Отправьте короткий черновик и проверьте сообщение об ошибке поля.
  2. Выберите «Внутренняя заметка», введите полезную заметку и сохраните её.
  3. Очистите следующий черновик и убедитесь, что сохранённый локальный снимок остался.

Сохраняйте стабильный порядок чтения

Запрос размещается перед черновиком, а новые локальные снимки сохраняются в хронологическом порядке. Действия встроенных кнопок обозначены текстом. В редакторе нет скрытых сочетаний клавиш или автоматической отправки, а выбор видимости остаётся подписанным элементом select.

Интеграция дизайн-системы Zendesk Garden React

Устанавливайте совместимые версии пакетов

Для темизации, кнопок и форм в примере зафиксирована версия 9.16.1; также используются React 18 и styled-components. Смешивание более старых поколений пакетов Garden может привести к несовпадению ожиданий относительно темы. Полный файл JSX включает провайдер, композицию поля и локальное состояние, а файл CSS содержит только заданную вручную компоновку.

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

Добавляйте только недостающий слой сервисной логики

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

main.jsx — полный рабочий образец

Подготовьте ответ, не теряя из виду контекст клиента. Ниже приведён полный исходный код записи React, включая всё состояние и проверки.

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

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

  • Создайте проект React на Vite, сохраните <div id="root"></div> и загрузите этот код как src/main.jsx.

garden.css — оригинальная адаптивная компоновка

Слой компоновки приложения поверх нативных компонентов.

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

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

  • Сохраните рядом с main.jsx. Эти собственные правила композиции отделены от справочника токенов библиотеки.
04

Настройка агента дизайн-системы Zendesk Garden

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

Пример с закреплёнными версиями нативных компонентов собран и проверен в браузере локально. В образце используется только локальное состояние приложения.

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

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

Промпт для AI-агента
Создайте интерфейс для составления обращений в поддержку Garden, используя нативную композицию Field/Label/Hint/Textarea/Message. Сохраняйте видимость в каждом снимке черновика, проверяйте данные перед добавлением, сохраняйте контекст клиента и различайте локальное сохранение и отправку. Здесь указаны точные роли темы и полный исходный код.
05

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

OpenDesign руководство по приложению. Нативные компоненты Garden отображают образец; содержание вымышленных обращений и локальные черновики не связаны с Zendesk и не отправляют сообщения.