# Дизайн-система Segment Evergreen

## Segment Evergreen Предпросмотр интерфейса дизайн-системы

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

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

Нативные компоненты React Evergreen 7.1.9 и defaultTheme; исходные правила локальной аудитории.

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

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| radii.0 | 0px | Радиус из темы по индексу; выбирайте подходящую роль, а не скругляйте всё сильнее каждый вложенный блок. |
| radii.1 | 4px | Радиус из темы по индексу; выбирайте подходящую роль, а не скругляйте всё сильнее каждый вложенный блок. |
| radii.2 | 8px | Радиус из темы по индексу; выбирайте подходящую роль, а не скругляйте всё сильнее каждый вложенный блок. |
### Размеры текста

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| fontSizes.0 | 10px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.1 | 12px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.2 | 14px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.3 | 16px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.4 | 18px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.5 | 20px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.6 | 24px | Значения font-size по индексу из опубликованной темы по умолчанию. |
| fontSizes.7 | 32px | Значения font-size по индексу из опубликованной темы по умолчанию. |
### Высота строки

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| lineHeights.0 | 16px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.1 | 18px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.2 | 20px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.3 | 24px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.4 | 28px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.5 | 32px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
| lineHeights.6 | 40px | Сочетайте нужную роль текста с соответствующим стилем, а не задавайте каждому абзацу ритм заголовков. |
### Насыщенность шрифта

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| fontWeights.light | 300 | В этой теме Evergreen обозначает полужирное начертание значением 500, а жирное — 600; не подменяйте их без предупреждения стандартными ключевыми словами браузера. |
| fontWeights.normal | 400 | В этой теме Evergreen обозначает полужирное начертание значением 500, а жирное — 600; не подменяйте их без предупреждения стандартными ключевыми словами браузера. |
| fontWeights.semibold | 500 | В этой теме Evergreen обозначает полужирное начертание значением 500, а жирное — 600; не подменяйте их без предупреждения стандартными ключевыми словами браузера. |
| fontWeights.bold | 600 | В этой теме Evergreen обозначает полужирное начертание значением 500, а жирное — 600; не подменяйте их без предупреждения стандартными ключевыми словами браузера. |
### Ссылки на стандартную палитру

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| colors.gray900 | #101840 | Основной тёмный цвет текста. |
| colors.gray700 | #696f8c | Вспомогательный текст. |
| colors.gray400 | #d8dae5 | Обозначенная граница. |
| colors.gray200 | #edeff5 | Ненавязчивый разделитель. |
| colors.gray100 | #F4F5F9 | Нейтральный фон. |
| colors.blue500 | #3366FF | Основной синий цвет. |
| colors.blue600 | #2952CC | Более насыщенный синий цвет для взаимодействия. |
| colors.red500 | #D14343 | Цвет критической ошибки. |
| colors.green500 | #52BD95 | Цвет успешного состояния. |
### Функции сетки и контролируемый ввод API

| Название / правило | Значение / конфигурация | Применение |
| --- | --- | --- |
| majorScale(3) | 24px | Основной шаг — восемь пикселей для интервалов между разделами. |
| minorScale(3) | 12px | Дополнительный шаг — четыре пикселя для небольших интервалов. |
| TagInput.values | controlled array | Допустимые теги определяет приложение. |
| TagInput.onChange | new array; return false to retain input | Проверяйте новые значения перед добавлением. |
| TagInput.separator | comma and new line by default | Разрешите добавлять несколько тегов без собственного парсера. |
## Полное руководство по дизайн-системе Segment Evergreen

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

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

## Структура конструктора аудитории в дизайн-системе Segment Evergreen

### Расположите правила рядом с результатами их применения

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

### Используйте ограниченный набор прозрачных тестовых данных

В примере представлены пять записей с названиями, тарифами и тегами. Страница не имитирует запрос к хранилищу данных клиентов и не оценивает размер реальной аудитории. Нулевое число результатов — полезная часть примера; предусмотрено действие, восстанавливающее полный набор данных.

## Значения и семантика темы дизайн-системы Segment Evergreen

### Изучите фактические значения стандартной темы

В Evergreen 7.1.9, помимо именованных цветов и стилей компонентов, заданы радиусы, размеры шрифта и высота строки с индексами. В таблице приведены именно экспортируемые значения. Особенно важно проверить названия начертаний: полужирное и жирное соответствуют значениям 500 и 600, что отличается от распространённых представлений.

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

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

