# Sainsbury's デザインシステム

## Sainsbury's デザインシステム インターフェースのプレビュー

日付と時刻を変更し、料金の例を確認してから、ローカルでの選択内容を確認します。

## Sainsbury's デザインシステム デザインリファレンス

公開されているSainsbury’sのカラー、サイズトークン、タイポグラフィ、コンポーネントのガイドです。公開情報のブレークポイント表に相違がある場合は、統合せずに明示しています。

### Sainsbury’sのパレットのロール

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| Primary brand base | #F06C00 | この研究では、ブランドアクセントとボタンの塗りに、ダークカラーのテキストを組み合わせています。 |
| Primary hover | #E55000 | ホバー時の塗り。白背景で小さな文字の色として使うことはできません。 |
| Primary pressed | #C15100 | 押下状態。 |
| Primary light | #FEF5F0 | 選択状態とサマリーの背景。 |
| Secondary base | #7F0442 | 装飾的なアクセントとして控えめに使用。 |
| Monochrome darker | #262626 | 主要コンテンツ。 |
| Monochrome dark | #404040 | 補足コンテンツ。 |
| Monochrome light | #D8D8D8 | 境界線。 |
| Monochrome lighter | #F2F2F2 | 選択できないオプションの背景。 |
| Success lighter | #E6F4ED | ローカルの確認メッセージ用の背景。 |
| Success darker | #246127 | メッセージのテキスト。 |
| Info darker | #135CA3 | アプリケーションのフォーカスアウトライン。 |
### 公開されているサイズトークン

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| xs | 2px | 公開されているサイズトークン表のスペーシング値。 |
| sm | 4px | 公開されているサイズトークン表のスペーシング値。 |
| md | 8px | 公開されているサイズトークン表のスペーシング値。 |
| lg | 16px | 公開されているサイズトークン表のスペーシング値。 |
| xl | 24px | 公開されているサイズトークン表のスペーシング値。 |
| 2xl | 32px | 公開されているサイズトークン表のスペーシング値。 |
| 3xl | 40px | 公開されているサイズトークン表のスペーシング値。 |
| 4xl | 48px | 公開されているサイズトークン表のスペーシング値。 |
| width-sm | 1px | ボーダーのトークン。幅と角丸の名前を混同しないでください。 |
| width-base | 2px | ボーダーのトークン。幅と角丸の名前を混同しないでください。 |
| radius-base | 2px | ボーダーのトークン。幅と角丸の名前を混同しないでください。 |
| radius-xl | 12px | ボーダーのトークン。幅と角丸の名前を混同しないでください。 |
| min-width-sm | 576px | トークンのブレークポイント。エディトリアルレイアウトのページとは異なります。 |
| min-width-md | 768px | トークンのブレークポイント。エディトリアルレイアウトのページとは異なります。 |
| min-width-lg | 992px | トークンのブレークポイント。エディトリアルレイアウトのページとは異なります。 |
| min-width-xl | 1200px | トークンのブレークポイント。エディトリアルレイアウトのページとは異なります。 |
### Sainsbury’sの文字サイズスケール

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| Body 1 | 1rem / 1.5 / Arial Regular | 本文。 |
| Caption | 0.875rem / 1.571 / Arial Regular | 補足メモ。 |
| Label 1 | 1rem / 1.5 / Arial Bold | コントロールのラベル。 |
| Display 1 | 1.25rem / 1.3 | 公式ガイドに記載されたブランド用ディスプレイ書体。この例では代替書体を使用しています。 |
| Display 2 | 1.5rem / 1.333 | レスポンシブ時の代替はDisplay 3です。 |
| Display 3 | 1.875rem / 1.333 | レスポンシブ時の代替はDisplay 4です。 |
| Display 4 | 2.375rem / 1.316 | レスポンシブ時の代替はDisplay 5です。 |
| Display 5 | 3rem / 1.292 | レスポンシブ時の代替はDisplay 6です。 |
| Display 6 | 3.75rem / 1.267 | ドキュメントに記載されたディスプレイ書体の最大サイズ。 |
| Responsive type threshold | larger than 720px | 768pxのサイズトークンのブレークポイントとは独立しています。 |
## Sainsbury's デザインシステム 完全ガイド

