# ServiceTitan Anvil 디자인 시스템

## ServiceTitan Anvil 디자인 시스템 인터페이스 미리보기

밝은 모드와 어두운 모드를 전환하고, 사용 가능한 담당자를 선택해 동기화된 로컬 계획을 검토하세요.

## ServiceTitan Anvil 디자인 시스템 디자인 참조

@servicetitan/hammer-token 3.5.0의 core 테마 내보내기와 Anvil2 테마 지정 문서를 참조합니다.

### 시맨틱 라이트·다크 쌍

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| BackgroundColorDefault | light #ffffff / dark #1a1a1a | 주요 애플리케이션 표면. |
| BackgroundColorDefaultHover | light #f9f9f9 / dark #292929 | 호버 표면. |
| BackgroundColorPrimary | light #0265dc / dark #70b1ff | 기본 동작 채우기색. |
| BackgroundColorPrimaryHover | light #1d4ca3 / dark #9ecaff | 기본 상호작용 호버 역할입니다. |
| BackgroundColorPrimaryFaint | light #fafcff / dark #000b19 | 절제된 선택 표면입니다. |
| ForegroundColorSubdued | light #707070 / dark #c4c4c4 | 보조 텍스트. |
| ForegroundColorOnPrimary | light #ffffff / dark #1a1a1a | 기본 채우기 색상과 짝을 이루는 텍스트입니다. |
| ForegroundColorPrimary | light #0265dc / dark #70b1ff | 인터랙티브 전경색. |
| BorderColorSubdued | light #e6e6e6 / dark #404040 | 낮은 강조도의 경계선입니다. |
| BorderColorPrimary | light #0265dc / dark #9ecaff | 인터랙티브 경계선입니다. |
| StatusColorInfo | light #0265dc / dark #70b1ff | 정보 상태입니다. |
| StatusColorDanger | light #d62100 / dark #ff5b3d | 즉각적인 주의가 필요합니다. |
| StatusColorSuccess | light #077e50 / dark #0bd085 | 로컬 검토를 완료했습니다. |
| StatusColorWarning | light #ffbe00 / dark #ffe278 | 중요도가 낮은 주의 사항입니다. |
### 원시 기하 값 및 반응형 값

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| BreakpointSm | 640px | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| BreakpointMd | 768px | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| BreakpointLg | 1024px | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| BreakpointXl | 1280px | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| BreakpointXxl | 1536px | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| DurationDefault | 200ms | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| DurationInstant | 0ms | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| DurationFast | 100ms | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| DurationSlow | 300ms | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius0 | 0rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius1 | 0.1875rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius2 | 0.375rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius3 | 0.5625rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius4 | 0.75rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius5 | 0.9375rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius6 | 1.125rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius7 | 1.3125rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
| Radius8 | 1.5rem | 공개된 원시 토큰입니다. 실제 적용 역할은 의미별/컴포넌트별 별칭으로 결정됩니다. |
### ThemeProvider 재정의 계약

| 이름 / 규칙 | 값 / 구성 | 용도 |
| --- | --- | --- |
| theme.semantic | semantic token overrides | BackgroundColorPrimary와 같은 역할을 변경합니다. |
| theme.component | component token overrides | ButtonPrimaryBackgroundColor와 같은 컴포넌트 역할로 변경 범위를 좁힙니다. |
| value | default/light token value | 라이트 모양 값을 지정합니다. |
| extensions.appearance.dark.value | dark appearance value | 이에 대응하는 다크 모양을 지정합니다. |
| CSS output | --a2-<kebab-case-name> | ThemeProvider는 토큰 키를 CSS 변수로 직렬화합니다. |
| Primitive cascade | resolved at build time | 런타임에 원시 토큰을 재정의해도 의미별 별칭은 다시 계산되지 않습니다. |
## ServiceTitan Anvil 디자인 시스템 전체 가이드

실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.

완전한 안내와 구현 시작점, 소스 링크.

## ServiceTitan Anvil 디자인 시스템 3계층 토큰 아키텍처

### 원시 토큰은 의미별 역할보다 하위 계층에 둡니다