## Типографика для редактирования правил в дизайн-системе Segment Evergreen

### Задайте понятную иерархию

Стили заголовков помогают отличить название аудитории от заголовков панелей и названий записей в результатах. Вспомогательный текст поясняет ввод тегов и вымышленный характер данных. Бейдж с числом результатов расположен рядом с заголовком списка, а не вместо него: сначала пользователь определяет нужную область, а затем читает число.

### Сохраняйте читаемость метаданных

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

## Основная и дополнительная сетки дизайн-системы Segment Evergreen

### Используйте функции для повторяющихся интервалов

majorScale и minorScale задают шаги в восемь и четыре пикселя. В примере компонента majorScale(3) задаёт интервал 24px между заголовками панелей, а адаптивная композиция оформлена пользовательской таблицей стилей. Разделяйте эти задачи: контрольная точка сетки — решение приложения, а не результат применения функции отступов.

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

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

## Контролируемые теги и сопоставление в дизайн-системе Segment Evergreen

### Нормализуйте значения перед добавлением

Обработчик onChange удаляет пробелы в начале и конце строк, переводит символы в нижний регистр, убирает дубликаты и отклоняет ввод, если в нём больше четырёх разных тегов. Возврат false сохраняет значение поля, если новый тег отклонён. Это правило относится к логике приложения для работы с аудиториями; TagInput обеспечивает контролируемое взаимодействие, но не задаёт бизнес-ограничения.

### Осознанно используйте сопоставление по всем тегам

Запись должна соответствовать выбранному тарифу и каждому обязательному тегу. Если удалить все теги, это ограничение снимается; если выбрать Any, снимается ограничение по тарифу. Текущее число результатов вычисляется по тому же отфильтрованному массиву, который отображается на экране, поэтому число не расходится с видимыми карточками.

## Диалог подтверждения и локальный снимок в дизайн-системе Segment Evergreen

### Проверяйте текущие правила перед сохранением

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

### Сбрасывайте прежний статус успеха при изменении правил

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

## Ввод с клавиатуры и восстановление диалога в дизайн-системе Segment Evergreen

### Проверьте теги, результаты и подтверждение в рамках одного сценария

Теги можно добавлять с помощью описанных клавиш ввода; доступное имя поля задаётся через id. Если превышен лимит тегов, появляется стандартное предупреждение об ошибке. Для диалога используется стандартная логика управления фокусом Dialog, а не самодельное всплывающее окно с неконтролируемым фокусом.

1. Добавьте newsletter к начальному активному тегу и сравните число результатов.

2. Добавьте тег, которому ничего не соответствует, а затем сбросьте правила, чтобы восстановить все пять записей.

3. Просмотрите и сохраните данные локально, затем измените правило и убедитесь, что прежнее сообщение об успехе исчезло.

### Предусмотрите восстановление после пустого результата в рамках текущей задачи

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

## Интеграция дизайн-системы Segment Evergreen React

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

В исходной точке входа подключаются ThemeProvider, defaultTheme и отображаемые компоненты. Состояние хранит правила, ошибки, видимость диалогового окна и локальный сохранённый снимок. Полный JSX и CSS ниже содержат вымышленные тестовые данные, поэтому расчёт результатов можно воспроизвести без внешнего API.

- ThemeProvider использует закреплённую версию defaultTheme.

- Значениями TagInput управляет приложение.

- Dialog проверяет те же правила, что и список результатов.

### Добавьте доступ к данным отдельным уровнем приложения

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

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

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

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