実際のインターフェースで、このデザインシステムを選び、適用し、レビューするための実践ガイドです。

詳しいガイダンス、実装の出発点、ソースへのリンクをまとめています。

## Sainsbury's デザインシステム Sainsbury's デザインシステム マルチブランドシステムとアクセス

### ブランドテーマを1つ選ぶ

> Fableは、共通のコンポーネント構造とブランド固有の値を通じて、Sainsbury’s、Argos、Nectar、Tu、Habitatをサポートしています。このガイドではSainsbury’sのパレットのみを使用します。Sainsbury’sの操作にNectarの紫を混ぜたり、すべてのブランドで同じフォントが使われると想定したりすると、明示されたシステムの境界が曖昧になります。選択したテーマは、アプリケーションのエントリーポイントに関連付けてください。

### 公開ガイドと非公開パッケージを区別する

公開されているパートナー向けガイドには、Reactのコンポーネント、Fable Styles、デザイントークンパッケージについて記載されていますが、コードベースへのアクセスにはSainsbury’sの担当者を通じて取得する認証情報が必要です。この例には必要ありません。公開ガイドに基づいて作成した、完全なオリジナルのHTMLです。Fableが動作すると装ったり、アクセスできないレジストリ向けのインストールコマンドを作り出したりしていません。

## Sainsbury's デザインシステム Sainsbury's デザインシステム 配色とコントラスト

### オレンジには適切な文字色を組み合わせる

資料によると、ベースオレンジとダークオレンジは、白地で通常の本文テキストに使う場合のコントラスト要件を満たしません。この例では、白地に小さなオレンジ文字を置いたり、オレンジ地に小さな白文字を置いたりせず、黒いボタン文字を添えた塗りつぶしとしてオレンジを使っています。ドキュメントに記載されたブランド上の例外を、あらゆる配色がアクセシブルであるという主張にすり替えてはいけません。

### フィードバックには意味のある色を使う

確認結果には、成功を示す緑の背景と濃い緑の文字を使っています。利用できない枠にはニュートラルな背景と文字ラベルを使い、選択中の枠にはチェック済みラジオボタンとオレンジの枠線を併用しています。色は補助的な手がかりです。時刻、空き状況、選択状態を示すテキストの代わりにはなりません。

## Sainsbury's デザインシステム Sainsbury's デザインシステム 余白、角丸、ブレークポイントの境界

### 公開されているサイズスケールに従う

この例では、選択肢の間に8px、各枠内に16px、主要なグループ間に24〜32pxの余白を設けています。コントロールの角丸は2px、概要欄の角丸はドキュメントに記載された12pxです。どこにでも同じ角丸のカードを使うのではなく、こうした違いでグループ分けを表現しています。

### ドキュメント間の不一致を明記する

レイアウトガイドにはデバイスのしきい値として600pxと900pxが記載されていますが、サイズトークンの表では576px、768px、992pxが示されています。タイポグラフィガイドでは、720pxを超えるとディスプレイ用文字のサイズが別途変わります。これらは同じスケールを別の名前で呼んでいるわけではありません。この実装では、列の切り替えにサイズトークンの768pxのしきい値を採用し、その選択を明記しています。

## Sainsbury's デザインシステム Sainsbury's デザインシステム タイポグラフィと役立つ情報

### ブランドフォントの使用範囲を守る

Sainsbury’sの公式ディスプレイスタイルではMary Ann Extra Bold、通常の本文ではArialを使います。この公開サンプルにはブランドフォントのファイルが含まれていないため、全体をArialで組んでいます。フォールバックフォントが視覚的に同一だとは主張せず、文字のスケールと行の高さの関係を維持しています。見出しのセマンティックなレベルは、ディスプレイ文字のサイズとは独立しています。