> Anvil2는 원시 토큰, 의미별 역할, 컴포넌트별 별칭을 분리합니다. 제품에서는 일반적으로 원시 파란색을 모든 컨트롤에 복사하기보다 인터페이스의 의미를 설명하는 역할을 선택해야 합니다. 참조 표에는 내보내는 값과 다크 모드 대응 값이 정확히 나와 있으므로, 테마 변경을 쌍으로 검토할 수 있습니다.

### 런타임에 별칭이 다시 계산될 것이라고 기대하지 마세요

공식 테마 적용 가이드에 따르면 원시 토큰 참조는 빌드 중에 해석됩니다. 런타임 제공자를 통해 원시 토큰을 변경해도 의미별 계층이 자동으로 다시 생성되지는 않습니다. 애플리케이션의 색을 변경하려면 관련 의미별 역할을 재정의하고, 단일 컴포넌트를 변경하려면 컴포넌트 계층을 사용하세요. 이렇게 하면 관련 컨트롤이 일관되지 않은 상태로 남는 부분적인 테마 변경을 방지할 수 있습니다.

## ServiceTitan Anvil 디자인 시스템의 라이트 및 다크 모양

### 전경색과 배경색을 함께 변경하세요

기본 동작에는 BackgroundColorPrimary와 ForegroundColorOnPrimary가 사용됩니다. 라이트 모드에서는 파란색 배경에 흰색 텍스트를, 다크 모드에서는 더 밝은 파란색 배경에 어두운 라벨을 사용합니다. 채우기 색만 전환하면 조화롭지 않은 색 조합이 됩니다. 전체 HTML 예제에서는 ThemeProvider라고 주장하지 않으면서 color-scheme 전환과 함께 light-dark()를 사용해 이 값을 보여 줍니다.

### 의미를 문구로 명시한 상태 색상을 사용하세요

Anvil2는 색상 계열에 상태의 의미를 부여합니다. 로컬 검토에서는 성공 역할을 사용하지만, 어떤 일이 있었는지 문구로 정확히 설명합니다. 담당할 수 없는 기술자는 텍스트로 표시하고 라디오 버튼을 비활성화합니다. 서비스 방문이 배정되었다는 의미로 초록색을 사용하지 않습니다. 이 예제는 배정 백엔드에 연결되지 않습니다.

## ServiceTitan Anvil 디자인 시스템의 서비스 배정 및 상태

### 가능 여부에 따라 다음 선택지를 제한하세요

기술자를 선택하면 시작 시간 선택지가 해당 기술자의 가상 일정으로 바뀝니다. 담당할 수 없는 기술자도 계속 표시되지만 선택할 수는 없습니다. 두 컨트롤이 서로 종속되어 있으므로 첫 번째 선택을 변경하면 두 번째 선택도 유효한 값으로 초기화해야 합니다. 다른 사람에게 해당하는 시간을 그대로 유지해서는 안 됩니다.

### 계획과 실행을 구분하세요

배정 검토는 로컬 계획을 기록하고 방문이 배정되지 않았음을 명시적으로 안내합니다. 실제 운영 워크플로에서는 확정 전에 권한 확인, 최신 일정 조회, 충돌 처리가 필요합니다. 이 예제는 그 경계를 분명히 유지하면서 직접 시험하고 적용할 수 있는 완전한 상호작용을 제공합니다.

## ServiceTitan Anvil 디자인 시스템의 정보 밀도 및 가독성

### 작업 맥락을 선택 항목 가까이에 두세요

간결한 작업 요약에는 작업, 소요 시간, 구역, 우선순위가 포함됩니다. 기술자 선택지는 읽기 쉬운 세로 목록으로 표시하고, 예정 방문은 별도 패널에 배치합니다. 중립적인 경계선과 절제된 강조색을 사용해 선택 항목과 주요 동작을 쉽게 식별할 수 있습니다. 일정 막대에는 예시용이라고 표시하며, 실제 시간은 선택 메뉴를 기준으로 합니다.

### 모바일에서도 읽기 순서를 유지하세요

