# B.C. デザインシステム

## B.C. デザインシステムインターフェースプレビュー

メールと電話を切り替えても入力内容を保持し、検証後にローカルの設定を確認できます。

## B.C. デザインシステムデザインリファレンス

ネイティブの@bcgov/design-system-react-components 0.8.1、トークン5.0.0、BC Sans 2.1.2。

### 界面表面とテキストの役割

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| --surface-color-primary-button-default | #013366 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-primary-button-hover | #1e5189 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-primary-button-disabled | #edebe9 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-background-white | #ffffff | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-background-light-gray | #faf9f8 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-background-light-blue | #f1f8fe | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-border-default | #d8d8d8 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-border-medium | #898785 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --surface-color-border-active | #2e5dd7 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-color-primary | #2d2d2d | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-color-secondary | #474543 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-color-link | #255a90 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-color-danger | #ce3e39 | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-color-primary-invert | #ffffff | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
### レイアウトのリズム

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| --layout-padding-hair | 0.125rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-padding-xsmall | 0.25rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-padding-small | 0.5rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-padding-medium | 1rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-padding-large | 1.5rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-padding-xlarge | 2rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-margin-medium | 1rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-margin-large | 1.5rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-margin-xlarge | 2rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-margin-xxxlarge | 3rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-border-radius-small | 2px | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-border-radius-medium | 4px | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --layout-border-radius-large | 6px | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
### 文字のサイズ階層

| 名前 / ルール | 値 / 設定 | 用途 |
| --- | --- | --- |
| --typography-font-size-small-body | 0.875rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-body | 1rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-large-body | 1.125rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-h5 | 1.25rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-h4 | 1.5rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-h3 | 1.75rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-h2 | 2rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-h1 | 2.25rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
| --typography-font-size-display | 3rem | 公開されているB.C.の役割です。値を生の色や寸法に置き換えず、用途に応じて使用してください。 |
## B.C. デザインシステム完全ガイド

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

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

## B.C. デザインシステムの現在のReactライブラリとトークン

### メンテナンスされている実装を選ぶ

> 現在のB.C. Design Systemは、React Ariaを基盤とするReactコンポーネントを提供します。この例では、react-components 0.8.1と、その依存関係であるdesign-tokens 5.0.0をバージョン固定しています。旧B.C. Web Componentsリポジトリは、別のレガシー実装です。これをインポートしても、現在のReactライブラリと同じものにはなりません。例をコピーする前に、ドキュメントと実装が一致していることを確認してください。

### 実際のフォントフェイスをインポートする

コンポーネントが想定するフォントファミリー名は、スペースを含むBC Sansです。バージョン2.1.2ではcss/BC_Sans.cssが提供されています。旧形式のBCSans.cssは非推奨とされており、異なるフォントファミリー名が宣言されています。開発者のマシンにBC Sansがインストールされていると、フォントのインポート漏れに気づかないことがあります。この実例には公開済みフォントが含まれているため、ローカルへのインストールに依存せずに表示できます。

## B.C. デザインシステム セマンティックカラーとスペーシングの役割

### 値を選ぶ前に役割を確認する

プライマリボタンにはダークブルーの塗り色を使い、補足コンテンツには typography-color-secondary を使います。エラーメッセージには typography-color-danger を使います。この表には現在の CSS のエクスポート名を記載しています。将来テーマによって値が変わっても、名前が安定した用途を示します。非アクティブなコントロールの色を、通常の補足テキストと混同しないでください。

### 意図をもってレイアウトを設計する

フォームではフィールド間に 24px の間隔を設け、メインタスクと補足説明の間にはより広い 48px の余白を取っています。これらの値はライブラリのリズムに対応していますが、2 カラム全体の構成はこのサンプル用に作成したものです。モバイルレイアウトではカラムを 1 列にし、フォームラベルを縮小したり、説明テキストをツールチップにしたりしません。

## B.C. デザインシステム 条件付きフィールドと入力値の保持

### 選択した連絡方法だけを検証する

ネイティブの RadioGroup で、Email address または Phone number の TextField の表示を切り替えます。連絡方法を切り替えても、どちらの値も React の state に保持されますが、レビュー時の検証対象になるのは選択中のフィールドだけです。これにより、入力済みの情報を保ちながら、非表示のフィールドが現在のタスクを妨げることを防げます。

### その場で役立つエラーを表示する