### 受け取り方法を読み取りやすくする

各枠には時間帯と料金、または利用不可のラベルを表示します。概要欄には選択した日付、時間、サンプルの場所を再掲します。メインアクションには、次にこの画面で行う操作を表す「受け取り内容を確認」と表示します。商用らしく見せるために、タイマー、注文合計、予約完了を作り出すことはしていません。

## Sainsbury's デザインシステム Sainsbury's デザインシステム ラジオボタンの選択肢とローカル状態

### グループ内で連動する選択肢を使う

日付コントロールを変更すると選べる時間帯が変わります。各時間帯は、名前を付けた1つのグループ内にあるネイティブのラジオボタンです。日付を変更すると、最初に利用可能な枠が選択され、概要欄も更新されます。利用不可の選択肢は表示されたままですが、選択できません。ネイティブのラジオボタンを使うことで、クリック可能なdiv要素を使ってキーボード操作を再現せずに、なじみのある操作性を提供します。

### 古い予約情報を残さない

確認すると、ローカルの確認メッセージが表示され、枠は予約されていないことが伝わります。日付か時間を変更すると、そのメッセージは非表示になります。本番フローで予約済みと表示するには、最新の空き状況確認とサーバーからの応答が必要です。この例では操作の仕様を切り分けて示し、バックエンドの未実装を予約完了と誤解されないようにしています。

## Sainsbury's デザインシステム Sainsbury's デザインシステム タップ領域、フォーカス、レスポンシブ動作

### 選択肢に十分なスペースを確保する

公開されているボタンのガイドでは、48pxのタップ領域を推奨しています。日付ボタンと確認アクションはこの高さを満たし、各枠はラベルを含む全体をクリックできます。青いフォーカスアウトラインは、オレンジや淡い背景の上でも見える状態を保ちます。装飾用のバスケットマークは、支援技術から隠しています。

### 長い内容も折り返して表示する

画面幅が狭い場合、概要欄は選択肢一覧の後に表示され、装飾用のマークは非表示になります。枠のラベルや料金は通常のドキュメントフローに配置し、高さを柔軟にしています。翻訳後の場所名などが長くなっても、固定サイズのカード内で切り詰めないようにしてください。この英語のプロトタイプでは、後のローカライズに備えて余裕を持たせています。

## Sainsbury's デザインシステム Sainsbury's デザインシステム 実装とAIエージェントによるレビュー

### 単体で動作するサンプルを実行する

HTMLの完全なサンプルを保存し、ローカルで配信してください。3日分と各日の3つの枠はサンプルデータとして記述されており、変更内容はすべてメモリ内に保持されます。ソースにはCSS、ラジオボタンの生成、概要欄の更新、古いフィードバックのクリア処理が含まれているため、プレビューの背後に未実装のアプリケーション層はありません。

1. ファイル全体をindex.htmlとして保存します。

2. 火曜日を選択し、午前中の利用不可の枠が選択できないことを確認します。

3. 時間を変更し、概要欄を確認します。

4. 確認を実行した後、日付を変更し、古い結果が消えることを確認します。

### アクセスを確認してからFableに移行する

認可された社内連携を行う場合は、実際のパッケージアクセスを取得し、現在のテーマとコンポーネントAPIを確認してください。この例の動作を維持しながら、オリジナルのマークアップをサポート対象のコンポーネントに置き換えます。スクリーンショットを実装の証拠として扱う前に、インストール済みのトークンスケールが公開資料の内容と一致することを確認してください。

- ブランドテーマを一貫して使う。

- パッケージへのアクセスと現在のAPIを確認する。

- テキストのコントラストとブランドカラーの再現性を個別に確認する。

## Sainsbury's デザインシステム Sainsbury's デザインシステムのコンポーネント例

### 受け取り枠選択の一連の操作