768px 미만에서는 예정 방문이 작업 및 기술자 목록 뒤에 표시됩니다. 컨트롤은 충분한 크기를 유지하며 라벨은 자연스럽게 줄바꿈됩니다. 미리보기에는 높이가 고정된 뷰포트 패널을 사용하지 않으므로 콘텐츠가 짧을 때 큰 빈 공간이 생기지 않습니다. 단일 열의 순서는 넓은 화면에서와 동일한 의사 결정 순서를 따릅니다.

## ServiceTitan Anvil 디자인 시스템의 네이티브 통합 및 전체 HTML 대안

### 문서에 명시된 제공자 구조를 사용하세요

Anvil2의 ThemeProvider는 value 및 다크 모양 확장 기능과 함께 의미별 토큰 및 컴포넌트 토큰 재정의를 지원합니다. 아래 가이드에는 공개 문서를 출처로 한 완전한 제공자 예제가 포함되어 있습니다. 이는 로컬에서 실행한 독립적인 HTML 예제와 구별되는 네이티브 통합 참고 자료입니다.

### 검증되지 않은 패키지 런타임을 사용한다고 주장하지 마세요

이 페이지에서는 작동하는 HTML 구현과 검증된 토큰 데이터를 제공합니다. 네이티브 제공자 예제는 별도의 통합 참고 자료이며 미리보기에 표시된 런타임이 아닙니다. React 컴포넌트를 도입할 때는 서로 호환되는 Anvil2 버전을 설치하고 필요한 스타일을 포함한 뒤, 네이티브 HTML 컨트롤을 교체하기 전에 컴포넌트 API를 검증하세요.

## ServiceTitan Anvil 디자인 시스템의 접근성 및 상태 검증

### 네이티브 폼 의미 구조를 사용하세요

기술자 선택에는 라벨이 연결된 네이티브 라디오 버튼을, 시작 시간에는 라벨이 연결된 선택 메뉴를 사용하며, 모양 전환 컨트롤에는 aria-pressed를 제공합니다. 검토 메시지는 상태 영역입니다. 라디오 버튼 선택은 브라우저의 기본 키보드 동작으로 처리하며, 표시되는 포커스 스타일은 선택 또는 호버 스타일과 별도로 유지됩니다.

### 확인 후 변경 사항을 점검하세요

기술자나 시간을 변경하면 이전 검토 피드백을 지웁니다. 모양을 전환해도 선택한 기술자와 시간은 유지합니다. 시각적 테마 변경이 계획을 지워서는 안 되기 때문입니다. 버튼을 클릭할 수 있는지만 확인하지 말고 두 가지 전환과 비활성화된 선택, 좁은 화면에서의 오버플로도 테스트해야 합니다.

## ServiceTitan Anvil 디자인 시스템의 AI 에이전트 핸드오프 및 구현

### 전체 상태 모델부터 살펴보세요

전체 HTML 예제를 저장하고 실행해 동작을 확인하세요. 토큰에서 가져온 라이트/다크 색상 쌍은 CSS 상단에 표시되며, 직접 작성한 가능 시간 데이터는 스크립트에서 확인할 수 있습니다. 네이티브 React 구현에서도 검증된 Anvil2 컨트롤로 바꾸면서 동일한 상태 전환을 유지할 수 있습니다.

1. 전체 HTML 예제를 실행하세요.

2. 두 번째 기술자를 선택하고 시작 시간 선택지가 바뀌는지 확인하세요.

3. 계획을 검토한 다음 시간을 변경하고 피드백이 사라지는지 확인하세요.

4. 화면 모드를 전환하고 현재 선택이 유지되는지 확인하세요.

### 실제 데이터가 필요한 부분 명시

AI 에이전트에게 담당자에 따라 달라지는 시간 목록, 비활성화된 직원, 검토 상태 초기화, 화면 모드 동작을 유지하도록 요청하세요. 실제 데이터 계약을 사용할 수 있을 때만 가상의 작업과 직원을 실제 데이터로 교체하세요. 버튼 레이블만 변경해 로컬 검토 결과를 성공으로 표시하지 마세요.

- 실제 배정을 진행하기 전에 예약 가능 여부를 확인하세요.

- 시맨틱 재정의와 컴포넌트 재정의를 분리하세요.

