# Sistema de design ServiceTitan Anvil

## Prévia da interface do sistema de design ServiceTitan Anvil

Alterne entre os modos claro e escuro, selecione a equipe disponível e revise um plano local sincronizado.

## Referência de design do sistema de design ServiceTitan Anvil

Exportações do tema principal de @servicetitan/hammer-token 3.5.0, com a documentação de temas do Anvil2.

### Pares semânticos para os modos claro e escuro

| Nome / Regra | Valor / Configuração | Uso |
| --- | --- | --- |
| BackgroundColorDefault | light #ffffff / dark #1a1a1a | Superfície principal do aplicativo. |
| BackgroundColorDefaultHover | light #f9f9f9 / dark #292929 | Superfície ao passar o cursor. |
| BackgroundColorPrimary | light #0265dc / dark #70b1ff | Preenchimento da ação principal. |
| BackgroundColorPrimaryHover | light #1d4ca3 / dark #9ecaff | Função nativa de estado de hover primário. |
| BackgroundColorPrimaryFaint | light #fafcff / dark #000b19 | Superfície selecionada discreta. |
| ForegroundColorSubdued | light #707070 / dark #c4c4c4 | Texto de apoio. |
| ForegroundColorOnPrimary | light #ffffff / dark #1a1a1a | Texto combinado com preenchimento primário. |
| ForegroundColorPrimary | light #0265dc / dark #70b1ff | Primeiro plano interativo. |
| BorderColorSubdued | light #e6e6e6 / dark #404040 | Limites com pouca ênfase. |
| BorderColorPrimary | light #0265dc / dark #9ecaff | Limite interativo. |
| StatusColorInfo | light #0265dc / dark #70b1ff | Estado informativo. |
| StatusColorDanger | light #d62100 / dark #ff5b3d | Atenção imediata. |
| StatusColorSuccess | light #077e50 / dark #0bd085 | Revisão local concluída. |
| StatusColorWarning | light #ffbe00 / dark #ffe278 | Alerta não crítico. |
### Geometria primitiva e valores responsivos

| Nome / Regra | Valor / Configuração | Uso |
| --- | --- | --- |
| BreakpointSm | 640px | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| BreakpointMd | 768px | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| BreakpointLg | 1024px | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| BreakpointXl | 1280px | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| BreakpointXxl | 1536px | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| DurationDefault | 200ms | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| DurationInstant | 0ms | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| DurationFast | 100ms | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| DurationSlow | 300ms | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius0 | 0rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius1 | 0.1875rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius2 | 0.375rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius3 | 0.5625rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius4 | 0.75rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius5 | 0.9375rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius6 | 1.125rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius7 | 1.3125rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
| Radius8 | 1.5rem | Primitivo publicado; as funções semânticas e os aliases de componentes determinam as funções efetivamente aplicadas. |
### Contrato de substituição do ThemeProvider

| Nome / Regra | Valor / Configuração | Uso |
| --- | --- | --- |
| theme.semantic | semantic token overrides | Altere uma função, como BackgroundColorPrimary. |
| theme.component | component token overrides | Restrinja uma alteração à função de um componente, como ButtonPrimaryBackgroundColor. |
| value | default/light token value | Defina o valor para o modo claro. |
| extensions.appearance.dark.value | dark appearance value | Especifique o valor correspondente para o modo escuro. |
| CSS output | --a2-<kebab-case-name> | O ThemeProvider serializa a chave do token em uma variável CSS. |
| Primitive cascade | resolved at build time | Substituir um primitivo em tempo de execução não recalcula os aliases semânticos. |
## Guia completo do sistema de design ServiceTitan Anvil

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

## Arquitetura de tokens em três camadas do sistema de design ServiceTitan Anvil

### Mantenha os primitivos abaixo das funções semânticas

> O Anvil2 separa primitivos brutos, funções semânticas e aliases específicos de componentes. Em geral, um produto deve escolher a função que descreve o significado na interface, em vez de copiar um azul primitivo para cada controle. A tabela de referência inclui os valores exportados exatos e seus equivalentes para o modo escuro, permitindo revisar a mudança de tema como um par.

### Não espere que os aliases sejam recalculados em tempo de execução

O guia oficial de temas informa que as referências a primitivos são resolvidas durante a compilação. Alterar um primitivo por meio de um provedor em tempo de execução não regenera automaticamente a camada semântica. Para mudar as cores do aplicativo, substitua a função semântica relevante; para alterar um componente, use a camada de componentes. Isso evita um tema parcialmente alterado, que deixaria controles relacionados inconsistentes.

## Modo de aparência claro e escuro do sistema de design ServiceTitan Anvil