メールアドレスのフィールドでは基本的な形式を確認し、電話番号の例では 10 桁以上の数字を必須とします。これらはサンプル用のルールであり、国際的な連絡先を網羅的に検証するものではありません。レビューで無効と判定された場合は isInvalid を設定し、フィールドに固有の errorMessage を表示します。同意がない場合はメッセージを表示し、最初に無効となったコントロールにフォーカスを移します。

## B.C. デザインシステム React Aria コンポーネントの契約

### 制御された値とドキュメントに記載されたハンドラーを使う

TextField には value と onChange を、RadioGroup には value と onChange を指定します。Checkbox では isSelected と onChange を使います。これらのハンドラーが受け取るのは、ドキュメントに記載された値であり、常に event.target から値を読み取らなければならないブラウザーイベントオブジェクトではありません。Button には type=submit を指定し、ネイティブフォームの submit イベントを使うことで、キーボードからの送信でも同じ検証処理を実行します。

### レビュー結果を常に最新の状態に保つ

レビューの設定では、選択した連絡方法の概要をローカルに表示します。何かを変更すると、以前の結果を消去し、送信後のエラー状態をリセットします。この例は、メールを送信したとも、リマインダーを設定したとも示しません。そのように表示するには、実際の通知サービスにおいて、同意の取得、データの永続化、配信に関する契約を別途定める必要があります。

## B.C. デザインシステム アクセシブルな名前とレスポンシブな構成

### ラベル、説明、エラーを関連付ける

ネイティブコンポーネントは、ラベル、ヘルプテキスト、エラーメッセージに対する React Aria の関連付けを提供します。アプリケーション側では、意味のあるラベル、明確なグループの説明、理解しやすい検証メッセージを用意する必要があります。テストでは、表示されているラベルをクリックし、キーボードで操作してください。内部で視覚的に隠されている input は、表示上の操作対象ではありません。

### 補足情報をフォームと分けて配置する

隣接するコールアウトでは、ローカルでの操作手順を説明し、実装の補足情報をネイティブの details 開示要素に含めています。画面幅が狭い場合は、読み上げ順でフォームの後に配置されます。情報アイコンは装飾用です。意味は見出しで伝えます。コンポーネントを検討するうえで、公式の B.C. ロゴや政府サービスであることを示す表記は必要ありません。

## B.C. デザインシステム完全なReact実装

### 検証済みのソースを再現する

Vite React プロジェクトを作成し、バージョンを固定したコンポーネント、トークン、フォントのパッケージをインストールします。提供された main.jsx と bc.css を、ルートのマウント要素とともに使用してください。バンドルには、ネイティブのラジオボタン、フィールド、チェックボックス、ボタンの動作に加え、ローカルでの検証と状態遷移がすべて含まれています。非公開の API や認証情報は必要ありません。

1. バージョンを固定したパッケージをインストールし、css/BC_Sans.css を読み込みます。

2. ルートのマウント要素を維持したまま、main.jsx と bc.css を保存します。

3. 空のフォームを送信してから、表示されたフィールドを修正します。

4. 連絡方法を切り替え、以前の入力値が保持されることを確認します。

### 条件付き検証を選択中の連絡方法に合わせる

RadioGroup と TextField の onChange ハンドラーは値を受け取り、Checkbox の onChange ハンドラーは選択状態を示すブール値を受け取ります。すべてのコンポーネントに汎用的な event.target.value ハンドラーを適用するのではなく、受け取った値をそのまま保存してください。React Aria によってネイティブの input が視覚的に隠されていても、表示されているラベルが操作対象になります。

連絡方法を変更したときは、両方の入力途中の値を保持しつつ、以前のレビュー結果を消去して、選択中の方法だけを検証します。送信後は、最初に無効となった表示中のコントロールにフォーカスを移します。これにより、メールアドレスを失ったり、非表示の電話番号フィールドに妨げられたりすることなく、連絡方法を比較できます。このサンプルの 10 桁という電話番号のルールは、意図的にローカルなものです。実際のサービスで必要となる国際電話番号の要件に置き換えてください。

- 検証されるのは、選択中の連絡先フィールドだけです。

- 選択肢を変更すると、以前のレビュー結果が消去されます。

- リマインダーを設定したとは表示しません。

## B.C. デザインシステムのコンポーネント例

### main.jsx — 動作するサンプル一式

連絡方法を選び、内容を確認します。以下のソースは React の完全なエントリで、すべての状態管理と検証を含みます。