- 라이트 모드와 다크 모드 모두에서 전경색과 배경색 조합을 테스트하세요.

## ServiceTitan Anvil 디자인 시스템 컴포넌트 예시

### 완성된 로컬 배정 예제

토큰 기반 화면 모드와 종속된 양식 상태를 적용한 기본 HTML/CSS/JavaScript 예시입니다.

```
<!doctype html>
<html lang="en">
  <meta charset="utf-8" /><meta
    name="viewport"
    content="width=device-width,initial-scale=1"
  /><title>Dispatch assignment study</title
  ><style>
    :root {
      color-scheme: light;
      --surface: light-dark(#fff, #1a1a1a);
      --hover: light-dark(#f9f9f9, #292929);
      --text: light-dark(#040404, #fff);
      --muted: light-dark(#707070, #c4c4c4);
      --line: light-dark(#e6e6e6, #404040);
      --action: light-dark(#0265dc, #70b1ff);
      --on-action: light-dark(#fff, #1a1a1a);
      --faint: light-dark(#fafcff, #000b19);
      --success: light-dark(#077e50, #0bd085);
    }
    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
      padding: 24px;
      background: var(--surface);
      color: var(--text);
      font:
        16px/1.5 system-ui,
        sans-serif;
    }
    h1 {
      font-size: 28px;
      margin: 8px 0;
    }
    h2 {
      font-size: 20px;
      margin: 0 0 16px;
    }
    p {
      margin: 8px 0 16px;
    }
    .small {
      font-size: 13px;
      color: var(--muted);
    }
    header {
      display: flex;
      justify-content: space-between;
      gap: 24px;
      border-bottom: 1px solid var(--line);
      padding-bottom: 24px;
    }
    button,
    select {
      font: inherit;
      color: inherit;
      background: var(--surface);
      border: 1px solid var(--line);
      border-radius: 4px;
      padding: 10px 16px;
      min-height: 44px;
    }
    button {
      cursor: pointer;
    }
    button:hover {
      background: var(--hover);
    }
    button:focus-visible,
    select:focus-visible,
    input:focus-visible {
      outline: 3px solid var(--action);
      outline-offset: 3px;
    }
    main {
      display: grid;
      grid-template-columns: 1.4fr 1fr;
      gap: 24px;
      margin-top: 24px;
    }
    .board {
      border: 1px solid var(--line);
      border-radius: 8px;
      padding: 24px;
    }
    .job {
      padding: 16px;
      background: var(--faint);
      border-left: 4px solid var(--action);
      margin-bottom: 24px;
    }
    .job strong {
      display: block;
    }
    .people {
      display: grid;
      gap: 12px;
    }
    .person {
      display: grid;
      grid-template-columns: 24px 1fr auto;
      gap: 12px;
      padding: 16px;
      border: 1px solid var(--line);
      border-radius: 4px;
      align-items: center;
    }
    .person:has(:checked) {
      border-color: var(--action);
      background: var(--faint);
    }
    input {
      accent-color: var(--action);
      width: 18px;
      height: 18px;
    }
    .person small {
      display: block;
      color: var(--muted);
    }
    .person:has(:disabled) {
      background: var(--hover);
    }
    .timeline {
      display: flex;
      gap: 4px;
      margin: 20px 0;
    }
    .timeline span {
      height: 40px;
      flex: 1;
      background: var(--line);
      border-radius: 4px;
    }
    .timeline .open {
      background: var(--action);
    }
    .timeline-label {
      display: flex;
      justify-content: space-between;
      font-size: 13px;
      color: var(--muted);
    }
    label[for="time"] {
      display: block;
      margin: 16px 0 8px;
    }
    .primary {
      background: var(--action);
      color: var(--on-action);
      border-color: var(--action);
      margin-top: 24px;
    }
    .primary:hover {
      filter: brightness(0.95);
      background: var(--action);
    }
    #feedback {
      color: var(--success);
      padding-top: 16px;
    }
    footer {
      border-top: 1px solid var(--line);
      padding-top: 16px;
      margin-top: 24px;
      font-size: 13px;
      color: var(--muted);
    }
    @media (max-width: 767px) {
      body {
        padding: 16px;
      }
      main {
        grid-template-columns: 1fr;
      }
      .board {
        padding: 16px;
      }
      header {
        display: block;
      }
      header button {
        margin-top: 8px;
      }
      .person {
        grid-template-columns: 24px 1fr;
      }
      .person > span:last-child {
        grid-column: 2;
      }
    }
  </style>
  <body>
    <header>
      <div>
        <div class="small">SERVICE OPERATIONS / LOCAL PLANNING STUDY</div>
        <h1>Assign a service visit</h1>
        <p>Match a sample job with an available technician.</p>
      </div>
      <div>
        <button id="theme" aria-pressed="false">Dark appearance</button>
      </div>
    </header>
    <main>
      <section class="board">
        <h2>Job and technician</h2>
        <div class="job">
          <strong>Sample job #204 · Heating inspection</strong
          ><span>90 minutes · North district · Routine priority</span>
        </div>
        <div class="people" id="people"></div>
      </section>
      <aside class="board">
        <h2>Proposed visit</h2>
        <p id="technician"></p>
        <label for="time">Available start time</label
        ><select id="time"></select>
        <div class="timeline" aria-hidden="true">
          <span></span><span class="open"></span><span class="open"></span
          ><span></span><span></span><span></span>
        </div>
        <div class="timeline-label">
          <span>08:00</span><span>Illustrative day</span><span>17:00</span>
        </div>
        <p class="small">
          The time list is the source of available choices. The bars are a
          decorative schedule summary.
        </p>
        <button id="assign" class="primary">Review assignment</button>
        <p id="feedback" role="status"></p>
      </aside>
    </main>
    <footer>
      Original HTML using Anvil2 Hammer token 3.5.0 light/dark roles. Fictional
      technicians and schedules; no dispatch service connected.
    </footer>
    <script>
      const staff = [
        {
          id: "alex",
          name: "Alex Morgan",
          skill: "Heating specialist",
          slots: ["09:00", "11:00"],
        },
        {
          id: "sam",
          name: "Sam Rivera",
          skill: "General maintenance",
          slots: ["13:00", "15:00"],
        },
        { id: "lee", name: "Lee Chen", skill: "Unavailable today", slots: [] },
      ];
      let selected = "alex";
      const $ = (id) => document.getElementById(id);
      function update() {
        const p = staff.find((s) => s.id === selected);
        $("technician").textContent = p.name + " · " + p.skill;
        $("time").replaceChildren(...p.slots.map((t) => new Option(t, t)));
        $("feedback").textContent = "";
      }
      $("people").replaceChildren(
        ...staff.map((p) => {
          const l = document.createElement("label");
          l.className = "person";
          const input = document.createElement("input");
          input.type = "radio";
          input.name = "technician";
          input.checked = p.id === selected;
          input.disabled = p.slots.length === 0;
          input.onchange = () => {
            selected = p.id;
            update();
          };
          const text = document.createElement("span");
          text.innerHTML = `<strong>${p.name}</strong><small>${p.skill}</small>`;
          const availability = document.createElement("span");
          availability.textContent = p.slots.length
            ? p.slots.length + " start times"
            : "Unavailable";
          l.append(input, text, availability);
          return l;
        }),
      );
      $("time").onchange = () => {
        $("feedback").textContent = "";
      };
      $("assign").onclick = () => {
        $("feedback").textContent =
          "Local plan: " +
          staff.find((s) => s.id === selected).name +
          " at " +
          $("time").value +
          ". No visit has been dispatched.";
      };
      $("theme").onclick = () => {
        let dark = $("theme").getAttribute("aria-pressed") !== "true";
        $("theme").setAttribute("aria-pressed", dark);
        document.documentElement.style.colorScheme = dark ? "dark" : "light";
      };
      update();
    </script>
  </body>
</html>
```