日付選択、ラジオボタンの枠、選択不可の空き状況、動的な概要欄を備えた、独立したHTML/CSS/JavaScript。

```
<!doctype html>
<html lang="en">
  <meta charset="utf-8" /><meta
    name="viewport"
    content="width=device-width,initial-scale=1"
  /><title>Collection slot study</title
  ><style>
    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
      background: #fff;
      color: #262626;
      font:
        16px/1.5 Arial,
        sans-serif;
      padding: 32px;
    }
    header {
      border-top: 8px solid #f06c00;
      padding-top: 24px;
      display: flex;
      justify-content: space-between;
      gap: 24px;
    }
    h1 {
      font-size: 38px;
      line-height: 1.316;
      margin: 8px 0 16px;
    }
    h2 {
      font-size: 24px;
      line-height: 1.333;
      margin: 0 0 16px;
    }
    .eyebrow,
    small {
      font-size: 14px;
      color: #404040;
    }
    p {
      margin: 8px 0 24px;
    }
    .basket {
      font-size: 48px;
      line-height: 1;
      background: #fef5f0;
      border-radius: 50%;
      width: 96px;
      height: 96px;
      display: grid;
      place-items: center;
      color: #7f0442;
    }
    main {
      display: grid;
      grid-template-columns: 2fr 1fr;
      gap: 32px;
      margin-top: 24px;
    }
    fieldset {
      border: 0;
      padding: 0;
      margin: 0 0 24px;
    }
    legend {
      font-weight: bold;
      margin-bottom: 16px;
    }
    .dates {
      display: flex;
      gap: 8px;
      flex-wrap: wrap;
    }
    button,
    select {
      font: inherit;
      min-height: 48px;
      padding: 12px 16px;
      border: 1px solid #737373;
      border-radius: 2px;
      background: white;
      color: #262626;
      cursor: pointer;
    }
    .dates button[aria-pressed="true"] {
      border: 2px solid #f06c00;
      background: #fef5f0;
      padding: 11px 15px;
    }
    .slots {
      display: grid;
      gap: 8px;
    }
    .slot {
      display: flex;
      gap: 12px;
      align-items: center;
      padding: 16px;
      border: 1px solid #d8d8d8;
      border-radius: 2px;
      cursor: pointer;
    }
    .slot:has(input:checked) {
      border: 2px solid #f06c00;
      padding: 15px;
      background: #fef5f0;
    }
    .slot:has(input:disabled) {
      background: #f2f2f2;
      cursor: default;
    }
    .slot input {
      accent-color: #c15100;
      width: 20px;
      height: 20px;
    }
    .slot strong {
      margin-left: auto;
    }
    .unavailable {
      color: #404040;
    }
    .primary {
      background: #f06c00;
      border: 2px solid #f06c00;
      font-weight: bold;
      color: #000;
    }
    .primary:hover {
      background: #e55000;
      border-color: #e55000;
    }
    .primary:active {
      background: #c15100;
      border-color: #c15100;
    }
    .summary {
      background: #fef5f0;
      border-radius: 12px;
      padding: 24px;
      align-self: start;
    }
    .summary dl {
      margin: 0;
    }
    .summary dt {
      font-size: 14px;
      margin-top: 16px;
    }
    .summary dd {
      margin: 4px 0;
      font-weight: bold;
    }
    #result {
      padding: 16px;
      background: #e6f4ed;
      color: #246127;
      margin-top: 24px;
    }
    button:focus-visible,
    input:focus-visible {
      outline: 3px solid #135ca3;
      outline-offset: 3px;
    }
    footer {
      border-top: 1px solid #d8d8d8;
      margin-top: 32px;
      padding-top: 16px;
      font-size: 14px;
      color: #404040;
    }
    [hidden] {
      display: none !important;
    }
    @media (max-width: 767px) {
      body {
        padding: 16px;
      }
      main {
        grid-template-columns: 1fr;
        gap: 24px;
      }
      h1 {
        font-size: 30px;
      }
      .basket {
        display: none;
      }
      .dates button {
        flex: 1;
      }
      .summary {
        padding: 16px;
      }
    }
  </style>
  <body>
    <header>
      <div>
        <span class="eyebrow">GROCERIES / ORIGINAL COLLECTION STUDY</span>
        <h1>Choose a collection slot</h1>
        <p>
          Select a sample day and time. No order or real availability is
          connected.
        </p>
      </div>
      <div class="basket" aria-hidden="true">▥</div>
    </header>
    <main>
      <section>
        <fieldset>
          <legend>Collection day</legend>
          <div class="dates" id="dates"></div>
        </fieldset>
        <fieldset>
          <legend id="slotLabel">Available times</legend>
          <div id="slots" class="slots"></div>
        </fieldset>
      </section>
      <aside class="summary">
        <h2>Collection details</h2>
        <dl>
          <dt>Sample location</dt>
          <dd>Riverside collection point</dd>
          <dt>Day and time</dt>
          <dd id="selection"></dd>
          <dt>Sample fee</dt>
          <dd id="fee"></dd>
        </dl>
        <p><small>All fees and slots are illustrative.</small></p>
        <button class="primary" id="review">Review collection</button>
        <div id="result" role="status" hidden></div>
      </aside>
    </main>
    <footer>
      Independent HTML interpretation of Sainsbury’s public guidance. Arial
      fallback; no private Fable runtime or brand font assets.
    </footer>
    <script>
      const days = [
        {
          label: "Monday",
          slots: [
            ["09:00–10:00", 1, true],
            ["12:00–13:00", 0, true],
            ["17:00–18:00", 2, false],
          ],
        },
        {
          label: "Tuesday",
          slots: [
            ["09:00–10:00", 0, false],
            ["12:00–13:00", 1, true],
            ["17:00–18:00", 1, true],
          ],
        },
        {
          label: "Wednesday",
          slots: [
            ["09:00–10:00", 0, true],
            ["12:00–13:00", 0, true],
            ["17:00–18:00", 2, true],
          ],
        },
      ];
      let day = 0,
        slot = 0;
      const $ = (id) => document.getElementById(id);
      function update() {
        const choice = days[day].slots[slot];
        $("selection").textContent = days[day].label + ", " + choice[0];
        $("fee").textContent =
          choice[1] === 0 ? "No collection fee" : "£" + choice[1].toFixed(2);
        $("result").hidden = true;
      }
      function render() {
        $("dates").replaceChildren(
          ...days.map((d, i) => {
            let b = document.createElement("button");
            b.textContent = d.label;
            b.setAttribute("aria-pressed", i === day);
            b.onclick = () => {
              day = i;
              slot = d.slots.findIndex((s) => s[2]);
              render();
            };
            return b;
          }),
        );
        $("slotLabel").textContent = days[day].label + " collection times";
        $("slots").replaceChildren(
          ...days[day].slots.map((s, i) => {
            let l = document.createElement("label");
            l.className = "slot";
            let input = document.createElement("input");
            input.type = "radio";
            input.name = "time";
            input.checked = i === slot;
            input.disabled = !s[2];
            input.onchange = () => {
              slot = i;
              update();
            };
            let text = document.createElement("span");
            text.textContent = s[0];
            let fee = document.createElement("strong");
            fee.textContent = s[2]
              ? s[1] === 0
                ? "No fee"
                : "£" + s[1].toFixed(2)
              : "Unavailable";
            l.append(input, text, fee);
            return l;
          }),
        );
        update();
      }
      $("review").onclick = () => {
        $("result").hidden = false;
        $("result").textContent =
          "Local selection ready: " +
          $("selection").textContent +
          ". No slot has been reserved.";
      };
      render();
    </script>
  </body>
</html>
```

