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

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

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

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

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

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

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| borderRadii.sm | 2px | Подбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула. |
| borderRadii.md | 4px | Подбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула. |
| borderRadii.lg | 8px | Подбирайте форму с учётом роли компонента; стандартное среднее скругление — не капсула. |
### Адаптивные контрольные точки

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| breakpoints.xs | 0px | Контрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге. |
| breakpoints.sm | 576px | Контрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге. |
| breakpoints.md | 768px | Контрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге. |
| breakpoints.lg | 992px | Контрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге. |
| breakpoints.xl | 1200px | Контрольные точки темы, а не обещание, что приложение перестраивает каждую область на каждом шаге. |
### Размеры текста

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| fontSizes.xs | 10px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.sm | 12px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.md | 14px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.lg | 18px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.xl | 22px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.xxl | 26px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
| fontSizes.xxxl | 36px | Сохраняйте отдельные роли для основного текста, подписей, метаданных и заголовков. |
### Высота строки

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| lineHeights.sm | 16px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
| lineHeights.md | 20px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
| lineHeights.lg | 24px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
| lineHeights.xl | 28px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
| lineHeights.xxl | 32px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
| lineHeights.xxxl | 44px | Используйте вместе с ролью текста; не рассчитывайте всю высоту строки только на основе размера шрифта. |
### Шаги отступов

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| space.base | 4 | Значения отступов темы для предсказуемого ритма. |
| space.xxs | 4px | Значения отступов темы для предсказуемого ритма. |
| space.xs | 8px | Значения отступов темы для предсказуемого ритма. |
| space.sm | 12px | Значения отступов темы для предсказуемого ритма. |
| space.md | 20px | Значения отступов темы для предсказуемого ритма. |
| space.lg | 32px | Значения отступов темы для предсказуемого ритма. |
| space.xl | 40px | Значения отступов темы для предсказуемого ритма. |
| space.xxl | 48px | Значения отступов темы для предсказуемого ритма. |
### Сопоставление семантических ролей для светлой темы

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| colors.variables.light.background.default | palette.white | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.background.subtle | neutralHue.100 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.background.danger | dangerHue.100 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.background.primaryEmphasis | primaryHue.700 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.foreground.default | neutralHue.900 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.foreground.subtle | neutralHue.700 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.foreground.onEmphasis | palette.white | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.foreground.primary | primaryHue.700 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.foreground.danger | dangerHue.700 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.border.default | neutralHue.300 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.border.subtle | neutralHue.200 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.border.danger | dangerHue.300 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
| colors.variables.light.border.primaryEmphasis | primaryHue.700 | Псевдоним роли темы; разрешайте его через выбранный оттенок и палитру, а не считайте цветом CSS. |
## Полное руководство по дизайн-системе Zendesk Garden

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

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

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

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

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

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

Сохранённые локальные записи отображаются над редактором с явной пометкой о видимости. Активный черновик остаётся во встроенном 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, когда текст не соответствует заданному в приложении минимальному ограничению по длине. Так используется композиция компонентов, а цвет ошибки не применяется к постороннему абзацу за пределами поля.

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

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

## Состояние черновика и локальная история в дизайн-системе 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

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

Чтобы это стало полноценным инструментом поддержки, добавьте авторизованные данные обращений, проверки разрешений и проверенную отправку/сохранение черновика API с обработкой ожидания и ошибок. Сохраняйте семантику локального снимка, пока такие ответы не появятся. Не меняйте текст кнопки на «Отправить» только потому, что проверка формы прошла успешно.

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

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

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

```
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 — оригинальная адаптивная компоновка

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

```
* {
  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. Эти собственные правила композиции отделены от справочника токенов библиотеки.

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

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

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

```
npm create vite@latest garden-draft -- --template react
cd garden-draft
npm install
npm install react@18.3.1 react-dom@18.3.1 styled-components @zendeskgarden/react-theming@9.16.1 @zendeskgarden/react-buttons@9.16.1 @zendeskgarden/react-forms@9.16.1
# Replace src/main.jsx and add src/garden.css.
npm run dev
```

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

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

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

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

- Формы Garden Композиция нативных Field, Label и валидации.

- Кнопки Garden Варианты действий и поддерживаемые размеры.

- Источник темы Псевдонимы DEFAULT_THEME, палитра и шкалы.

## Zendesk Garden Связанные ресурсы дизайн-системы

### Adeo Mozaic

Создайте практичный интерфейс управления количеством с шагом Mozaic в 16px, единообразными элементами управления высотой 48px, реальными SCSS-импортами и классами BEM. Планировщик материалов позволяет проверить ограничения, типизированные ошибки и локальную сводку материалов.

### Adobe Spectrum

Изучите Spectrum v3 от React на примере таблицы творческих ресурсов с возможностью выбора и панели настройки экспорта. Разберитесь в темах Provider и масштабе полей ввода, поддерживаемых стилевых свойствах, коллекциях с ключами и различиях между v3 и более новой реализацией Spectrum 2.

### Alaska Airlines Auro

Изучите тему Alaska от Auro на примере реальных семантических цветовых и типографических токенов, типографики на основе классов и встроенного компонента рейса. Две исходные записи о рейсах демонстрируют локальную фильтрацию и выбор, не изображая инвентарь авиакомпании или бронирование.


- [Справочник по реализации](https://garden.zendesk.com/components/input/)
- [Источник](https://github.com/zendeskgarden/react-components/tree/main/packages/theming)
- [Справочник по коду](https://garden.zendesk.com/components/input/)
- [Формы Garden Композиция нативных Field, Label и валидации.](https://garden.zendesk.com/components/input/)
- [Кнопки Garden Варианты действий и поддерживаемые размеры.](https://garden.zendesk.com/components/button/)
- [Источник темы Псевдонимы DEFAULT_THEME, палитра и шкалы.](https://github.com/zendeskgarden/react-components/tree/main/packages/theming)