코드 참조

- index.html로 저장하세요. 최신 브라우저는 light-dark()를 지원합니다. 이는 Anvil2 네이티브 런타임이 아닙니다.

### ThemeProvider 통합 참고 예시

완성된 React 항목에 적용된 시맨틱 재정의 형식입니다. 설치된 Anvil2 버전에서 검증하세요.

```
import React from 'react';
import { createRoot } from 'react-dom/client';
import { ThemeProvider } from '@servicetitan/anvil2';

const theme = {
  semantic: {
    BackgroundColorPrimary: {
      value: '#7c3aed',
      extensions: { appearance: { dark: { value: '#a78bfa' } } },
    },
  },
};

function App() {
  return (
    <ThemeProvider theme={theme}>
      <main>
        <h1>Theme integration check</h1>
        <div style={{ background: 'var(--a2-background-color-primary)', padding: 24 }}>
          <span style={{ color: 'var(--a2-foreground-color-on-primary)' }}>
            Primary role with the provider’s matching foreground role
          </span>
        </div>
      </main>
    </ThemeProvider>
  );
}
createRoot(document.getElementById('root')).render(<App />);
```

코드 참조

- 이 프로바이더 참고 예시는 공식 문서와 대조해 확인했습니다. 위의 실행 가능한 예시는 별도의 독립적인 HTML입니다.