コードリファレンス

- 非公開パッケージや認証情報は不要です。

## Sainsbury's デザインシステム エージェントのセットアップ

### 実装の出発点

Fableパッケージへのアクセスは、公開されているこの単体のサンプルとは別途必要です。

```
# Save the complete HTML example as index.html
python3 -m http.server 8080
# Open http://localhost:8080
```

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

```
このHTMLの完全なサンプルをもとに、Sainsbury’sのガイダンスに沿った受取枠選択画面を作成してください。ブランドカラーは一貫させ、オレンジ色のアクションには黒いテキストを使用します。ラベル付きのネイティブラジオボタン、48pxのタップ領域、明示的な768pxのレイアウト切り替えを採用してください。選択が変わるたびに、確認フィードバックをクリアします。利用可能な枠は架空のものとし、Fableランタイムの使用や予約の完了を示唆しないでください。
```

## Sainsbury's デザインシステム ソースと対象範囲

Sainsbury’sの公開ガイダンスをもとにしたOpenDesignアプリケーションの検討例です。これは独自のHTMLであり、非公開のFableランタイムではありません。再配布されたMary AnnのアセットではなくArialを使用し、受取枠と手数料は架空のものです。

- Sainsbury’sのカラー パレットの値と、オレンジ色のコントラストに関する制約。