### Altere em conjunto o primeiro plano e o plano de fundo

A ação primária usa BackgroundColorPrimary com ForegroundColorOnPrimary. No modo claro, essa combinação usa azul com texto branco; no modo escuro, usa um azul mais claro com um rótulo escuro. Alterar apenas o preenchimento criaria um par incoerente. O estudo completo de HTML usa light-dark() com um seletor color-scheme para demonstrar esses valores, sem afirmar que é o ThemeProvider.

### Use cores de estado com significados descritos

O Anvil2 associa significados de estado a famílias de cores. A revisão local usa uma função de sucesso, mas ainda informa exatamente o que aconteceu. O técnico indisponível é identificado por texto e tem a opção de rádio desabilitada. Nenhuma tonalidade verde sugere que uma visita de serviço foi despachada; o exemplo nunca se conecta a um backend de despacho.

## Atribuição de serviço e estados no sistema de design ServiceTitan Anvil

### Faça com que a disponibilidade determine a próxima escolha

Ao selecionar um técnico, as opções de horário são substituídas pela disponibilidade fictícia dessa pessoa. A pessoa indisponível continua visível, mas não pode ser selecionada. Como há uma dependência entre dois controles, alterar o primeiro deve redefinir o segundo para um valor válido, em vez de manter um horário que não corresponde à disponibilidade da pessoa escolhida.

### Separe o planejamento da execução

A revisão da atribuição registra um plano local e informa explicitamente que nenhuma visita foi despachada. Um fluxo de produção exigiria verificações de permissão, uma resposta de agenda atualizada e tratamento de conflitos antes da confirmação. O exemplo mantém esse limite visível e, ainda assim, oferece uma interação completa que pode ser testada e adaptada.

## Densidade operacional e legibilidade no sistema de design ServiceTitan Anvil

### Mantenha o contexto do trabalho próximo da seleção

Um resumo compacto do trabalho apresenta a tarefa, a duração, a área e a prioridade. As opções de técnico formam uma lista vertical legível, e a visita proposta aparece em um painel separado. A interface usa limites neutros e cores de destaque moderadas para que a seleção e a ação principal continuem fáceis de identificar. As barras da agenda estão identificadas como ilustrativas; o seletor de horário é a fonte oficial.

### Preserve a ordem de leitura em dispositivos móveis

Abaixo de 768px, a visita proposta aparece depois do trabalho e da lista de técnicos. Os controles mantêm um tamanho adequado e os rótulos quebram linhas naturalmente. A prévia não usa painéis com altura de janela de visualização fixa, evitando criar grandes áreas vazias abaixo de conteúdos curtos. A ordem em uma única coluna segue a mesma sequência de decisão do layout mais amplo.

## Integração nativa e alternativa completa de HTML para o sistema de design ServiceTitan Anvil

### Use a estrutura documentada do provedor

O ThemeProvider do Anvil2 aceita substituições de tokens semânticos e de componentes, com extensões para valores e aparência escura. O guia inclui abaixo um exemplo completo do provedor, com fonte na documentação pública. Trata-se de uma referência de integração nativa, distinta do exemplo independente de HTML executado localmente.

### Evite alegar um runtime de pacote não verificado

Esta página apresenta uma implementação funcional em HTML e dados de tokens verificados. O exemplo do provedor nativo é uma referência de integração separada, não o runtime exibido na prévia. Ao adotar componentes React, instale uma versão compatível do Anvil2, inclua os estilos necessários e verifique as APIs dos componentes antes de substituir os controles nativos de HTML.

## Acessibilidade e verificação de estados no sistema de design ServiceTitan Anvil

### Use a semântica nativa dos formulários

Os técnicos são apresentados como opções de rádio nativas com rótulos, o horário de início é um seletor identificado por rótulo e o controle de aparência expõe aria-pressed. A mensagem de revisão é uma região de status. O modelo nativo de teclado do navegador gerencia a seleção das opções de rádio; o estilo de foco visível é independente dos estilos de seleção ou de hover.

### Verifique as alterações após a confirmação

Alterar o técnico ou o horário limpa as mensagens de revisão anteriores. Alternar a aparência mantém o técnico e o horário selecionados, pois uma mudança visual de tema não deve apagar um plano. Os testes devem abranger as duas transições, além da seleção desabilitada e do excesso de conteúdo em telas estreitas, em vez de apenas verificar se é possível clicar em um botão.

## Transferência para agente de IA e implementação do sistema de design ServiceTitan Anvil

### Comece pelo modelo completo de estados