```
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import {
  ThemeProvider,
  defaultTheme,
  Heading,
  Text,
  Paragraph,
  Button,
  TagInput,
  TextInputField,
  SelectField,
  Alert,
  Dialog,
  Badge,
  majorScale,
} from "evergreen-ui";
import "./evergreen.css";
const people = [
  { name: "Avery Stone", plan: "Pro", tags: ["active", "newsletter"] },
  { name: "Taylor Reed", plan: "Free", tags: ["newsletter"] },
  { name: "Jordan Park", plan: "Pro", tags: ["active"] },
  { name: "Morgan Lee", plan: "Team", tags: ["active", "newsletter"] },
  { name: "Casey Chen", plan: "Free", tags: ["trial"] },
];
function App() {
  const [tags, setTags] = useState(["active"]),
    [plan, setPlan] = useState("Any"),
    [name, setName] = useState("Active customers"),
    [error, setError] = useState(""),
    [open, setOpen] = useState(false),
    [saved, setSaved] = useState(null);
  const matches = people.filter(
    (p) =>
      (plan === "Any" || p.plan === plan) &&
      tags.every((t) => p.tags.includes(t)),
  );
  function changeTags(values) {
    const unique = [
      ...new Set(values.map((v) => v.trim().toLowerCase()).filter(Boolean)),
    ];
    if (unique.length > 4) {
      setError("Use at most four tags.");
      return false;
    }
    setTags(unique);
    setError("");
    setSaved(null);
  }
  return (
    <ThemeProvider value={defaultTheme}>
      <main className="audience">
        <header>
          <Text size={300}>WORKSPACE / AUDIENCES</Text>
          <Heading size={700} marginTop={8}>
            Build a focused audience
          </Heading>
          <Paragraph marginTop={8}>
            Combine a plan and tags against five fictional records. No customer
            data is loaded.
          </Paragraph>
        </header>
        <div className="audience-grid">
          <section className="rule-panel">
            <Heading size={500} marginBottom={majorScale(3)}>
              Audience rules
            </Heading>
            <TextInputField
              label="Audience name"
              value={name}
              onChange={(e) => {
                setName(e.target.value);
                setSaved(null);
              }}
            />
            <SelectField
              label="Plan"
              value={plan}
              onChange={(e) => {
                setPlan(e.target.value);
                setSaved(null);
              }}
            >
              <option>Any</option>
              <option>Free</option>
              <option>Pro</option>
              <option>Team</option>
            </SelectField>
            <label htmlFor="audience-tags">Required tags</label>
            <Paragraph size={300} marginBottom={8}>
              Press Enter or comma to add a tag. Every tag must match.
            </Paragraph>
            <TagInput
              values={tags}
              onChange={changeTags}
              width="100%"
              inputProps={{ id: "audience-tags", placeholder: "Add tag…" }}
            />
            <Paragraph size={300} marginTop={8}>
              Available sample tags: active, newsletter, trial.
            </Paragraph>
            {error && <Alert intent="danger" title={error} marginTop={16} />}
            <Button
              appearance="primary"
              marginTop={24}
              onClick={() => {
                if (!name.trim()) {
                  setError("Name the audience before reviewing.");
                  return;
                }
                setError("");
                setOpen(true);
              }}
            >
              Review audience
            </Button>
          </section>
          <section className="results-panel">
            <div className="results-title">
              <Heading size={500}>Matching sample records</Heading>
              <Badge color="blue">
                {matches.length} of {people.length}
              </Badge>
            </div>
            {matches.length ? (
              <div className="record-list">
                {matches.map((p) => (
                  <article key={p.name}>
                    <div>
                      <Heading size={400}>{p.name}</Heading>
                      <Text size={300}>{p.plan} plan</Text>
                    </div>
                    <div className="tag-list">
                      {p.tags.map((t) => (
                        <Badge key={t} color="neutral">
                          {t}
                        </Badge>
                      ))}
                    </div>
                  </article>
                ))}
              </div>
            ) : (
              <div className="empty">
                <Heading size={500}>No matching sample records</Heading>
                <Paragraph marginTop={8}>
                  Remove a tag or change the plan to broaden the selection.
                </Paragraph>
                <Button
                  marginTop={16}
                  onClick={() => {
                    setTags([]);
                    setPlan("Any");
                    setSaved(null);
                  }}
                >
                  Clear rules
                </Button>
              </div>
            )}
            {saved && (
              <Alert
                intent="success"
                title="Local audience saved"
                marginTop={20}
              >
                {saved.name} · {saved.count} sample records. Nothing was sent to
                Segment.
              </Alert>
            )}
          </section>
        </div>
        <Dialog
          isShown={open}
          title="Review local audience"
          onCloseComplete={() => setOpen(false)}
          confirmLabel="Save locally"
          onConfirm={() => {
            setSaved({ name: name.trim(), count: matches.length });
            setOpen(false);
          }}
          width={560}
        >
          <Paragraph>
            <strong>{name}</strong> matches {matches.length} of {people.length}{" "}
            fictional records.
          </Paragraph>
          <Paragraph marginTop={12}>
            Plan: {plan}. Required tags: {tags.join(", ") || "none"}.
          </Paragraph>
          <Paragraph marginTop={12}>
            This saves only a local snapshot; it does not create a Segment
            audience.
          </Paragraph>
        </Dialog>
        <footer>
          Native Evergreen 7.1.9 React components. Original audience logic; no
          analytics or customer service connection.
        </footer>
      </main>
    </ThemeProvider>
  );
}
createRoot(document.getElementById("root")).render(<App />);
```

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

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

