# Segment Evergreen デザインシステム

## Segment Evergreen デザインシステムのインターフェースプレビュー

プランと必須タグを組み合わせ、一致するレコードを確認し、該当なしの場合にリセットして、ローカルのスナップショットを確認します。

## Segment Evergreen デザインシステムのデザインリファレンス

ネイティブの Evergreen 7.1.9 React コンポーネントと 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 の semibold は 500、bold は 600 です。ブラウザーのキーワードのデフォルト値に安易に置き換えないでください。 |
| fontWeights.normal | 400 | このテーマでは、Evergreen の semibold は 500、bold は 600 です。ブラウザーのキーワードのデフォルト値に安易に置き換えないでください。 |
| fontWeights.semibold | 500 | このテーマでは、Evergreen の semibold は 500、bold は 600 です。ブラウザーのキーワードのデフォルト値に安易に置き換えないでください。 |
| fontWeights.bold | 600 | このテーマでは、Evergreen の semibold は 500、bold は 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 | セクション間の余白に使う、8ピクセル単位の大きなスケール。 |
| minorScale(3) | 12px | 小さな要素間の間隔に使う、4ピクセル単位の小さなスケール。 |
| 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 デザインシステムのオーディエンスビルダー構成

### ルールと、それがもたらす結果を並べて表示する

> このサンプルでは、ルールパネルと一致する架空のレコードを並べて表示します。プランの選択と必須タグを結果件数と同時に確認できるため、ルールを変更したときの影響が分かりやすくなっています。現在の組み合わせに該当する人がいるかを確認するために、保存したりダイアログを開いたりする必要はありません。

### 内容が明確な、有限のフィクスチャを使う

プランとタグが記載された5件のサンプルレコードを表示します。顧客データウェアハウスを検索したり、実際のオーディエンス規模を推定したりするものではありません。結果が0件になる場合も、例の有用な一部です。操作ひとつでフィクスチャ全体を復元できます。

## Segment Evergreen デザインシステムのテーマ値とセマンティクス

### 実際のデフォルトテーマを確認する

Evergreen 7.1.9 では、名前付きカラーやコンポーネントスタイルに加えて、インデックス付きの角丸、フォントサイズ、行の高さが提供されています。この表では、エクスポートされた値をそのまま掲載しています。特にフォントウェイトの名前は確認する価値があります。semibold と bold はそれぞれ 500 と 600 で、一般的な想定とは異なります。

### 独自の画面構成にもテーマとの一貫性を保つ

ThemeProvider はネイティブの入力欄、タグ、バッジ、ボタン、ダイアログにテーマを適用します。独自に作成したパネルにも、同じ落ち着いたクールグレーとブルーの組み合わせを使います。広範な CSS セレクターでネイティブコンポーネントの内部スタイルを上書きしないため、提供されている操作時のスタイルが保たれます。

## Segment Evergreen デザインシステム ルール編集のタイポグラフィ

### タスクが伝わる明確な階層を設ける

見出しのロールを使い、オーディエンス名、パネルのタイトル、個々の結果名を区別します。補足文ではタグの入力方法とデータが架空であることを説明します。件数バッジは結果の見出しの横に配置し、見出しの代わりには使いません。これにより、ユーザーは数値を読み取る前に、どの領域の情報かを把握できます。

### メタデータを読みやすく保つ

プランやタグの情報は、対応する説明を補足するものであり、単なる装飾ではありません。狭い画面では、タグが折り返され、レコードのテキストとバッジが縦に並ぶレイアウトになります。すべてのラベルを極端に小さな文字にすると、ルールを理解するために必要な情報が見えにくくなります。

## Segment Evergreen デザインシステムのメジャー・マイナースケール

### 繰り返し使う余白には関数を使う

majorScale と minorScale は、それぞれ8pxと4px刻みの値を表します。コンポーネント例では、パネル見出しの間隔に majorScale(3) を使って24pxを指定し、レスポンシブなレイアウトはカスタムスタイルシートで調整しています。この違いを明確にしましょう。グリッドのブレークポイントはアプリケーション側の判断であり、余白関数によって決まるものではありません。

### モバイルでもフィールド間の関係を保つ

ルールパネルは、元のアプリケーションのブレークポイントで結果の上に移動します。ラベル、ヒント、コントロールはひとまとまりに保たれ、タグ入力欄は利用可能な幅いっぱいに広がります。タグを標準で折り返すことで、値が長く並んでもフォームが横スクロールするのを防ぎます。

## Segment Evergreen デザインシステムの制御タグと一致条件

### 値を受け入れる前に正規化する