```
import React, { useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import {
  Button,
  Radio,
  RadioGroup,
  TextField,
  Checkbox,
} from "@bcgov/design-system-react-components";
import "@bcgov/bc-sans/css/BC_Sans.css";
import "./bc.css";
function App() {
  const [method, setMethod] = useState("email"),
    [email, setEmail] = useState(""),
    [phone, setPhone] = useState(""),
    [consent, setConsent] = useState(false),
    [submitted, setSubmitted] = useState(false),
    [result, setResult] = useState("");
  const panel = useRef(null);
  const invalidEmail = !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email),
    invalidPhone = phone.replace(/\D/g, "").length < 10;
  function change(fn, value) {
    fn(value);
    setResult("");
    setSubmitted(false);
  }
  function review(e) {
    e.preventDefault();
    setSubmitted(true);
    if ((method === "email" ? invalidEmail : invalidPhone) || !consent) {
      requestAnimationFrame(() =>
        panel.current
          .querySelector(
            '[aria-invalid="true"] input,input[aria-invalid="true"],input[type=checkbox]:not(:checked)',
          )
          ?.focus(),
      );
      return;
    }
    setResult(
      `Local preference ready: ${method === "email" ? "Email to " + email : "Phone call to " + phone}. No reminder has been scheduled.`,
    );
  }
  return (
    <main>
      <header>
        <div className="eyebrow">
          SERVICE REMINDER / ORIGINAL APPLICATION STUDY
        </div>
        <h1>Choose how to hear from us</h1>
        <p>
          Set a sample reminder preference. Use fictional contact details in
          this local example.
        </p>
      </header>
      <div className="columns">
        <form onSubmit={review} noValidate ref={panel}>
          <RadioGroup
            label="Contact method"
            value={method}
            onChange={(v) => change(setMethod, v)}
            description="Choose one way to receive a reminder."
          >
            <Radio value="email">Email</Radio>
            <Radio value="phone">Phone call</Radio>
          </RadioGroup>
          <div className="field">
            {method === "email" ? (
              <TextField
                label="Email address"
                type="email"
                value={email}
                onChange={(v) => change(setEmail, v)}
                isRequired
                isInvalid={submitted && invalidEmail}
                errorMessage="Enter an email address in the format name@example.com."
                description="Use a sample address, such as alex@example.com."
              />
            ) : (
              <TextField
                label="Phone number"
                type="tel"
                value={phone}
                onChange={(v) => change(setPhone, v)}
                isRequired
                isInvalid={submitted && invalidPhone}
                errorMessage="Enter a phone number with at least 10 digits."
                description="Sample validation only; a real service needs a jurisdiction-aware phone rule."
              />
            )}
          </div>
          <div className="field">
            <Checkbox
              isSelected={consent}
              onChange={(v) => change(setConsent, v)}
              isInvalid={submitted && !consent}
            >
              I agree to use these details for this sample reminder
            </Checkbox>
            {submitted && !consent && (
              <p className="error" role="alert">
                Confirm the reminder preference before continuing.
              </p>
            )}
          </div>
          <Button type="submit" variant="primary">
            Review preference
          </Button>
          <p className="result" role="status">
            {result}
          </p>
        </form>
        <aside>
          <div className="status-mark" aria-hidden="true">
            i
          </div>
          <h2>What happens next</h2>
          <ol>
            <li>Choose a contact method.</li>
            <li>Review the sample details.</li>
            <li>Connect a real notification service before scheduling.</li>
          </ol>
          <p>
            This example keeps both fields while switching methods, but only
            reviews the selected method.
          </p>
          <details>
            <summary>About this specimen</summary>
            <p>
              Native B.C. React Aria components with BC Sans. The form is
              original and is not an official government service.
            </p>
          </details>
        </aside>
      </div>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);
```

コードリファレンス

- Vite React プロジェクトを作成し、<div id="root"></div> を残したまま、これを src/main.jsx として読み込みます。

### bc.css — オリジナルのレスポンシブ構成

ネイティブコンポーネントを基にしたアプリケーションレイアウト。