- サイズトークン 境界線、間隔、ブレークポイントの値。

- タイポグラフィ ブランド書体、スケール、レスポンシブ動作。

- ラジオボタン 選択、ラベル、グループ化。

- Button アクションの優先順位、ラベル、タップ領域。

- パートナーアクセス 非公開コードベースへのアクセスと実装方法。

- レイアウト エディトリアルレイアウトグリッド。サイズトークンのブレークポイントとは異なります。

## Sainsbury's デザインシステム 関連リソース

### Salesforce Lightning

詳細なレコードを扱うための Lightning ブループリントガイドです。実際の余白、タイポグラフィ、セマンティックカラー、編集可能なケースワークスペース、フィールド検証、ローカルの変更を反映するアクティビティ履歴を紹介します。

### Samsung One UI

ダーク表示と明示的なリセット時の復旧を備えた、オリジナルの読書設定プレビューを通じて、One UIの閲覧・操作の構成、24dpのマージン指針、テキストを200%に拡大する要件を確認できます。

### SAP Fiori

UI5 Web Componentsを使ってSAP FioriのHorizonテーマを適用します。実際のテーマパラメーター、明示的なコンテンツ密度、セマンティックな値の状態、ローカル検証を備えた購入申請画面の構成を使用します。


- [実装リファレンス](https://design-systems.sainsburys.co.uk/components/radio-button/)
- [ソース](https://design-systems.sainsburys.co.uk/foundations/colour/sainsburys-colours/)
- [ソース](https://design-systems.sainsburys.co.uk/foundations/design-tokens/size-tokens/)
- [ソース](https://design-systems.sainsburys.co.uk/foundations/typography/)
- [コードリファレンス](https://design-systems.sainsburys.co.uk/components/radio-button/)
- [Sainsbury’sのカラー パレットの値と、オレンジ色のコントラストに関する制約。](https://design-systems.sainsburys.co.uk/foundations/colour/sainsburys-colours/)
- [サイズトークン 境界線、間隔、ブレークポイントの値。](https://design-systems.sainsburys.co.uk/foundations/design-tokens/size-tokens/)
- [タイポグラフィ ブランド書体、スケール、レスポンシブ動作。](https://design-systems.sainsburys.co.uk/foundations/typography/)
- [ラジオボタン 選択、ラベル、グループ化。](https://design-systems.sainsburys.co.uk/components/radio-button/)
- [Button アクションの優先順位、ラベル、タップ領域。](https://design-systems.sainsburys.co.uk/components/button/)
- [パートナーアクセス 非公開コードベースへのアクセスと実装方法。](https://design-systems.sainsburys.co.uk/getting-started/for-third-party-partners/)
- [レイアウト エディトリアルレイアウトグリッド。サイズトークンのブレークポイントとは異なります。](https://design-systems.sainsburys.co.uk/foundations/layout/)
