# 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열 구성은 이 예제를 위해 별도로 만들었습니다. 모바일 레이아웃에서는 열을 하나로 합치되 양식 레이블을 축소하거나 설명 텍스트를 툴팁으로 바꾸지 않습니다.

## B.C. 디자인 시스템 조건부 필드와 값 유지

### 선택한 연락 방법만 유효성을 검사하세요

네이티브 RadioGroup으로 이메일 주소 또는 전화번호 TextField의 표시 여부를 제어합니다. 연락 방법을 바꿔도 두 입력값은 React 상태에 그대로 유지되지만, 검토 시에는 선택한 필드만 유효성 검사에 포함됩니다. 이렇게 하면 입력값은 유지하면서 현재 작업에 표시되지 않는 필드가 작업을 막지 않도록 할 수 있습니다.

### 유용한 오류 메시지를 표시하세요

이메일 필드는 기본적인 주소 형식을 검사하고, 전화번호 예제는 숫자가 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의 연결 관계를 제공합니다. 애플리케이션에서도 의미 있는 레이블, 명확한 그룹 설명, 이해하기 쉬운 유효성 검사 문구를 제공해야 합니다. 테스트할 때는 화면에 표시된 라디오 레이블을 클릭하고 키보드로 조작해야 합니다. 내부의 시각적으로 숨겨진 입력 요소는 화면에서 직접 조작하는 대상이 아닙니다.

### 보조 안내와 양식을 분리하세요

옆에 배치된 안내 상자는 로컬 작업 흐름을 설명하고, 구현 관련 정보를 담은 네이티브 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가 네이티브 입력 요소를 시각적으로 숨기더라도 화면에 보이는 레이블은 계속 조작 대상으로 유지됩니다.

연락 방법이 바뀌어도 두 입력값은 모두 유지하되, 이전 검토 결과를 지우고 선택한 방법만 검증합니다. 제출 후에는 오류가 있는 첫 번째 표시 컨트롤로 포커스를 이동합니다. 이렇게 하면 이메일 주소를 잃거나 화면에 보이지 않는 전화번호 입력란 때문에 진행이 막히지 않아, 연락 방법을 비교해 볼 수 있습니다. 예시의 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 디자인 시스템의 타이포그래피, 시맨틱 토큰, 기본 웹 컴포넌트를 살펴보세요. 공개 및 빈 상태 동작을 포함한 검색 가능한 완성형 준비 가이드입니다.

### CFPB 디자인 시스템

CFPB의 편집용 그리드, 현재 타이포그래피와 기본 Expandables를 구현합니다. 작동하는 읽기 워크시트와 검증된 패키지 API, 명확한 아이덴티티 경계를 제공합니다.

### CMS 디자인 시스템

버전이 지정된 테마 변수, 실제 Review 구성 요소 API, 사용자 답변과 포커스를 유지하는 편집 및 검토 흐름을 구현하세요.


- [구현 레퍼런스](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)