onChange ハンドラーは文字列の前後の空白を取り除いて小文字に変換し、重複を削除したうえで、異なるタグが4つを超える場合は拒否します。追加が拒否されたときに false を返すと、入力欄の値が維持されます。この方針はオーディエンスを扱うアプリケーション側の責務です。TagInput は制御された操作を提供しますが、業務上の上限は決めません。

### すべてのタグを条件にする場合は意図を明確にする

レコードは、選択したプランと必須タグすべてに一致する必要があります。タグをクリアするとタグの条件が解除され、「すべて」を選ぶとプランの条件が解除されます。現在の結果件数は、画面に表示するものと同じフィルタリング済み配列から算出されるため、件数と表示カードが食い違いません。

## Segment Evergreen デザインシステムのレビュー用ダイアログとローカルスナップショット

### 保存前に現在のルールを確認する

ダイアログを開くには、オーディエンス名が入力されている必要があります。ダイアログには名前、件数、プラン、タグが再表示され、その後に「ローカルに保存」が提示されます。「本当によろしいですか？」とだけ尋ねる空疎な確認ではなく、具体的なスナップショットを確認できるネイティブのオーバーレイを示す手順です。

### ルールが変更されたら以前の成功状態を無効にする

名前、プラン、タグを変更すると、保存済みスナップショットの表示がクリアされます。これにより、以前のローカル保存が新しく編集したルールの確認だと誤認されるのを防ぎます。このアプリケーションは、スナップショットを Segment のオーディエンスとして説明したり、顧客プラットフォームにリクエストを送信したりしません。

## Segment Evergreen デザインシステムのキーボード入力とダイアログ復帰

### タグ、結果、レビューを一連の流れでテストする

説明されているキーでタグを追加でき、id によって入力欄に表示ラベルが関連付けられています。タグ数の上限によって追加が拒否されると、ネイティブの危険アラートが表示されます。レビューには、フォーカス管理を自作したオーバーレイではなく、ネイティブ Dialog のフォーカス動作を使用しています。

1. newsletter を最初の有効なタグに追加し、件数を比較します。

2. 一致しないタグを追加し、その後ルールをクリアして5件に戻します。

3. レビューしてローカルに保存した後、ルールを変更し、以前の成功表示が消えることを確認します。

### 空の結果からの復帰を現在のタスク内で完結させる

「ルールをクリア」を選ぶと、プランとタグの両方の制限が解除され、古い保存状態の表示も消えます。結果領域には再び5件すべてが表示されます。非表示の画面遷移やページの再読み込みは必要なく、ユーザーはすぐに編集を続けられます。

## Segment Evergreen デザインシステムのReact統合

### ひとまとまりの、動作を確認できる例を使う

ネイティブのエントリーポイントでは、ThemeProvider、defaultTheme、描画するコンポーネントをインポートします。状態には、ルール、エラー、ダイアログの表示状態、ローカルに保存したスナップショットを保持します。以下の JSX と CSS には架空のテストデータも含まれているため、外部の API がなくても結果計算を再現できます。

- ThemeProvider には、固定バージョンの defaultTheme を使用します。

- TagInput の値はアプリケーション側で制御します。

- Dialog では、結果リストと同じルールを確認できます。

### データアクセスは独立したアプリケーション層として追加する

実際のオーディエンスツールには、認証されたデータアクセス、明確に定義された一致条件のクエリ、読み込み状態、サーバー側での保存処理が必要です。ルールのプレビューとオーディエンスの永続化は、明確に区別してください。実際のデータセットに接続する際は、テストデータ5件の件数をそのまま使わないでください。

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

コードリファレンス

- Vite React プロジェクトを作成し、<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
```

### あなたのプロジェクト向けプロンプト

```
実際のテーマと制御された TagInput を使って、Evergreen のオーディエンスエディターを構築します。タグを正規化して重複を除き、すべてのタグを条件とすることを明示し、結果と件数の整合性を保ち、ネイティブの Dialog で内容を確認し、ルールの変更時には古い成功状態をクリアしてください。Segment サービスとの接続をうたわないでください。
```

## Segment Evergreen デザインシステムの参照元と適用範囲

Evergreen 7.1.9 向けの OpenDesign アプリケーションガイドです。架空の5件のレコードを使って、ローカルでのフィルタリングとスナップショットのレビューを説明します。Segment の顧客データやオーディエンス API には接続しません。

- Evergreen のタグ入力 制御された値、区切り文字、入力を拒否する動作。

- Evergreen のダイアログ ネイティブのフォーカス、確認、閉じる動作。

- 固定バージョンのテーマソース 公開されているデフォルトテーマの構成。

## Segment Evergreen デザインシステムの関連リソース

### Semi Design

Semi推奨の基本的なSteps、制御された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)