### evergreen.css — исходная адаптивная композиция

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

```
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: #f4f5f9;
  color: #101840;
  font:
    14px/1.5 system-ui,
    sans-serif;
}
.audience {
  padding: 32px;
}
.audience header {
  max-width: 800px;
  margin-bottom: 28px;
}
.audience-grid {
  display: grid;
  grid-template-columns: minmax(260px, 0.85fr) minmax(0, 1.5fr);
  gap: 24px;
}
.rule-panel,
.results-panel {
  padding: 24px;
  background: white;
  border: 1px solid #d8dae5;
  border-radius: 8px;
  min-width: 0;
}
.rule-panel > label {
  font-weight: 600;
  display: block;
  margin-bottom: 8px;
}
.results-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}
.record-list article {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 0;
  border-bottom: 1px solid #edeff5;
}
.record-list article:first-child {
  padding-top: 0;
}
.record-list article:last-child {
  border: 0;
}
.tag-list {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.empty {
  padding: 36px 12px;
  text-align: center;
  background: #f4f5f9;
  border-radius: 4px;
}
.audience footer {
  margin-top: 24px;
  font-size: 12px;
  color: #696f8c;
}
.audience input {
  max-width: 100%;
}
[role="dialog"] {
  max-width: calc(100vw - 32px);
}
@media (max-width: 850px) {
  .audience-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 550px) {
  .audience {
    padding: 16px;
  }
  .rule-panel,
  .results-panel {
    padding: 20px;
  }
  .record-list article {
    align-items: flex-start;
    flex-direction: column;
  }
  .results-title {
    align-items: flex-start;
  }
}
```

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

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

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

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

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

```
npm create vite@latest evergreen-audience -- --template react
cd evergreen-audience
npm install
npm install react@18.3.1 react-dom@18.3.1 evergreen-ui@7.1.9
# Replace src/main.jsx and add src/evergreen.css.
npm run dev
```

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

```
Создайте редактор аудитории на основе Evergreen с фактической темой и контролируемым TagInput. Нормализуйте теги и удаляйте дубликаты, явно задайте сопоставление по всем тегам, обеспечьте согласованность списка и числа результатов, просматривайте данные в стандартном Dialog и сбрасывайте устаревшее сообщение об успехе при изменении правил. Не заявляйте о подключении к сервису Segment.
```

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

Руководство по приложению OpenDesign для Evergreen 7.1.9. Пять вымышленных записей демонстрируют локальную фильтрацию и просмотр снимка. Данные клиентов Segment и API аудитории не подключены.

- Поле ввода тегов Evergreen Управляемые значения, разделители и логика отклонения.

- Диалоговое окно Evergreen Стандартное управление фокусом, подтверждением и закрытием.

- Закреплённый источник темы Композиция опубликованной темы по умолчанию.

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

### Semi Design

Создайте пошаговую настройку рабочей среды с базовыми элементами Steps, рекомендованными Semi, управляемыми компонентами Input и Switch, реальными токенами темы и явным выбором пакета React 18 или React 19.

### Semrush Intergalactic

Руководство по Intergalactic с актуальными семантическими токенами и токенами диаграмм, встроенными элементами управления фильтрацией, сравнением в фиксированном масштабе, сведениями о выбранном объекте и полным воспроизводимым примером данных.

### ServiceNow Horizon

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


- [Справочник по реализации](https://evergreen.segment.com/components/tag-input)
- [Источник](https://cdn.jsdelivr.net/npm/evergreen-ui@7.1.9/esm/themes/default/index.js)
- [Источник](https://evergreen.segment.com/components/tag-input)
- [Справочник по коду](https://evergreen.segment.com/components/tag-input)
- [Поле ввода тегов Evergreen Управляемые значения, разделители и логика отклонения.](https://evergreen.segment.com/components/tag-input)
- [Диалоговое окно Evergreen Стандартное управление фокусом, подтверждением и закрытием.](https://evergreen.segment.com/components/dialog)
- [Закреплённый источник темы Композиция опубликованной темы по умолчанию.](https://cdn.jsdelivr.net/npm/evergreen-ui@7.1.9/esm/themes/default/index.js)