## ServiceTitan Anvil 디자인 시스템 에이전트 설정

### 구현 시작점

실행된 예시에는 Anvil2 패키지가 필요하지 않습니다. 별도의 ThemeProvider 예시에는 호환되는 네이티브 설치가 필요합니다.

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

### 프로젝트를 위한 프롬프트

```
Anvil2 시맨틱 역할을 사용해 서비스 배정 인터페이스를 만드세요. 완성된 예시의 라이트/다크 전경색 조합, 기술자에 따라 달라지는 시간 선택지, 예약할 수 없는 직원의 비활성화, 검토 상태 초기화를 유지하세요. 기본 HTML과 검증된 Anvil2 React 설치 중 하나를 명시적으로 선택하세요. 백엔드 응답 없이 배정이 완료됐다고 표시하지 마세요.
```

## ServiceTitan Anvil 디자인 시스템 출처 및 범위

ServiceTitan Anvil2에 관한 OpenDesign 가이드입니다. 토큰 값은 공개된 Hammer 토큰 3.5.0에서 추출했습니다. 실행 가능한 예시는 Anvil2 React 런타임이 아니라 기본 HTML이며, 모든 기술자와 예약 가능 일정은 가상입니다.

- 테마 설정 토큰 계층, 재정의, 화면 모드 값

- 색상 상태 역할 및 상호작용 색상 가이드

- 간격 간격 척도 및 유틸리티 통합

- 크기 크기 설정의 기초

- 라이브러리 아키텍처 Anvil2 패키지와 라이브러리의 경계

## ServiceTitan Anvil 디자인 시스템 관련 자료

### Siemens iX

명확한 심각도 체계, 테마에 반응하는 색상 역할, iX Event List API를 사용해 산업 현장의 이벤트를 살펴보세요. 이 가이드는 검토가 완료된 기록과 해결된 기계 경보를 혼동하지 않도록 로컬 장비 기록장을 구성합니다.

### Sprout Social Seeds

완성된 편집 검토 대기열에서 Seeds의 실제 공개 색상, 간격, 제품 타이포그래피, 테두리 디자인 토큰을 확인하세요. 여러 항목 선택, 필터 적용 후 빈 상태, 실행 취소도 포함되어 있습니다.

### SumUp Circuit

정확한 시맨틱 토큰, 네이티브 유효성 검사 props, 완성된 판매자 상품 편집기, 고객 측 미리보기 그림을 제공하는 Circuit 가이드입니다.


- [구현 레퍼런스](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [출처](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [출처](https://anvil.servicetitan.com/docs/web/foundations/sizing)
- [코드 참조](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [테마 설정 토큰 계층, 재정의, 화면 모드 값](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [색상 상태 역할 및 상호작용 색상 가이드](https://anvil.servicetitan.com/docs/web/foundations/colors)
- [간격 간격 척도 및 유틸리티 통합](https://anvil.servicetitan.com/docs/web/foundations/spacing)
- [크기 크기 설정의 기초](https://anvil.servicetitan.com/docs/web/foundations/sizing)
- [라이브러리 아키텍처 Anvil2 패키지와 라이브러리의 경계](https://anvil.servicetitan.com/docs/library-architecture)