Salve e execute o exemplo completo em HTML para inspecionar o comportamento. Os pares claro/escuro derivados dos tokens aparecem na parte superior do CSS, e os dados de disponibilidade definidos no exemplo estão no script. Uma implementação nativa de React pode manter as mesmas transições de estado e substituir os controles do Anvil2 após verificar sua compatibilidade.

1. Execute o exemplo completo de HTML.

2. Selecione o segundo técnico e confirme que as opções de horário de início mudam.

3. Revise o plano, depois altere o horário e confirme que as mensagens são removidas.

4. Alterne a aparência e confirme que a seleção atual é mantida.

### Especifique o que exige dados reais

Peça ao agente de IA que mantenha a lista de horários dependente do técnico, o membro da equipe indisponível desabilitado, a invalidação da revisão e o comportamento da aparência. Substitua o trabalho e a equipe fictícios somente quando houver um contrato de dados real. Não transforme a revisão local em uma alegação de sucesso apenas mudando o rótulo do botão.

- Verifique a disponibilidade antes de realizar um despacho.

- Mantenha separadas as substituições semânticas e as de componentes.

- Teste os pares de primeiro plano e plano de fundo nos modos claro e escuro.

## Exemplos de componentes do sistema de design ServiceTitan Anvil

### Exemplo completo de atribuição local

Original em HTML/CSS/JavaScript, com aparências derivadas de tokens e estado de formulário dependente.

```
<!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>
```

Referência de código

- Salve como index.html; navegadores modernos oferecem suporte a light-dark(). Este não é o runtime nativo do Anvil2.

### Referência de integração do ThemeProvider

Estrutura documentada de substituição semântica em uma entrada completa de React. Valide-a com a versão instalada do 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 />);
```

Referência de código

- Esta referência do provedor foi conferida com a documentação oficial; o exemplo em execução acima é independente de HTML.

## Configuração do agente de IA para o sistema de design ServiceTitan Anvil

### Ponto de partida para implementação

O exemplo executado não requer um pacote Anvil2. O exemplo separado do ThemeProvider exige uma instalação nativa compatível.

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

### Um prompt para seu projeto

```
Crie uma interface de atribuição de serviços usando funções semânticas do Anvil2. Mantenha os pares de primeiro plano para os modos claro e escuro, as opções de horário dependentes do técnico, a equipe indisponível desabilitada e a invalidação da revisão do exemplo completo. Escolha explicitamente entre o HTML original e uma instalação verificada de React do Anvil2. Nunca afirme que houve um despacho sem uma resposta do backend.
```

## Fontes e escopo do sistema de design ServiceTitan Anvil

Um guia de OpenDesign para o Anvil2 da ServiceTitan. Os valores dos tokens foram extraídos do Hammer 3.5.0 público. O exemplo em execução é HTML original, não um runtime de React do Anvil2; todos os técnicos e dados de disponibilidade são fictícios.

- Tematização Camadas de tokens, substituições e valores de aparência.

- Cores Funções de estado e orientações sobre cores de interação.

- Espaçamento Escala de espaçamento e integração de utilitários.

- Dimensões Fundamentos de dimensionamento.

- Arquitetura da biblioteca Limites entre os pacotes e as bibliotecas do Anvil2.

## Recursos relacionados ao sistema de design ServiceTitan Anvil

### Siemens iX

Inspecione eventos industriais com um vocabulário explícito de níveis de gravidade, funções de cor adaptadas ao tema e o iX Event List API. Este guia cria um caderno local de equipamentos sem confundir um registro revisado com um alarme de máquina resolvido.

### Sprout Social Seeds

Inspecione as cores públicas, o espaçamento, a tipografia de produto e os tokens de borda reais do Seeds em uma fila completa de revisão editorial, com seleção múltipla, estados vazios após filtragem e opção de desfazer.

### SumUp Circuit

Um guia do Circuit com tokens semânticos exatos, propriedades nativas de validação, um editor completo de itens para lojistas e uma prévia ilustrada do lado do cliente.


- [Referência de implementação](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [Fonte](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [Fonte](https://anvil.servicetitan.com/docs/web/foundations/sizing)
- [Referência de código](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [Tematização Camadas de tokens, substituições e valores de aparência.](https://anvil.servicetitan.com/docs/web/foundations/theming)
- [Cores Funções de estado e orientações sobre cores de interação.](https://anvil.servicetitan.com/docs/web/foundations/colors)
- [Espaçamento Escala de espaçamento e integração de utilitários.](https://anvil.servicetitan.com/docs/web/foundations/spacing)
- [Dimensões Fundamentos de dimensionamento.](https://anvil.servicetitan.com/docs/web/foundations/sizing)
- [Arquitetura da biblioteca Limites entre os pacotes e as bibliotecas do Anvil2.](https://anvil.servicetitan.com/docs/library-architecture)