```
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  font:
    16px/1.5 "BC Sans",
    sans-serif;
  color: var(--typography-color-primary, #2d2d2d);
  background: white;
}
main {
  padding: 32px;
}
header {
  border-top: 6px solid #fcba19;
  border-bottom: 1px solid #d8d8d8;
  padding: 24px 0;
  margin-bottom: 32px;
}
.eyebrow {
  font-size: 13px;
  color: #474543;
}
h1 {
  font-size: 32px;
  line-height: 1.25;
  margin: 8px 0 16px;
}
h2 {
  font-size: 24px;
  margin: 0 0 16px;
}
p {
  margin: 8px 0 16px;
}
.columns {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 48px;
}
form {
  max-width: 620px;
}
.field {
  margin: 24px 0;
}
aside {
  padding: 24px;
  background: #f1f8fe;
  border-left: 4px solid #1a5a96;
  align-self: start;
}
.status-mark {
  background: #1a5a96;
  color: white;
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  font-weight: bold;
  margin-bottom: 16px;
}
ol {
  padding-left: 24px;
}
li {
  padding-left: 4px;
  margin: 12px 0;
}
.error {
  color: #ce3e39;
  font-size: 14px;
}
.result {
  margin-top: 24px;
  color: #24613b;
}
summary {
  cursor: pointer;
  text-decoration: underline;
  color: #1a5a96;
}
details {
  margin-top: 24px;
}
details p {
  font-size: 14px;
}
@media (max-width: 767px) {
  main {
    padding: 16px;
  }
  .columns {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  h1 {
    font-size: 28px;
  }
  aside {
    padding: 16px;
  }
}
```

コードリファレンス

- main.jsx と同じ場所に保存します。ライブラリのトークンリファレンスとは異なる、カスタムの構成ルールです。

## B.C. デザインシステム エージェントのセットアップ

### 実装の出発点

バージョンを固定したネイティブのサンプルをバンドルし、ローカルのブラウザーで動作を確認しました。このサンプルでは、アプリケーションのローカルな状態だけを使用します。

```
npm create vite@latest bc-reminder -- --template react
cd bc-reminder
npm install
npm install @bcgov/design-system-react-components@0.8.1 @bcgov/design-tokens@5.0.0 @bcgov/bc-sans@2.1.2
# Replace src/main.jsx and add src/bc.css using the complete examples.
npm run dev
```

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

```
B.C. React のコンポーネント 0.8.1 と BC Sans 2.1.2 を使って、リマインダーフォームを作成します。条件付き検証、入力値の保持、表示されるエラー、古い結果の消去を維持してください。最新のトークン名と、正しくスペースを入れたフォントファミリーを使います。実際の通知契約が整うまでは、この例をローカルにとどめてください。
```

## B.C. デザインシステム 出典と対象範囲

現在公開されている B.C. React ライブラリを使った OpenDesign アプリケーションの検討例です。これは独自に作成したローカルフォームであり、公式の行政サービスではありません。架空の連絡先情報を使用してください。

- 現在のコンポーネントソース React Ariaライブラリとパッケージの境界。

- デザイントークン セマンティックトークンのモデルと現在の値。

- タイポグラフィ BC Sansの基礎と使用方法。

- BC Sansのソース 公開フォントファミリーと正しいCSSエントリーポイント。

## B.C. デザインシステム 関連リソース

### Canada.ca デザインシステム

GC Design System のタイポグラフィ、セマンティックトークン、ネイティブWebコンポーネントを、開閉表示と空の状態の動作を備えた、検索可能な準備ガイドでご覧ください。

### CFPB デザインシステム

CFPBの編集向けグリッド、現行のタイポグラフィ、ネイティブの展開パネルを、動作する読書ワークシート、検証済みのパッケージAPI、明確なブランド利用上の境界とともに実装します。

### CMS デザインシステム

バージョン管理されたテーマ変数、実際のReviewコンポーネントAPI、そしてユーザーの回答とフォーカスを保持する編集・レビューの一連のフローを備えたCMS Coreを実装します。


- [実装リファレンス](https://github.com/bcgov/design-system/)
- [ソース](https://www2.gov.bc.ca/gov/content/digital/design-system/foundations/design-tokens)
- [コードリファレンス](https://github.com/bcgov/design-system/)
- [現在のコンポーネントソース React Ariaライブラリとパッケージの境界。](https://github.com/bcgov/design-system/)
- [デザイントークン セマンティックトークンのモデルと現在の値。](https://www2.gov.bc.ca/gov/content/digital/design-system/foundations/design-tokens)
- [タイポグラフィ BC Sansの基礎と使用方法。](https://www2.gov.bc.ca/gov/content/digital/design-system/foundations/typography)
- [BC Sansのソース 公開フォントファミリーと正しいCSSエントリーポイント。](https://github.com/bcgov/bc-sans)
